pci-driver.c revision c8958177224622411b9979eabb5610e30b06034b
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/pci/pci-driver.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci-dynids.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pci.h"
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Registration of PCI drivers and handling of hot-pluggable devices.
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HOTPLUG
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_probe_dynamic()
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Walk the dynamic ID list looking for a match.
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = -ENODEV;
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *pos;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dynid *dynid;
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&drv->dynids.lock);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each(pos, &drv->dynids.list) {
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dynid = list_entry(pos, struct dynid, node);
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (pci_match_one_device(&dynid->id, pci_dev)) {
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock(&drv->dynids.lock);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			error = drv->probe(pci_dev, &dynid->id);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (error >= 0) {
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_dev->driver = drv;
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return error;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&drv->dynids.lock);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * store_new_id
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds a new dynamic pci device ID to this driver,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and causes the driver to probe for all devices again.
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline ssize_t
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstore_new_id(struct device_driver *driver, const char *buf, size_t count)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dynid *dynid;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bus_type * bus;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *pdrv = to_pci_driver(driver);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		subdevice=PCI_ANY_ID, class=0, class_mask=0;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long driver_data=0;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fields=0;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fields = sscanf(buf, "%x %x %x %x %x %x %lux",
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&vendor, &device, &subvendor, &subdevice,
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&class, &class_mask, &driver_data);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fields < 0)
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid = kmalloc(sizeof(*dynid), GFP_KERNEL);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dynid)
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(dynid, 0, sizeof(*dynid));
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&dynid->node);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.vendor = vendor;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.device = device;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subvendor = subvendor;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subdevice = subdevice;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class = class;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class_mask = class_mask;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.driver_data = pdrv->dynids.use_driver_data ?
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		driver_data : 0UL;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&pdrv->dynids.lock);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add_tail(&pdrv->dynids.list, &dynid->node);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&pdrv->dynids.lock);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bus = get_bus(pdrv->driver.bus);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bus) {
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (get_driver(&pdrv->driver)) {
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			down_write(&bus->subsys.rwsem);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			driver_attach(&pdrv->driver);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up_write(&bus->subsys.rwsem);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_driver(&pdrv->driver);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_bus(bus);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_init_dynids(struct pci_dynids *dynids)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&dynids->lock);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&dynids->list);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_free_dynids(struct pci_driver *drv)
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *pos, *n;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dynid *dynid;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&drv->dynids.lock);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_safe(pos, n, &drv->dynids.list) {
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dynid = list_entry(pos, struct dynid, node);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del(&dynid->node);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(dynid);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&drv->dynids.lock);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_create_newid_file(struct pci_driver *drv)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->probe != NULL)
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = sysfs_create_file(&drv->driver.kobj,
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  &driver_attr_new_id.attr);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *pos;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dynid *dynid;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&pci_drv->dynids.lock);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each(pos, &pci_drv->dynids.list) {
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dynid = list_entry(pos, struct dynid, node);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (pci_match_one_device(&dynid->id, pci_dev)) {
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock(&pci_drv->dynids.lock);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&pci_drv->dynids.lock);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* !CONFIG_HOTPLUG */
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_init_dynids(struct pci_dynids *dynids) {}
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_free_dynids(struct pci_driver *drv) {}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_create_newid_file(struct pci_driver *drv)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_match_device - Tell if a PCI device structure has a matching
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                    PCI device id structure
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ids: array of PCI device id structures to search in
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the PCI device structure to match against
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * system is in its list of supported devices.Returns the matching
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst struct pci_device_id *
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev)
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ids->vendor || ids->subvendor || ids->class_mask) {
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (pci_match_one_device(ids, dev))
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ids;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ids++;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_probe_static()
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev)
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = -ENODEV;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *id;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!drv->id_table)
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return error;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	id = pci_match_device(drv->id_table, pci_dev);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (id)
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = drv->probe(pci_dev, id);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error >= 0) {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev->driver = drv;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = 0;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __pci_device_probe()
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns 0  on success, else error.
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pci_dev->driver && drv->probe) {
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = pci_device_probe_static(drv, pci_dev);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (error == -ENODEV)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			error = pci_device_probe_dynamic(drv, pci_dev);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_probe(struct device * dev)
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *drv;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *pci_dev;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv = to_pci_driver(dev->driver);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev = to_pci_dev(dev);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_get(pci_dev);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = __pci_device_probe(drv, pci_dev);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error)
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev_put(pci_dev);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_remove(struct device * dev)
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv) {
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (drv->remove)
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			drv->remove(pci_dev);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev->driver = NULL;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We would love to complain here if pci_dev->is_enabled is set, that
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the driver should have called pci_disable_device(), but the
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unfortunate fact is there are too many odd BIOS and bridge setups
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that don't like drivers doing that all of the time.
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Oh well, we can dream of sane hardware when we sleep, no matter how
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * horrible the crap we have to deal with is when we are awake...
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_put(pci_dev);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_suspend(struct device * dev, pm_message_t state)
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->suspend)
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = drv->suspend(pci_dev, state);
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_save_state(pci_dev);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Default resume method for devices that have no driver provided resume,
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or not even a driver at all.
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pci_default_resume(struct pci_dev *pci_dev)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* restore the PCI config space */
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_restore_state(pci_dev);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the device was enabled before suspend, reenable */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_dev->is_enabled)
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_enable_device(pci_dev);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the device was busmaster before the suspend, make it busmaster again */
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_dev->is_busmaster)
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_set_master(pci_dev);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_resume(struct device * dev)
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->resume)
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		drv->resume(pci_dev);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_default_resume(pci_dev);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartmanstatic void pci_device_shutdown(struct device *dev)
322c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman{
323c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	struct pci_dev *pci_dev = to_pci_dev(dev);
324c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	struct pci_driver *drv = pci_dev->driver;
325c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman
326c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	if (drv && drv->shutdown)
327c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman		drv->shutdown(pci_dev);
328c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_driver *driver = kobj_to_pci_driver(kobj);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ssize_t ret = 0;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_driver(driver)) {
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dattr->show)
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = dattr->show(driver, buf);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_driver(driver);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_store(struct kobject * kobj, struct attribute *attr,
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      const char *buf, size_t count)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_driver *driver = kobj_to_pci_driver(kobj);
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ssize_t ret = 0;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_driver(driver)) {
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dattr->store)
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = dattr->store(driver, buf, count);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_driver(driver);
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sysfs_ops pci_driver_sysfs_ops = {
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.show = pci_driver_attr_show,
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.store = pci_driver_attr_store,
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct kobj_type pci_driver_kobj_type = {
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sysfs_ops = &pci_driver_sysfs_ops,
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_populate_driver_dir(struct pci_driver *drv)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return pci_create_newid_file(drv);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_register_driver - register a new pci driver
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to register
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds the driver structure to the list of registered drivers.
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns a negative value on error, otherwise 0.
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If no error occured, the driver remains registered even if
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no device was claimed during registration.
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pci_register_driver(struct pci_driver *drv)
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error;
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize common driver fields */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.name = drv->name;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.bus = &pci_bus_type;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.probe = pci_device_probe;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.remove = pci_device_remove;
396c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	drv->driver.shutdown = pci_device_shutdown,
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.owner = drv->owner;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.kobj.ktype = &pci_driver_kobj_type;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_init_dynids(&drv->dynids);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register with core */
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = driver_register(&drv->driver);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!error)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_populate_driver_dir(drv);
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_unregister_driver - unregister a pci driver
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to unregister
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers,
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gives it a chance to clean up by calling its remove() function for
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each device it was responsible for, and marks those devices as
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driverless.
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_unregister_driver(struct pci_driver *drv)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&drv->driver);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_dynids(drv);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver pci_compat_driver = {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name = "compat"
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_driver - get the pci_driver of a device
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device to query
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registered driver for the device.
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_driver *
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_dev_driver(const struct pci_dev *dev)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->driver)
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dev->driver;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(i=0; i<=PCI_ROM_RESOURCE; i++)
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->resource[i].flags & IORESOURCE_BUSY)
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return &pci_compat_driver;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ids: array of PCI device id structures to search in
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the PCI device structure to match against
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * system is in its list of supported devices.Returns the matching
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_bus_match(struct device * dev, struct device_driver * drv)
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_dev * pci_dev = to_pci_dev(dev);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * pci_drv = to_pci_driver(drv);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id * ids = pci_drv->id_table;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *found_id;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!ids)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	found_id = pci_match_device(ids, pci_dev);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (found_id)
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return pci_bus_match_dynids(pci_dev, pci_drv);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device being referenced
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Each live reference to a device should be refcounted.
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Drivers for PCI devices should normally record such references in
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * their probe() methods, when they bind to a device, and release
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods.
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A pointer to the device with the incremented reference counter is returned.
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_dev *pci_dev_get(struct pci_dev *dev)
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_device(&dev->dev);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_put - release a use of the pci device structure
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device that's been disconnected
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called when a user of a device is finished with it.  When the last
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of the device calls this function, the memory of the device is freed.
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pci_dev_put(struct pci_dev *dev)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_device(&dev->dev);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_HOTPLUG
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pci_hotplug (struct device *dev, char **envp, int num_envp,
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 char *buffer, int buffer_size)
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type pci_bus_type = {
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "pci",
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.match		= pci_bus_match,
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.hotplug	= pci_hotplug,
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= pci_device_suspend,
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= pci_device_resume,
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dev_attrs	= pci_dev_attrs,
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pci_driver_init(void)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bus_register(&pci_bus_type);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspostcore_initcall(pci_driver_init);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_match_device);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_register_driver);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_unregister_driver);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_driver);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_type);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_get);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_put);
541