diff options
Diffstat (limited to 'drivers/pci/pci-driver.c')
| -rw-r--r-- | drivers/pci/pci-driver.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 474e9cd0e9e4..b1c0c707d96c 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -17,6 +17,16 @@ | |||
| 17 | * Registration of PCI drivers and handling of hot-pluggable devices. | 17 | * Registration of PCI drivers and handling of hot-pluggable devices. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | /* multithreaded probe logic */ | ||
| 21 | static int pci_multithread_probe = | ||
| 22 | #ifdef CONFIG_PCI_MULTITHREAD_PROBE | ||
| 23 | 1; | ||
| 24 | #else | ||
| 25 | 0; | ||
| 26 | #endif | ||
| 27 | __module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644); | ||
| 28 | |||
| 29 | |||
| 20 | /* | 30 | /* |
| 21 | * Dynamic device IDs are disabled for !CONFIG_HOTPLUG | 31 | * Dynamic device IDs are disabled for !CONFIG_HOTPLUG |
| 22 | */ | 32 | */ |
| @@ -46,6 +56,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
| 46 | subdevice=PCI_ANY_ID, class=0, class_mask=0; | 56 | subdevice=PCI_ANY_ID, class=0, class_mask=0; |
| 47 | unsigned long driver_data=0; | 57 | unsigned long driver_data=0; |
| 48 | int fields=0; | 58 | int fields=0; |
| 59 | int retval = 0; | ||
| 49 | 60 | ||
| 50 | fields = sscanf(buf, "%x %x %x %x %x %x %lux", | 61 | fields = sscanf(buf, "%x %x %x %x %x %x %lux", |
| 51 | &vendor, &device, &subvendor, &subdevice, | 62 | &vendor, &device, &subvendor, &subdevice, |
| @@ -72,10 +83,12 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
| 72 | spin_unlock(&pdrv->dynids.lock); | 83 | spin_unlock(&pdrv->dynids.lock); |
| 73 | 84 | ||
| 74 | if (get_driver(&pdrv->driver)) { | 85 | if (get_driver(&pdrv->driver)) { |
| 75 | driver_attach(&pdrv->driver); | 86 | retval = driver_attach(&pdrv->driver); |
| 76 | put_driver(&pdrv->driver); | 87 | put_driver(&pdrv->driver); |
| 77 | } | 88 | } |
| 78 | 89 | ||
| 90 | if (retval) | ||
| 91 | return retval; | ||
| 79 | return count; | 92 | return count; |
| 80 | } | 93 | } |
| 81 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | 94 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); |
| @@ -279,6 +292,18 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) | |||
| 279 | return i; | 292 | return i; |
| 280 | } | 293 | } |
| 281 | 294 | ||
| 295 | static int pci_device_suspend_late(struct device * dev, pm_message_t state) | ||
| 296 | { | ||
| 297 | struct pci_dev * pci_dev = to_pci_dev(dev); | ||
| 298 | struct pci_driver * drv = pci_dev->driver; | ||
| 299 | int i = 0; | ||
| 300 | |||
| 301 | if (drv && drv->suspend_late) { | ||
| 302 | i = drv->suspend_late(pci_dev, state); | ||
| 303 | suspend_report_result(drv->suspend_late, i); | ||
| 304 | } | ||
| 305 | return i; | ||
| 306 | } | ||
| 282 | 307 | ||
| 283 | /* | 308 | /* |
| 284 | * Default resume method for devices that have no driver provided resume, | 309 | * Default resume method for devices that have no driver provided resume, |
| @@ -313,6 +338,17 @@ static int pci_device_resume(struct device * dev) | |||
| 313 | return error; | 338 | return error; |
| 314 | } | 339 | } |
| 315 | 340 | ||
| 341 | static int pci_device_resume_early(struct device * dev) | ||
| 342 | { | ||
| 343 | int error = 0; | ||
| 344 | struct pci_dev * pci_dev = to_pci_dev(dev); | ||
| 345 | struct pci_driver * drv = pci_dev->driver; | ||
| 346 | |||
| 347 | if (drv && drv->resume_early) | ||
| 348 | error = drv->resume_early(pci_dev); | ||
| 349 | return error; | ||
| 350 | } | ||
| 351 | |||
| 316 | static void pci_device_shutdown(struct device *dev) | 352 | static void pci_device_shutdown(struct device *dev) |
| 317 | { | 353 | { |
| 318 | struct pci_dev *pci_dev = to_pci_dev(dev); | 354 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| @@ -386,6 +422,11 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) | |||
| 386 | drv->driver.owner = owner; | 422 | drv->driver.owner = owner; |
| 387 | drv->driver.kobj.ktype = &pci_driver_kobj_type; | 423 | drv->driver.kobj.ktype = &pci_driver_kobj_type; |
| 388 | 424 | ||
| 425 | if (pci_multithread_probe) | ||
| 426 | drv->driver.multithread_probe = pci_multithread_probe; | ||
| 427 | else | ||
| 428 | drv->driver.multithread_probe = drv->multithread_probe; | ||
| 429 | |||
| 389 | spin_lock_init(&drv->dynids.lock); | 430 | spin_lock_init(&drv->dynids.lock); |
| 390 | INIT_LIST_HEAD(&drv->dynids.list); | 431 | INIT_LIST_HEAD(&drv->dynids.list); |
| 391 | 432 | ||
| @@ -509,8 +550,10 @@ struct bus_type pci_bus_type = { | |||
| 509 | .probe = pci_device_probe, | 550 | .probe = pci_device_probe, |
| 510 | .remove = pci_device_remove, | 551 | .remove = pci_device_remove, |
| 511 | .suspend = pci_device_suspend, | 552 | .suspend = pci_device_suspend, |
| 512 | .shutdown = pci_device_shutdown, | 553 | .suspend_late = pci_device_suspend_late, |
| 554 | .resume_early = pci_device_resume_early, | ||
| 513 | .resume = pci_device_resume, | 555 | .resume = pci_device_resume, |
| 556 | .shutdown = pci_device_shutdown, | ||
| 514 | .dev_attrs = pci_dev_attrs, | 557 | .dev_attrs = pci_dev_attrs, |
| 515 | }; | 558 | }; |
| 516 | 559 | ||
