11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * drivers/pci/pci-driver.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include <linux/pci.h> 71da177e4SLinus Torvalds #include <linux/module.h> 81da177e4SLinus Torvalds #include <linux/init.h> 91da177e4SLinus Torvalds #include <linux/device.h> 10d42c6997SAndi Kleen #include <linux/mempolicy.h> 114e57b681STim Schmielau #include <linux/string.h> 124e57b681STim Schmielau #include <linux/slab.h> 138c65b4a6STim Schmielau #include <linux/sched.h> 141da177e4SLinus Torvalds #include "pci.h" 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds /* 171da177e4SLinus Torvalds * Registration of PCI drivers and handling of hot-pluggable devices. 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds 200f397f86SGreg Kroah-Hartman /* multithreaded probe logic */ 210f397f86SGreg Kroah-Hartman static int pci_multithread_probe = 220f397f86SGreg Kroah-Hartman #ifdef CONFIG_PCI_MULTITHREAD_PROBE 230f397f86SGreg Kroah-Hartman 1; 240f397f86SGreg Kroah-Hartman #else 250f397f86SGreg Kroah-Hartman 0; 260f397f86SGreg Kroah-Hartman #endif 270f397f86SGreg Kroah-Hartman __module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644); 280f397f86SGreg Kroah-Hartman 290f397f86SGreg Kroah-Hartman 301da177e4SLinus Torvalds /* 311da177e4SLinus Torvalds * Dynamic device IDs are disabled for !CONFIG_HOTPLUG 321da177e4SLinus Torvalds */ 331da177e4SLinus Torvalds 3475865858SGreg Kroah-Hartman struct pci_dynid { 3575865858SGreg Kroah-Hartman struct list_head node; 3675865858SGreg Kroah-Hartman struct pci_device_id id; 3775865858SGreg Kroah-Hartman }; 381da177e4SLinus Torvalds 393d3c2ae1SGreg KH #ifdef CONFIG_HOTPLUG 403d3c2ae1SGreg KH 411da177e4SLinus Torvalds /** 428f7020d3SRandy Dunlap * store_new_id - add a new PCI device ID to this driver and re-probe devices 438f7020d3SRandy Dunlap * @driver: target device driver 448f7020d3SRandy Dunlap * @buf: buffer for scanning device ID data 458f7020d3SRandy Dunlap * @count: input size 461da177e4SLinus Torvalds * 471da177e4SLinus Torvalds * Adds a new dynamic pci device ID to this driver, 481da177e4SLinus Torvalds * and causes the driver to probe for all devices again. 491da177e4SLinus Torvalds */ 50f8eb1005SRandy Dunlap static ssize_t 511da177e4SLinus Torvalds store_new_id(struct device_driver *driver, const char *buf, size_t count) 521da177e4SLinus Torvalds { 5375865858SGreg Kroah-Hartman struct pci_dynid *dynid; 541da177e4SLinus Torvalds struct pci_driver *pdrv = to_pci_driver(driver); 551da177e4SLinus Torvalds __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, 561da177e4SLinus Torvalds subdevice=PCI_ANY_ID, class=0, class_mask=0; 571da177e4SLinus Torvalds unsigned long driver_data=0; 581da177e4SLinus Torvalds int fields=0; 59b19441afSGreg Kroah-Hartman int retval = 0; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds fields = sscanf(buf, "%x %x %x %x %x %x %lux", 621da177e4SLinus Torvalds &vendor, &device, &subvendor, &subdevice, 631da177e4SLinus Torvalds &class, &class_mask, &driver_data); 641da177e4SLinus Torvalds if (fields < 0) 651da177e4SLinus Torvalds return -EINVAL; 661da177e4SLinus Torvalds 67f5afe806SEric Sesterhenn dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); 681da177e4SLinus Torvalds if (!dynid) 691da177e4SLinus Torvalds return -ENOMEM; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds INIT_LIST_HEAD(&dynid->node); 721da177e4SLinus Torvalds dynid->id.vendor = vendor; 731da177e4SLinus Torvalds dynid->id.device = device; 741da177e4SLinus Torvalds dynid->id.subvendor = subvendor; 751da177e4SLinus Torvalds dynid->id.subdevice = subdevice; 761da177e4SLinus Torvalds dynid->id.class = class; 771da177e4SLinus Torvalds dynid->id.class_mask = class_mask; 781da177e4SLinus Torvalds dynid->id.driver_data = pdrv->dynids.use_driver_data ? 791da177e4SLinus Torvalds driver_data : 0UL; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds spin_lock(&pdrv->dynids.lock); 821da177e4SLinus Torvalds list_add_tail(&pdrv->dynids.list, &dynid->node); 831da177e4SLinus Torvalds spin_unlock(&pdrv->dynids.lock); 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds if (get_driver(&pdrv->driver)) { 86b19441afSGreg Kroah-Hartman retval = driver_attach(&pdrv->driver); 871da177e4SLinus Torvalds put_driver(&pdrv->driver); 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds 90b19441afSGreg Kroah-Hartman if (retval) 91b19441afSGreg Kroah-Hartman return retval; 921da177e4SLinus Torvalds return count; 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds static void 971da177e4SLinus Torvalds pci_free_dynids(struct pci_driver *drv) 981da177e4SLinus Torvalds { 9975865858SGreg Kroah-Hartman struct pci_dynid *dynid, *n; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds spin_lock(&drv->dynids.lock); 10275865858SGreg Kroah-Hartman list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { 1031da177e4SLinus Torvalds list_del(&dynid->node); 1041da177e4SLinus Torvalds kfree(dynid); 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds spin_unlock(&drv->dynids.lock); 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds static int 1101da177e4SLinus Torvalds pci_create_newid_file(struct pci_driver *drv) 1111da177e4SLinus Torvalds { 1121da177e4SLinus Torvalds int error = 0; 1131da177e4SLinus Torvalds if (drv->probe != NULL) 1141da177e4SLinus Torvalds error = sysfs_create_file(&drv->driver.kobj, 1151da177e4SLinus Torvalds &driver_attr_new_id.attr); 1161da177e4SLinus Torvalds return error; 1171da177e4SLinus Torvalds } 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds #else /* !CONFIG_HOTPLUG */ 1201da177e4SLinus Torvalds static inline void pci_free_dynids(struct pci_driver *drv) {} 1211da177e4SLinus Torvalds static inline int pci_create_newid_file(struct pci_driver *drv) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds return 0; 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds #endif 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds /** 12875865858SGreg Kroah-Hartman * pci_match_id - See if a pci device matches a given pci_id table 1291da177e4SLinus Torvalds * @ids: array of PCI device id structures to search in 13075865858SGreg Kroah-Hartman * @dev: the PCI device structure to match against. 1311da177e4SLinus Torvalds * 1321da177e4SLinus Torvalds * Used by a driver to check whether a PCI device present in the 1331da177e4SLinus Torvalds * system is in its list of supported devices. Returns the matching 1341da177e4SLinus Torvalds * pci_device_id structure or %NULL if there is no match. 13575865858SGreg Kroah-Hartman * 13675865858SGreg Kroah-Hartman * Depreciated, don't use this as it will not catch any dynamic ids 13775865858SGreg Kroah-Hartman * that a driver might want to check for. 1381da177e4SLinus Torvalds */ 13975865858SGreg Kroah-Hartman const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, 14075865858SGreg Kroah-Hartman struct pci_dev *dev) 1411da177e4SLinus Torvalds { 14275865858SGreg Kroah-Hartman if (ids) { 1431da177e4SLinus Torvalds while (ids->vendor || ids->subvendor || ids->class_mask) { 1441da177e4SLinus Torvalds if (pci_match_one_device(ids, dev)) 1451da177e4SLinus Torvalds return ids; 1461da177e4SLinus Torvalds ids++; 1471da177e4SLinus Torvalds } 14875865858SGreg Kroah-Hartman } 1491da177e4SLinus Torvalds return NULL; 1501da177e4SLinus Torvalds } 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds /** 153ae9608afSRandy Dunlap * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure 15475865858SGreg Kroah-Hartman * @drv: the PCI driver to match against 15539ba487fSHenrik Kretzschmar * @dev: the PCI device structure to match against 1561da177e4SLinus Torvalds * 15775865858SGreg Kroah-Hartman * Used by a driver to check whether a PCI device present in the 15875865858SGreg Kroah-Hartman * system is in its list of supported devices. Returns the matching 15975865858SGreg Kroah-Hartman * pci_device_id structure or %NULL if there is no match. 1601da177e4SLinus Torvalds */ 16175865858SGreg Kroah-Hartman const struct pci_device_id *pci_match_device(struct pci_driver *drv, 16275865858SGreg Kroah-Hartman struct pci_dev *dev) 1631da177e4SLinus Torvalds { 16475865858SGreg Kroah-Hartman struct pci_dynid *dynid; 1651da177e4SLinus Torvalds 1667461b60aSRussell King /* Look at the dynamic ids first, before the static ones */ 16775865858SGreg Kroah-Hartman spin_lock(&drv->dynids.lock); 16875865858SGreg Kroah-Hartman list_for_each_entry(dynid, &drv->dynids.list, node) { 16975865858SGreg Kroah-Hartman if (pci_match_one_device(&dynid->id, dev)) { 17075865858SGreg Kroah-Hartman spin_unlock(&drv->dynids.lock); 17175865858SGreg Kroah-Hartman return &dynid->id; 1721da177e4SLinus Torvalds } 17375865858SGreg Kroah-Hartman } 17475865858SGreg Kroah-Hartman spin_unlock(&drv->dynids.lock); 1757461b60aSRussell King 1767461b60aSRussell King return pci_match_id(drv->id_table, dev); 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 179d42c6997SAndi Kleen static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, 180d42c6997SAndi Kleen const struct pci_device_id *id) 181d42c6997SAndi Kleen { 182d42c6997SAndi Kleen int error; 183d42c6997SAndi Kleen #ifdef CONFIG_NUMA 184d42c6997SAndi Kleen /* Execute driver initialization on node where the 185d42c6997SAndi Kleen device's bus is attached to. This way the driver likely 186d42c6997SAndi Kleen allocates its local memory on the right node without 187d42c6997SAndi Kleen any need to change it. */ 188d42c6997SAndi Kleen struct mempolicy *oldpol; 189d42c6997SAndi Kleen cpumask_t oldmask = current->cpus_allowed; 190d42c6997SAndi Kleen int node = pcibus_to_node(dev->bus); 191d42c6997SAndi Kleen if (node >= 0 && node_online(node)) 192d42c6997SAndi Kleen set_cpus_allowed(current, node_to_cpumask(node)); 193d42c6997SAndi Kleen /* And set default memory allocation policy */ 194d42c6997SAndi Kleen oldpol = current->mempolicy; 195d42c6997SAndi Kleen current->mempolicy = &default_policy; 196d42c6997SAndi Kleen mpol_get(current->mempolicy); 197d42c6997SAndi Kleen #endif 198d42c6997SAndi Kleen error = drv->probe(dev, id); 199d42c6997SAndi Kleen #ifdef CONFIG_NUMA 200d42c6997SAndi Kleen set_cpus_allowed(current, oldmask); 201d42c6997SAndi Kleen mpol_free(current->mempolicy); 202d42c6997SAndi Kleen current->mempolicy = oldpol; 203d42c6997SAndi Kleen #endif 204d42c6997SAndi Kleen return error; 205d42c6997SAndi Kleen } 206d42c6997SAndi Kleen 2071da177e4SLinus Torvalds /** 2081da177e4SLinus Torvalds * __pci_device_probe() 2098f7020d3SRandy Dunlap * @drv: driver to call to check if it wants the PCI device 2108f7020d3SRandy Dunlap * @pci_dev: PCI device being probed 2111da177e4SLinus Torvalds * 2121da177e4SLinus Torvalds * returns 0 on success, else error. 2131da177e4SLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. 2141da177e4SLinus Torvalds */ 2151da177e4SLinus Torvalds static int 2161da177e4SLinus Torvalds __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 2171da177e4SLinus Torvalds { 21875865858SGreg Kroah-Hartman const struct pci_device_id *id; 2191da177e4SLinus Torvalds int error = 0; 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds if (!pci_dev->driver && drv->probe) { 22275865858SGreg Kroah-Hartman error = -ENODEV; 22375865858SGreg Kroah-Hartman 22475865858SGreg Kroah-Hartman id = pci_match_device(drv, pci_dev); 22575865858SGreg Kroah-Hartman if (id) 226d42c6997SAndi Kleen error = pci_call_probe(drv, pci_dev, id); 22775865858SGreg Kroah-Hartman if (error >= 0) { 22875865858SGreg Kroah-Hartman pci_dev->driver = drv; 22975865858SGreg Kroah-Hartman error = 0; 23075865858SGreg Kroah-Hartman } 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds return error; 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds static int pci_device_probe(struct device * dev) 2361da177e4SLinus Torvalds { 2371da177e4SLinus Torvalds int error = 0; 2381da177e4SLinus Torvalds struct pci_driver *drv; 2391da177e4SLinus Torvalds struct pci_dev *pci_dev; 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds drv = to_pci_driver(dev->driver); 2421da177e4SLinus Torvalds pci_dev = to_pci_dev(dev); 2431da177e4SLinus Torvalds pci_dev_get(pci_dev); 2441da177e4SLinus Torvalds error = __pci_device_probe(drv, pci_dev); 2451da177e4SLinus Torvalds if (error) 2461da177e4SLinus Torvalds pci_dev_put(pci_dev); 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds return error; 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds static int pci_device_remove(struct device * dev) 2521da177e4SLinus Torvalds { 2531da177e4SLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 2541da177e4SLinus Torvalds struct pci_driver * drv = pci_dev->driver; 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds if (drv) { 2571da177e4SLinus Torvalds if (drv->remove) 2581da177e4SLinus Torvalds drv->remove(pci_dev); 2591da177e4SLinus Torvalds pci_dev->driver = NULL; 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* 2632449e06aSShaohua Li * If the device is still on, set the power state as "unknown", 2642449e06aSShaohua Li * since it might change by the next time we load the driver. 2652449e06aSShaohua Li */ 2662449e06aSShaohua Li if (pci_dev->current_state == PCI_D0) 2672449e06aSShaohua Li pci_dev->current_state = PCI_UNKNOWN; 2682449e06aSShaohua Li 2692449e06aSShaohua Li /* 2701da177e4SLinus Torvalds * We would love to complain here if pci_dev->is_enabled is set, that 2711da177e4SLinus Torvalds * the driver should have called pci_disable_device(), but the 2721da177e4SLinus Torvalds * unfortunate fact is there are too many odd BIOS and bridge setups 2731da177e4SLinus Torvalds * that don't like drivers doing that all of the time. 2741da177e4SLinus Torvalds * Oh well, we can dream of sane hardware when we sleep, no matter how 2751da177e4SLinus Torvalds * horrible the crap we have to deal with is when we are awake... 2761da177e4SLinus Torvalds */ 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds pci_dev_put(pci_dev); 2791da177e4SLinus Torvalds return 0; 2801da177e4SLinus Torvalds } 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds static int pci_device_suspend(struct device * dev, pm_message_t state) 2831da177e4SLinus Torvalds { 2841da177e4SLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 2851da177e4SLinus Torvalds struct pci_driver * drv = pci_dev->driver; 2861da177e4SLinus Torvalds int i = 0; 2871da177e4SLinus Torvalds 28802669492SAndrew Morton if (drv && drv->suspend) { 2891da177e4SLinus Torvalds i = drv->suspend(pci_dev, state); 29002669492SAndrew Morton suspend_report_result(drv->suspend, i); 29102669492SAndrew Morton } else { 2921da177e4SLinus Torvalds pci_save_state(pci_dev); 2932449e06aSShaohua Li /* 2942449e06aSShaohua Li * mark its power state as "unknown", since we don't know if 2952449e06aSShaohua Li * e.g. the BIOS will change its device state when we suspend. 2962449e06aSShaohua Li */ 2972449e06aSShaohua Li if (pci_dev->current_state == PCI_D0) 2982449e06aSShaohua Li pci_dev->current_state = PCI_UNKNOWN; 29902669492SAndrew Morton } 3001da177e4SLinus Torvalds return i; 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds 303cbd69dbbSLinus Torvalds static int pci_device_suspend_late(struct device * dev, pm_message_t state) 304cbd69dbbSLinus Torvalds { 305cbd69dbbSLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 306cbd69dbbSLinus Torvalds struct pci_driver * drv = pci_dev->driver; 307cbd69dbbSLinus Torvalds int i = 0; 308cbd69dbbSLinus Torvalds 309cbd69dbbSLinus Torvalds if (drv && drv->suspend_late) { 310cbd69dbbSLinus Torvalds i = drv->suspend_late(pci_dev, state); 311cbd69dbbSLinus Torvalds suspend_report_result(drv->suspend_late, i); 312cbd69dbbSLinus Torvalds } 313cbd69dbbSLinus Torvalds return i; 314cbd69dbbSLinus Torvalds } 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds /* 3171da177e4SLinus Torvalds * Default resume method for devices that have no driver provided resume, 3181da177e4SLinus Torvalds * or not even a driver at all. 3191da177e4SLinus Torvalds */ 3208d92bc22SJean Delvare static int pci_default_resume(struct pci_dev *pci_dev) 3211da177e4SLinus Torvalds { 3228d92bc22SJean Delvare int retval = 0; 32395a62965SGreg Kroah-Hartman 3241da177e4SLinus Torvalds /* restore the PCI config space */ 3251da177e4SLinus Torvalds pci_restore_state(pci_dev); 3261da177e4SLinus Torvalds /* if the device was enabled before suspend, reenable */ 327bae94d02SInaky Perez-Gonzalez if (atomic_read(&pci_dev->enable_cnt)) 328bae94d02SInaky Perez-Gonzalez retval = __pci_enable_device(pci_dev); 3291da177e4SLinus Torvalds /* if the device was busmaster before the suspend, make it busmaster again */ 3301da177e4SLinus Torvalds if (pci_dev->is_busmaster) 3311da177e4SLinus Torvalds pci_set_master(pci_dev); 3328d92bc22SJean Delvare 3338d92bc22SJean Delvare return retval; 3341da177e4SLinus Torvalds } 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds static int pci_device_resume(struct device * dev) 3371da177e4SLinus Torvalds { 3388d92bc22SJean Delvare int error; 3391da177e4SLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 3401da177e4SLinus Torvalds struct pci_driver * drv = pci_dev->driver; 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds if (drv && drv->resume) 3438d92bc22SJean Delvare error = drv->resume(pci_dev); 3441da177e4SLinus Torvalds else 3458d92bc22SJean Delvare error = pci_default_resume(pci_dev); 3468d92bc22SJean Delvare return error; 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 349cbd69dbbSLinus Torvalds static int pci_device_resume_early(struct device * dev) 350cbd69dbbSLinus Torvalds { 351cbd69dbbSLinus Torvalds int error = 0; 352cbd69dbbSLinus Torvalds struct pci_dev * pci_dev = to_pci_dev(dev); 353cbd69dbbSLinus Torvalds struct pci_driver * drv = pci_dev->driver; 354cbd69dbbSLinus Torvalds 3551597cacbSAlan Cox pci_fixup_device(pci_fixup_resume, pci_dev); 3561597cacbSAlan Cox 357cbd69dbbSLinus Torvalds if (drv && drv->resume_early) 358cbd69dbbSLinus Torvalds error = drv->resume_early(pci_dev); 359cbd69dbbSLinus Torvalds return error; 360cbd69dbbSLinus Torvalds } 361cbd69dbbSLinus Torvalds 362c8958177SGreg KH static void pci_device_shutdown(struct device *dev) 363c8958177SGreg KH { 364c8958177SGreg KH struct pci_dev *pci_dev = to_pci_dev(dev); 365c8958177SGreg KH struct pci_driver *drv = pci_dev->driver; 366c8958177SGreg KH 367c8958177SGreg KH if (drv && drv->shutdown) 368c8958177SGreg KH drv->shutdown(pci_dev); 369c8958177SGreg KH } 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds #define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj) 3721da177e4SLinus Torvalds #define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr) 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds static ssize_t 3751da177e4SLinus Torvalds pci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) 3761da177e4SLinus Torvalds { 3771da177e4SLinus Torvalds struct device_driver *driver = kobj_to_pci_driver(kobj); 3781da177e4SLinus Torvalds struct driver_attribute *dattr = attr_to_driver_attribute(attr); 379fc7e4828SDmitry Torokhov ssize_t ret; 3801da177e4SLinus Torvalds 381fc7e4828SDmitry Torokhov if (!get_driver(driver)) 382fc7e4828SDmitry Torokhov return -ENODEV; 383fc7e4828SDmitry Torokhov 384fc7e4828SDmitry Torokhov ret = dattr->show ? dattr->show(driver, buf) : -EIO; 385fc7e4828SDmitry Torokhov 3861da177e4SLinus Torvalds put_driver(driver); 3871da177e4SLinus Torvalds return ret; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds static ssize_t 3911da177e4SLinus Torvalds pci_driver_attr_store(struct kobject * kobj, struct attribute *attr, 3921da177e4SLinus Torvalds const char *buf, size_t count) 3931da177e4SLinus Torvalds { 3941da177e4SLinus Torvalds struct device_driver *driver = kobj_to_pci_driver(kobj); 3951da177e4SLinus Torvalds struct driver_attribute *dattr = attr_to_driver_attribute(attr); 396fc7e4828SDmitry Torokhov ssize_t ret; 3971da177e4SLinus Torvalds 398fc7e4828SDmitry Torokhov if (!get_driver(driver)) 399fc7e4828SDmitry Torokhov return -ENODEV; 400fc7e4828SDmitry Torokhov 401fc7e4828SDmitry Torokhov ret = dattr->store ? dattr->store(driver, buf, count) : -EIO; 402fc7e4828SDmitry Torokhov 4031da177e4SLinus Torvalds put_driver(driver); 4041da177e4SLinus Torvalds return ret; 4051da177e4SLinus Torvalds } 4061da177e4SLinus Torvalds 4071da177e4SLinus Torvalds static struct sysfs_ops pci_driver_sysfs_ops = { 4081da177e4SLinus Torvalds .show = pci_driver_attr_show, 4091da177e4SLinus Torvalds .store = pci_driver_attr_store, 4101da177e4SLinus Torvalds }; 4111da177e4SLinus Torvalds static struct kobj_type pci_driver_kobj_type = { 4121da177e4SLinus Torvalds .sysfs_ops = &pci_driver_sysfs_ops, 4131da177e4SLinus Torvalds }; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds /** 416863b18f4SLaurent riffard * __pci_register_driver - register a new pci driver 4171da177e4SLinus Torvalds * @drv: the driver structure to register 418863b18f4SLaurent riffard * @owner: owner module of drv 4191da177e4SLinus Torvalds * 4201da177e4SLinus Torvalds * Adds the driver structure to the list of registered drivers. 4211da177e4SLinus Torvalds * Returns a negative value on error, otherwise 0. 422eaae4b3aSSteven Cole * If no error occurred, the driver remains registered even if 4231da177e4SLinus Torvalds * no device was claimed during registration. 4241da177e4SLinus Torvalds */ 425*725522b5SGreg Kroah-Hartman int __pci_register_driver(struct pci_driver *drv, struct module *owner, 426*725522b5SGreg Kroah-Hartman const char *mod_name) 4271da177e4SLinus Torvalds { 4281da177e4SLinus Torvalds int error; 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds /* initialize common driver fields */ 4311da177e4SLinus Torvalds drv->driver.name = drv->name; 4321da177e4SLinus Torvalds drv->driver.bus = &pci_bus_type; 433863b18f4SLaurent riffard drv->driver.owner = owner; 434*725522b5SGreg Kroah-Hartman drv->driver.mod_name = mod_name; 4351da177e4SLinus Torvalds drv->driver.kobj.ktype = &pci_driver_kobj_type; 43650b00755SAlan Cox 43750b00755SAlan Cox if (pci_multithread_probe) 4380f397f86SGreg Kroah-Hartman drv->driver.multithread_probe = pci_multithread_probe; 43950b00755SAlan Cox else 44050b00755SAlan Cox drv->driver.multithread_probe = drv->multithread_probe; 44175865858SGreg Kroah-Hartman 44275865858SGreg Kroah-Hartman spin_lock_init(&drv->dynids.lock); 44375865858SGreg Kroah-Hartman INIT_LIST_HEAD(&drv->dynids.list); 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds /* register with core */ 4461da177e4SLinus Torvalds error = driver_register(&drv->driver); 44750bf14b3SAkinobu Mita if (error) 44850bf14b3SAkinobu Mita return error; 4491da177e4SLinus Torvalds 45075865858SGreg Kroah-Hartman error = pci_create_newid_file(drv); 45150bf14b3SAkinobu Mita if (error) 45250bf14b3SAkinobu Mita driver_unregister(&drv->driver); 4531da177e4SLinus Torvalds 4541da177e4SLinus Torvalds return error; 4551da177e4SLinus Torvalds } 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds /** 4581da177e4SLinus Torvalds * pci_unregister_driver - unregister a pci driver 4591da177e4SLinus Torvalds * @drv: the driver structure to unregister 4601da177e4SLinus Torvalds * 4611da177e4SLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers, 4621da177e4SLinus Torvalds * gives it a chance to clean up by calling its remove() function for 4631da177e4SLinus Torvalds * each device it was responsible for, and marks those devices as 4641da177e4SLinus Torvalds * driverless. 4651da177e4SLinus Torvalds */ 4661da177e4SLinus Torvalds 4671da177e4SLinus Torvalds void 4681da177e4SLinus Torvalds pci_unregister_driver(struct pci_driver *drv) 4691da177e4SLinus Torvalds { 4701da177e4SLinus Torvalds driver_unregister(&drv->driver); 4711da177e4SLinus Torvalds pci_free_dynids(drv); 4721da177e4SLinus Torvalds } 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds static struct pci_driver pci_compat_driver = { 4751da177e4SLinus Torvalds .name = "compat" 4761da177e4SLinus Torvalds }; 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds /** 4791da177e4SLinus Torvalds * pci_dev_driver - get the pci_driver of a device 4801da177e4SLinus Torvalds * @dev: the device to query 4811da177e4SLinus Torvalds * 4821da177e4SLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no 4831da177e4SLinus Torvalds * registered driver for the device. 4841da177e4SLinus Torvalds */ 4851da177e4SLinus Torvalds struct pci_driver * 4861da177e4SLinus Torvalds pci_dev_driver(const struct pci_dev *dev) 4871da177e4SLinus Torvalds { 4881da177e4SLinus Torvalds if (dev->driver) 4891da177e4SLinus Torvalds return dev->driver; 4901da177e4SLinus Torvalds else { 4911da177e4SLinus Torvalds int i; 4921da177e4SLinus Torvalds for(i=0; i<=PCI_ROM_RESOURCE; i++) 4931da177e4SLinus Torvalds if (dev->resource[i].flags & IORESOURCE_BUSY) 4941da177e4SLinus Torvalds return &pci_compat_driver; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds return NULL; 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds /** 5001da177e4SLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure 5011da177e4SLinus Torvalds * @dev: the PCI device structure to match against 5028f7020d3SRandy Dunlap * @drv: the device driver to search for matching PCI device id structures 5031da177e4SLinus Torvalds * 5041da177e4SLinus Torvalds * Used by a driver to check whether a PCI device present in the 5051da177e4SLinus Torvalds * system is in its list of supported devices. Returns the matching 5061da177e4SLinus Torvalds * pci_device_id structure or %NULL if there is no match. 5071da177e4SLinus Torvalds */ 5081da177e4SLinus Torvalds static int pci_bus_match(struct device *dev, struct device_driver *drv) 5091da177e4SLinus Torvalds { 51075865858SGreg Kroah-Hartman struct pci_dev *pci_dev = to_pci_dev(dev); 5111da177e4SLinus Torvalds struct pci_driver *pci_drv = to_pci_driver(drv); 5121da177e4SLinus Torvalds const struct pci_device_id *found_id; 5131da177e4SLinus Torvalds 51475865858SGreg Kroah-Hartman found_id = pci_match_device(pci_drv, pci_dev); 5151da177e4SLinus Torvalds if (found_id) 5161da177e4SLinus Torvalds return 1; 5171da177e4SLinus Torvalds 51875865858SGreg Kroah-Hartman return 0; 5191da177e4SLinus Torvalds } 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds /** 5221da177e4SLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure 5231da177e4SLinus Torvalds * @dev: the device being referenced 5241da177e4SLinus Torvalds * 5251da177e4SLinus Torvalds * Each live reference to a device should be refcounted. 5261da177e4SLinus Torvalds * 5271da177e4SLinus Torvalds * Drivers for PCI devices should normally record such references in 5281da177e4SLinus Torvalds * their probe() methods, when they bind to a device, and release 5291da177e4SLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods. 5301da177e4SLinus Torvalds * 5311da177e4SLinus Torvalds * A pointer to the device with the incremented reference counter is returned. 5321da177e4SLinus Torvalds */ 5331da177e4SLinus Torvalds struct pci_dev *pci_dev_get(struct pci_dev *dev) 5341da177e4SLinus Torvalds { 5351da177e4SLinus Torvalds if (dev) 5361da177e4SLinus Torvalds get_device(&dev->dev); 5371da177e4SLinus Torvalds return dev; 5381da177e4SLinus Torvalds } 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds /** 5411da177e4SLinus Torvalds * pci_dev_put - release a use of the pci device structure 5421da177e4SLinus Torvalds * @dev: device that's been disconnected 5431da177e4SLinus Torvalds * 5441da177e4SLinus Torvalds * Must be called when a user of a device is finished with it. When the last 5451da177e4SLinus Torvalds * user of the device calls this function, the memory of the device is freed. 5461da177e4SLinus Torvalds */ 5471da177e4SLinus Torvalds void pci_dev_put(struct pci_dev *dev) 5481da177e4SLinus Torvalds { 5491da177e4SLinus Torvalds if (dev) 5501da177e4SLinus Torvalds put_device(&dev->dev); 5511da177e4SLinus Torvalds } 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds #ifndef CONFIG_HOTPLUG 554312c004dSKay Sievers int pci_uevent(struct device *dev, char **envp, int num_envp, 5551da177e4SLinus Torvalds char *buffer, int buffer_size) 5561da177e4SLinus Torvalds { 5571da177e4SLinus Torvalds return -ENODEV; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds #endif 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds struct bus_type pci_bus_type = { 5621da177e4SLinus Torvalds .name = "pci", 5631da177e4SLinus Torvalds .match = pci_bus_match, 564312c004dSKay Sievers .uevent = pci_uevent, 565b15d686aSRussell King .probe = pci_device_probe, 566b15d686aSRussell King .remove = pci_device_remove, 5671da177e4SLinus Torvalds .suspend = pci_device_suspend, 568cbd69dbbSLinus Torvalds .suspend_late = pci_device_suspend_late, 569cbd69dbbSLinus Torvalds .resume_early = pci_device_resume_early, 5701da177e4SLinus Torvalds .resume = pci_device_resume, 571cbd69dbbSLinus Torvalds .shutdown = pci_device_shutdown, 5721da177e4SLinus Torvalds .dev_attrs = pci_dev_attrs, 5731da177e4SLinus Torvalds }; 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds static int __init pci_driver_init(void) 5761da177e4SLinus Torvalds { 5771da177e4SLinus Torvalds return bus_register(&pci_bus_type); 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds postcore_initcall(pci_driver_init); 5811da177e4SLinus Torvalds 58275865858SGreg Kroah-Hartman EXPORT_SYMBOL(pci_match_id); 5831da177e4SLinus Torvalds EXPORT_SYMBOL(pci_match_device); 584863b18f4SLaurent riffard EXPORT_SYMBOL(__pci_register_driver); 5851da177e4SLinus Torvalds EXPORT_SYMBOL(pci_unregister_driver); 5861da177e4SLinus Torvalds EXPORT_SYMBOL(pci_dev_driver); 5871da177e4SLinus Torvalds EXPORT_SYMBOL(pci_bus_type); 5881da177e4SLinus Torvalds EXPORT_SYMBOL(pci_dev_get); 5891da177e4SLinus Torvalds EXPORT_SYMBOL(pci_dev_put); 590