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