pci-driver.c revision 50bf14b3ff05fb6e10688021b96f95d30a300f8d
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> 10d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#include <linux/mempolicy.h> 114e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h> 124e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h> 138c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/sched.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pci.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Registration of PCI drivers and handling of hot-pluggable devices. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 200f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman/* multithreaded probe logic */ 210f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartmanstatic int pci_multithread_probe = 220f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman#ifdef CONFIG_PCI_MULTITHREAD_PROBE 230f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman 1; 240f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman#else 250f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman 0; 260f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman#endif 270f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644); 280f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman 290f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic device IDs are disabled for !CONFIG_HOTPLUG 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstruct pci_dynid { 3575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct list_head node; 3675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_device_id id; 3775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman}; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 393d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman#ifdef CONFIG_HOTPLUG 403d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 428f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * store_new_id - add a new PCI device ID to this driver and re-probe devices 438f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @driver: target device driver 448f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @buf: buffer for scanning device ID data 458f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @count: input size 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds a new dynamic pci device ID to this driver, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and causes the driver to probe for all devices again. 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 50f8eb1005a5bdb019d2a4ff3ef8d8e8015b22afcbRandy Dunlapstatic ssize_t 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstore_new_id(struct device_driver *driver, const char *buf, size_t count) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_dynid *dynid; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_driver *pdrv = to_pci_driver(driver); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subdevice=PCI_ANY_ID, class=0, class_mask=0; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long driver_data=0; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fields=0; 59b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman int retval = 0; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fields = sscanf(buf, "%x %x %x %x %x %x %lux", 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &vendor, &device, &subvendor, &subdevice, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &class, &class_mask, &driver_data); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fields < 0) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dynid) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&dynid->node); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.vendor = vendor; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.device = device; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.subvendor = subvendor; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.subdevice = subdevice; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.class = class; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.class_mask = class_mask; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynid->id.driver_data = pdrv->dynids.use_driver_data ? 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_data : 0UL; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&pdrv->dynids.lock); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&pdrv->dynids.list, &dynid->node); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&pdrv->dynids.lock); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman if (get_driver(&pdrv->driver)) { 86b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman retval = driver_attach(&pdrv->driver); 8775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman put_driver(&pdrv->driver); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 90b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman if (retval) 91b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman return retval; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_free_dynids(struct pci_driver *drv) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_dynid *dynid, *n; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&drv->dynids.lock); 10275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&dynid->node); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dynid); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&drv->dynids.lock); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_create_newid_file(struct pci_driver *drv) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->probe != NULL) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sysfs_create_file(&drv->driver.kobj, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &driver_attr_new_id.attr); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* !CONFIG_HOTPLUG */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_free_dynids(struct pci_driver *drv) {} 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_create_newid_file(struct pci_driver *drv) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_id - See if a pci device matches a given pci_id table 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ids: array of PCI device id structures to search in 13075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @dev: the PCI device structure to match against. 13175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the 13375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices. Returns the matching 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match. 13575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * 13675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Depreciated, don't use this as it will not catch any dynamic ids 13775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * that a driver might want to check for. 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_id(const struct pci_device_id *ids, 14075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_dev *dev) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman if (ids) { 14375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman while (ids->vendor || ids->subvendor || ids->class_mask) { 14475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman if (pci_match_one_device(ids, dev)) 14575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman return ids; 14675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman ids++; 14775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman } 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 15375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_device - Tell if a PCI device structure has a matching 15475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * PCI device id structure 15575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @drv: the PCI driver to match against 15639ba487fe22a63b3df7c543c82d01db0f0fed700Henrik Kretzschmar * @dev: the PCI device structure to match against 15775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * 15875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Used by a driver to check whether a PCI device present in the 15975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices. Returns the matching 16075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_device_id structure or %NULL if there is no match. 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_device(struct pci_driver *drv, 16375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_dev *dev) 16475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *id; 16675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_dynid *dynid; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman id = pci_match_id(drv->id_table, dev); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id) 17075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman return id; 17175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman 17275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman /* static ids didn't match, lets look at the dynamic ones */ 17375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman spin_lock(&drv->dynids.lock); 17475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman list_for_each_entry(dynid, &drv->dynids.list, node) { 17575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman if (pci_match_one_device(&dynid->id, dev)) { 17675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman spin_unlock(&drv->dynids.lock); 17775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman return &dynid->id; 17875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman } 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman spin_unlock(&drv->dynids.lock); 18175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman return NULL; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 184d42c69972b853fd33a26c8c7405624be41a22136Andi Kleenstatic int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, 185d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen const struct pci_device_id *id) 186d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen{ 187d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen int error; 188d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA 189d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen /* Execute driver initialization on node where the 190d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen device's bus is attached to. This way the driver likely 191d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen allocates its local memory on the right node without 192d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen any need to change it. */ 193d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen struct mempolicy *oldpol; 194d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen cpumask_t oldmask = current->cpus_allowed; 195d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen int node = pcibus_to_node(dev->bus); 196d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen if (node >= 0 && node_online(node)) 197d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen set_cpus_allowed(current, node_to_cpumask(node)); 198d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen /* And set default memory allocation policy */ 199d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen oldpol = current->mempolicy; 200d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen current->mempolicy = &default_policy; 201d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen mpol_get(current->mempolicy); 202d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif 203d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen error = drv->probe(dev, id); 204d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA 205d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen set_cpus_allowed(current, oldmask); 206d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen mpol_free(current->mempolicy); 207d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen current->mempolicy = oldpol; 208d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif 209d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen return error; 210d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen} 211d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __pci_device_probe() 2148f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: driver to call to check if it wants the PCI device 2158f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @pci_dev: PCI device being probed 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2178f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * returns 0 on success, else error. 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 22275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{ 22375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman const struct pci_device_id *id; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pci_dev->driver && drv->probe) { 22775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman error = -ENODEV; 22875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman 22975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman id = pci_match_device(drv, pci_dev); 23075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman if (id) 231d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen error = pci_call_probe(drv, pci_dev, id); 23275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman if (error >= 0) { 23375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman pci_dev->driver = drv; 23475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman error = 0; 23575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_probe(struct device * dev) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_driver *drv; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pci_dev; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv = to_pci_driver(dev->driver); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev = to_pci_dev(dev); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev_get(pci_dev); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = __pci_device_probe(drv, pci_dev); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev_put(pci_dev); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_remove(struct device * dev) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_driver * drv = pci_dev->driver; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv) { 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->remove) 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->remove(pci_dev); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev->driver = NULL; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2682449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li * If the device is still on, set the power state as "unknown", 2692449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li * since it might change by the next time we load the driver. 2702449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li */ 2712449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li if (pci_dev->current_state == PCI_D0) 2722449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li pci_dev->current_state = PCI_UNKNOWN; 2732449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li 2742449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li /* 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We would love to complain here if pci_dev->is_enabled is set, that 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the driver should have called pci_disable_device(), but the 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unfortunate fact is there are too many odd BIOS and bridge setups 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that don't like drivers doing that all of the time. 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Oh well, we can dream of sane hardware when we sleep, no matter how 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * horrible the crap we have to deal with is when we are awake... 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev_put(pci_dev); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_suspend(struct device * dev, pm_message_t state) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_driver * drv = pci_dev->driver; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293026694920579590c73b5c56705d543568ed5ad41Andrew Morton if (drv && drv->suspend) { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = drv->suspend(pci_dev, state); 295026694920579590c73b5c56705d543568ed5ad41Andrew Morton suspend_report_result(drv->suspend, i); 296026694920579590c73b5c56705d543568ed5ad41Andrew Morton } else { 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_save_state(pci_dev); 2982449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li /* 2992449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li * mark its power state as "unknown", since we don't know if 3002449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li * e.g. the BIOS will change its device state when we suspend. 3012449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li */ 3022449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li if (pci_dev->current_state == PCI_D0) 3032449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li pci_dev->current_state = PCI_UNKNOWN; 304026694920579590c73b5c56705d543568ed5ad41Andrew Morton } 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 308cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvaldsstatic int pci_device_suspend_late(struct device * dev, pm_message_t state) 309cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds{ 310cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 311cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds struct pci_driver * drv = pci_dev->driver; 312cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds int i = 0; 313cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds 314cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds if (drv && drv->suspend_late) { 315cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds i = drv->suspend_late(pci_dev, state); 316cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds suspend_report_result(drv->suspend_late, i); 317cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds } 318cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds return i; 319cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds} 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32195a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman/* 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Default resume method for devices that have no driver provided resume, 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or not even a driver at all. 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3258d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvarestatic int pci_default_resume(struct pci_dev *pci_dev) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3278d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare int retval = 0; 32895a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* restore the PCI config space */ 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_restore_state(pci_dev); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if the device was enabled before suspend, reenable */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pci_dev->is_enabled) 33395a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman retval = pci_enable_device(pci_dev); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if the device was busmaster before the suspend, make it busmaster again */ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pci_dev->is_busmaster) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master(pci_dev); 3378d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare 3388d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare return retval; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_resume(struct device * dev) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3438d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare int error; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_driver * drv = pci_dev->driver; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->resume) 3488d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare error = drv->resume(pci_dev); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3508d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare error = pci_default_resume(pci_dev); 3518d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare return error; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 354cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvaldsstatic int pci_device_resume_early(struct device * dev) 355cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds{ 356cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds int error = 0; 357cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 358cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds struct pci_driver * drv = pci_dev->driver; 359cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds 360cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds if (drv && drv->resume_early) 361cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds error = drv->resume_early(pci_dev); 362cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds return error; 363cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds} 364cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds 365c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartmanstatic void pci_device_shutdown(struct device *dev) 366c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman{ 367c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman struct pci_dev *pci_dev = to_pci_dev(dev); 368c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman struct pci_driver *drv = pci_dev->driver; 369c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman 370c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman if (drv && drv->shutdown) 371c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman drv->shutdown(pci_dev); 372c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman} 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj) 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr) 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device_driver *driver = kobj_to_pci_driver(kobj); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct driver_attribute *dattr = attr_to_driver_attribute(attr); 382fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov ssize_t ret; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 384fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov if (!get_driver(driver)) 385fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov return -ENODEV; 386fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov 387fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov ret = dattr->show ? dattr->show(driver, buf) : -EIO; 388fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov 389fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov put_driver(driver); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_store(struct kobject * kobj, struct attribute *attr, 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *buf, size_t count) 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device_driver *driver = kobj_to_pci_driver(kobj); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct driver_attribute *dattr = attr_to_driver_attribute(attr); 399fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov ssize_t ret; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov if (!get_driver(driver)) 402fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov return -ENODEV; 403fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov 404fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov ret = dattr->store ? dattr->store(driver, buf, count) : -EIO; 405fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov 406fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov put_driver(driver); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sysfs_ops pci_driver_sysfs_ops = { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = pci_driver_attr_show, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .store = pci_driver_attr_store, 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct kobj_type pci_driver_kobj_type = { 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sysfs_ops = &pci_driver_sysfs_ops, 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 419863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard * __pci_register_driver - register a new pci driver 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to register 421863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard * @owner: owner module of drv 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds the driver structure to the list of registered drivers. 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns a negative value on error, otherwise 0. 425eaae4b3a84a3781543a32bcaf0a33306ae915574Steven Cole * If no error occurred, the driver remains registered even if 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no device was claimed during registration. 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 428863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffardint __pci_register_driver(struct pci_driver *drv, struct module *owner) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize common driver fields */ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->driver.name = drv->name; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->driver.bus = &pci_bus_type; 435863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard drv->driver.owner = owner; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->driver.kobj.ktype = &pci_driver_kobj_type; 43750b0075520a0acba9cabab5203bbce918b966d9aAlan Cox 43850b0075520a0acba9cabab5203bbce918b966d9aAlan Cox if (pci_multithread_probe) 43950b0075520a0acba9cabab5203bbce918b966d9aAlan Cox drv->driver.multithread_probe = pci_multithread_probe; 44050b0075520a0acba9cabab5203bbce918b966d9aAlan Cox else 44150b0075520a0acba9cabab5203bbce918b966d9aAlan Cox drv->driver.multithread_probe = drv->multithread_probe; 44275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman 44375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman spin_lock_init(&drv->dynids.lock); 44475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman INIT_LIST_HEAD(&drv->dynids.list); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* register with core */ 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = driver_register(&drv->driver); 44850bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita if (error) 44950bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita return error; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45150bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita error = pci_create_newid_file(drv); 45250bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita if (error) 45350bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita driver_unregister(&drv->driver); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_unregister_driver - unregister a pci driver 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to unregister 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers, 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gives it a chance to clean up by calling its remove() function for 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each device it was responsible for, and marks those devices as 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driverless. 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_unregister_driver(struct pci_driver *drv) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&drv->driver); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_free_dynids(drv); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver pci_compat_driver = { 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "compat" 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_driver - get the pci_driver of a device 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device to query 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registered driver for the device. 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_driver * 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_dev_driver(const struct pci_dev *dev) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->driver) 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev->driver; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i=0; i<=PCI_ROM_RESOURCE; i++) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->resource[i].flags & IORESOURCE_BUSY) 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &pci_compat_driver; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the PCI device structure to match against 5038f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: the device driver to search for matching PCI device id structures 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the 5068f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * system is in its list of supported devices. Returns the matching 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match. 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 50975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstatic int pci_bus_match(struct device *dev, struct device_driver *drv) 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 51175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_dev *pci_dev = to_pci_dev(dev); 51275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman struct pci_driver *pci_drv = to_pci_driver(drv); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *found_id; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman found_id = pci_match_device(pci_drv, pci_dev); 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found_id) 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman return 0; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device being referenced 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Each live reference to a device should be refcounted. 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Drivers for PCI devices should normally record such references in 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * their probe() methods, when they bind to a device, and release 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods. 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A pointer to the device with the incremented reference counter is returned. 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_dev *pci_dev_get(struct pci_dev *dev) 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev) 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_device(&dev->dev); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_put - release a use of the pci device structure 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device that's been disconnected 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called when a user of a device is finished with it. When the last 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of the device calls this function, the memory of the device is freed. 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pci_dev_put(struct pci_dev *dev) 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev) 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&dev->dev); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_HOTPLUG 555312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sieversint pci_uevent(struct device *dev, char **envp, int num_envp, 556312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers char *buffer, int buffer_size) 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type pci_bus_type = { 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "pci", 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .match = pci_bus_match, 565312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers .uevent = pci_uevent, 566b15d686a2b589c9e4f1ea116553e9c3c3d030daeRussell King .probe = pci_device_probe, 567b15d686a2b589c9e4f1ea116553e9c3c3d030daeRussell King .remove = pci_device_remove, 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = pci_device_suspend, 569cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds .suspend_late = pci_device_suspend_late, 570cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds .resume_early = pci_device_resume_early, 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = pci_device_resume, 572cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds .shutdown = pci_device_shutdown, 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .dev_attrs = pci_dev_attrs, 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pci_driver_init(void) 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return bus_register(&pci_bus_type); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspostcore_initcall(pci_driver_init); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 58375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-HartmanEXPORT_SYMBOL(pci_match_id); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_match_device); 585863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffardEXPORT_SYMBOL(__pci_register_driver); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_unregister_driver); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_driver); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_type); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_get); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_put); 591