diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
commit | 478c6a43fcbc6c11609f8cee7c7b57223907754f (patch) | |
tree | a7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/pci/pci-driver.c | |
parent | 8a3f257c704e02aee9869decd069a806b45be3f1 (diff) | |
parent | 6bb597507f9839b13498781e481f5458aea33620 (diff) |
Merge branch 'linus' into release
Conflicts:
arch/x86/kernel/cpu/cpufreq/longhaul.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r-- | drivers/pci/pci-driver.c | 258 |
1 files changed, 191 insertions, 67 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 93eac1423585..c0cbbb5a245e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -99,6 +99,52 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
99 | } | 99 | } |
100 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | 100 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); |
101 | 101 | ||
102 | /** | ||
103 | * store_remove_id - remove a PCI device ID from this driver | ||
104 | * @driver: target device driver | ||
105 | * @buf: buffer for scanning device ID data | ||
106 | * @count: input size | ||
107 | * | ||
108 | * Removes a dynamic pci device ID to this driver. | ||
109 | */ | ||
110 | static ssize_t | ||
111 | store_remove_id(struct device_driver *driver, const char *buf, size_t count) | ||
112 | { | ||
113 | struct pci_dynid *dynid, *n; | ||
114 | struct pci_driver *pdrv = to_pci_driver(driver); | ||
115 | __u32 vendor, device, subvendor = PCI_ANY_ID, | ||
116 | subdevice = PCI_ANY_ID, class = 0, class_mask = 0; | ||
117 | int fields = 0; | ||
118 | int retval = -ENODEV; | ||
119 | |||
120 | fields = sscanf(buf, "%x %x %x %x %x %x", | ||
121 | &vendor, &device, &subvendor, &subdevice, | ||
122 | &class, &class_mask); | ||
123 | if (fields < 2) | ||
124 | return -EINVAL; | ||
125 | |||
126 | spin_lock(&pdrv->dynids.lock); | ||
127 | list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) { | ||
128 | struct pci_device_id *id = &dynid->id; | ||
129 | if ((id->vendor == vendor) && | ||
130 | (id->device == device) && | ||
131 | (subvendor == PCI_ANY_ID || id->subvendor == subvendor) && | ||
132 | (subdevice == PCI_ANY_ID || id->subdevice == subdevice) && | ||
133 | !((id->class ^ class) & class_mask)) { | ||
134 | list_del(&dynid->node); | ||
135 | kfree(dynid); | ||
136 | retval = 0; | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | spin_unlock(&pdrv->dynids.lock); | ||
141 | |||
142 | if (retval) | ||
143 | return retval; | ||
144 | return count; | ||
145 | } | ||
146 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | ||
147 | |||
102 | static void | 148 | static void |
103 | pci_free_dynids(struct pci_driver *drv) | 149 | pci_free_dynids(struct pci_driver *drv) |
104 | { | 150 | { |
@@ -125,6 +171,20 @@ static void pci_remove_newid_file(struct pci_driver *drv) | |||
125 | { | 171 | { |
126 | driver_remove_file(&drv->driver, &driver_attr_new_id); | 172 | driver_remove_file(&drv->driver, &driver_attr_new_id); |
127 | } | 173 | } |
174 | |||
175 | static int | ||
176 | pci_create_removeid_file(struct pci_driver *drv) | ||
177 | { | ||
178 | int error = 0; | ||
179 | if (drv->probe != NULL) | ||
180 | error = driver_create_file(&drv->driver,&driver_attr_remove_id); | ||
181 | return error; | ||
182 | } | ||
183 | |||
184 | static void pci_remove_removeid_file(struct pci_driver *drv) | ||
185 | { | ||
186 | driver_remove_file(&drv->driver, &driver_attr_remove_id); | ||
187 | } | ||
128 | #else /* !CONFIG_HOTPLUG */ | 188 | #else /* !CONFIG_HOTPLUG */ |
129 | static inline void pci_free_dynids(struct pci_driver *drv) {} | 189 | static inline void pci_free_dynids(struct pci_driver *drv) {} |
130 | static inline int pci_create_newid_file(struct pci_driver *drv) | 190 | static inline int pci_create_newid_file(struct pci_driver *drv) |
@@ -132,6 +192,11 @@ static inline int pci_create_newid_file(struct pci_driver *drv) | |||
132 | return 0; | 192 | return 0; |
133 | } | 193 | } |
134 | static inline void pci_remove_newid_file(struct pci_driver *drv) {} | 194 | static inline void pci_remove_newid_file(struct pci_driver *drv) {} |
195 | static inline int pci_create_removeid_file(struct pci_driver *drv) | ||
196 | { | ||
197 | return 0; | ||
198 | } | ||
199 | static inline void pci_remove_removeid_file(struct pci_driver *drv) {} | ||
135 | #endif | 200 | #endif |
136 | 201 | ||
137 | /** | 202 | /** |
@@ -352,53 +417,60 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) | |||
352 | { | 417 | { |
353 | struct pci_dev * pci_dev = to_pci_dev(dev); | 418 | struct pci_dev * pci_dev = to_pci_dev(dev); |
354 | struct pci_driver * drv = pci_dev->driver; | 419 | struct pci_driver * drv = pci_dev->driver; |
355 | int i = 0; | 420 | |
421 | pci_dev->state_saved = false; | ||
356 | 422 | ||
357 | if (drv && drv->suspend) { | 423 | if (drv && drv->suspend) { |
358 | pci_power_t prev = pci_dev->current_state; | 424 | pci_power_t prev = pci_dev->current_state; |
425 | int error; | ||
359 | 426 | ||
360 | pci_dev->state_saved = false; | 427 | error = drv->suspend(pci_dev, state); |
361 | 428 | suspend_report_result(drv->suspend, error); | |
362 | i = drv->suspend(pci_dev, state); | 429 | if (error) |
363 | suspend_report_result(drv->suspend, i); | 430 | return error; |
364 | if (i) | ||
365 | return i; | ||
366 | |||
367 | if (pci_dev->state_saved) | ||
368 | goto Fixup; | ||
369 | 431 | ||
370 | if (pci_dev->current_state != PCI_D0 | 432 | if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 |
371 | && pci_dev->current_state != PCI_UNKNOWN) { | 433 | && pci_dev->current_state != PCI_UNKNOWN) { |
372 | WARN_ONCE(pci_dev->current_state != prev, | 434 | WARN_ONCE(pci_dev->current_state != prev, |
373 | "PCI PM: Device state not saved by %pF\n", | 435 | "PCI PM: Device state not saved by %pF\n", |
374 | drv->suspend); | 436 | drv->suspend); |
375 | goto Fixup; | ||
376 | } | 437 | } |
377 | } | 438 | } |
378 | 439 | ||
379 | pci_save_state(pci_dev); | ||
380 | /* | ||
381 | * This is for compatibility with existing code with legacy PM support. | ||
382 | */ | ||
383 | pci_pm_set_unknown_state(pci_dev); | ||
384 | |||
385 | Fixup: | ||
386 | pci_fixup_device(pci_fixup_suspend, pci_dev); | 440 | pci_fixup_device(pci_fixup_suspend, pci_dev); |
387 | 441 | ||
388 | return i; | 442 | return 0; |
389 | } | 443 | } |
390 | 444 | ||
391 | static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) | 445 | static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) |
392 | { | 446 | { |
393 | struct pci_dev * pci_dev = to_pci_dev(dev); | 447 | struct pci_dev * pci_dev = to_pci_dev(dev); |
394 | struct pci_driver * drv = pci_dev->driver; | 448 | struct pci_driver * drv = pci_dev->driver; |
395 | int i = 0; | ||
396 | 449 | ||
397 | if (drv && drv->suspend_late) { | 450 | if (drv && drv->suspend_late) { |
398 | i = drv->suspend_late(pci_dev, state); | 451 | pci_power_t prev = pci_dev->current_state; |
399 | suspend_report_result(drv->suspend_late, i); | 452 | int error; |
453 | |||
454 | error = drv->suspend_late(pci_dev, state); | ||
455 | suspend_report_result(drv->suspend_late, error); | ||
456 | if (error) | ||
457 | return error; | ||
458 | |||
459 | if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 | ||
460 | && pci_dev->current_state != PCI_UNKNOWN) { | ||
461 | WARN_ONCE(pci_dev->current_state != prev, | ||
462 | "PCI PM: Device state not saved by %pF\n", | ||
463 | drv->suspend_late); | ||
464 | return 0; | ||
465 | } | ||
400 | } | 466 | } |
401 | return i; | 467 | |
468 | if (!pci_dev->state_saved) | ||
469 | pci_save_state(pci_dev); | ||
470 | |||
471 | pci_pm_set_unknown_state(pci_dev); | ||
472 | |||
473 | return 0; | ||
402 | } | 474 | } |
403 | 475 | ||
404 | static int pci_legacy_resume_early(struct device *dev) | 476 | static int pci_legacy_resume_early(struct device *dev) |
@@ -423,6 +495,23 @@ static int pci_legacy_resume(struct device *dev) | |||
423 | 495 | ||
424 | /* Auxiliary functions used by the new power management framework */ | 496 | /* Auxiliary functions used by the new power management framework */ |
425 | 497 | ||
498 | /** | ||
499 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
500 | * @pci_dev: PCI device to handle | ||
501 | */ | ||
502 | static int pci_restore_standard_config(struct pci_dev *pci_dev) | ||
503 | { | ||
504 | pci_update_current_state(pci_dev, PCI_UNKNOWN); | ||
505 | |||
506 | if (pci_dev->current_state != PCI_D0) { | ||
507 | int error = pci_set_power_state(pci_dev, PCI_D0); | ||
508 | if (error) | ||
509 | return error; | ||
510 | } | ||
511 | |||
512 | return pci_dev->state_saved ? pci_restore_state(pci_dev) : 0; | ||
513 | } | ||
514 | |||
426 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) | 515 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) |
427 | { | 516 | { |
428 | pci_restore_standard_config(pci_dev); | 517 | pci_restore_standard_config(pci_dev); |
@@ -443,7 +532,6 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev) | |||
443 | /* Disable non-bridge devices without PM support */ | 532 | /* Disable non-bridge devices without PM support */ |
444 | if (!pci_is_bridge(pci_dev)) | 533 | if (!pci_is_bridge(pci_dev)) |
445 | pci_disable_enabled_device(pci_dev); | 534 | pci_disable_enabled_device(pci_dev); |
446 | pci_save_state(pci_dev); | ||
447 | } | 535 | } |
448 | 536 | ||
449 | static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) | 537 | static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) |
@@ -493,13 +581,13 @@ static int pci_pm_suspend(struct device *dev) | |||
493 | if (pci_has_legacy_pm_support(pci_dev)) | 581 | if (pci_has_legacy_pm_support(pci_dev)) |
494 | return pci_legacy_suspend(dev, PMSG_SUSPEND); | 582 | return pci_legacy_suspend(dev, PMSG_SUSPEND); |
495 | 583 | ||
584 | pci_dev->state_saved = false; | ||
585 | |||
496 | if (!pm) { | 586 | if (!pm) { |
497 | pci_pm_default_suspend(pci_dev); | 587 | pci_pm_default_suspend(pci_dev); |
498 | goto Fixup; | 588 | goto Fixup; |
499 | } | 589 | } |
500 | 590 | ||
501 | pci_dev->state_saved = false; | ||
502 | |||
503 | if (pm->suspend) { | 591 | if (pm->suspend) { |
504 | pci_power_t prev = pci_dev->current_state; | 592 | pci_power_t prev = pci_dev->current_state; |
505 | int error; | 593 | int error; |
@@ -509,24 +597,14 @@ static int pci_pm_suspend(struct device *dev) | |||
509 | if (error) | 597 | if (error) |
510 | return error; | 598 | return error; |
511 | 599 | ||
512 | if (pci_dev->state_saved) | 600 | if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 |
513 | goto Fixup; | ||
514 | |||
515 | if (pci_dev->current_state != PCI_D0 | ||
516 | && pci_dev->current_state != PCI_UNKNOWN) { | 601 | && pci_dev->current_state != PCI_UNKNOWN) { |
517 | WARN_ONCE(pci_dev->current_state != prev, | 602 | WARN_ONCE(pci_dev->current_state != prev, |
518 | "PCI PM: State of device not saved by %pF\n", | 603 | "PCI PM: State of device not saved by %pF\n", |
519 | pm->suspend); | 604 | pm->suspend); |
520 | goto Fixup; | ||
521 | } | 605 | } |
522 | } | 606 | } |
523 | 607 | ||
524 | if (!pci_dev->state_saved) { | ||
525 | pci_save_state(pci_dev); | ||
526 | if (!pci_is_bridge(pci_dev)) | ||
527 | pci_prepare_to_sleep(pci_dev); | ||
528 | } | ||
529 | |||
530 | Fixup: | 608 | Fixup: |
531 | pci_fixup_device(pci_fixup_suspend, pci_dev); | 609 | pci_fixup_device(pci_fixup_suspend, pci_dev); |
532 | 610 | ||
@@ -536,21 +614,43 @@ static int pci_pm_suspend(struct device *dev) | |||
536 | static int pci_pm_suspend_noirq(struct device *dev) | 614 | static int pci_pm_suspend_noirq(struct device *dev) |
537 | { | 615 | { |
538 | struct pci_dev *pci_dev = to_pci_dev(dev); | 616 | struct pci_dev *pci_dev = to_pci_dev(dev); |
539 | struct device_driver *drv = dev->driver; | 617 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
540 | int error = 0; | ||
541 | 618 | ||
542 | if (pci_has_legacy_pm_support(pci_dev)) | 619 | if (pci_has_legacy_pm_support(pci_dev)) |
543 | return pci_legacy_suspend_late(dev, PMSG_SUSPEND); | 620 | return pci_legacy_suspend_late(dev, PMSG_SUSPEND); |
544 | 621 | ||
545 | if (drv && drv->pm && drv->pm->suspend_noirq) { | 622 | if (!pm) { |
546 | error = drv->pm->suspend_noirq(dev); | 623 | pci_save_state(pci_dev); |
547 | suspend_report_result(drv->pm->suspend_noirq, error); | 624 | return 0; |
548 | } | 625 | } |
549 | 626 | ||
550 | if (!error) | 627 | if (pm->suspend_noirq) { |
551 | pci_pm_set_unknown_state(pci_dev); | 628 | pci_power_t prev = pci_dev->current_state; |
629 | int error; | ||
552 | 630 | ||
553 | return error; | 631 | error = pm->suspend_noirq(dev); |
632 | suspend_report_result(pm->suspend_noirq, error); | ||
633 | if (error) | ||
634 | return error; | ||
635 | |||
636 | if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 | ||
637 | && pci_dev->current_state != PCI_UNKNOWN) { | ||
638 | WARN_ONCE(pci_dev->current_state != prev, | ||
639 | "PCI PM: State of device not saved by %pF\n", | ||
640 | pm->suspend_noirq); | ||
641 | return 0; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | if (!pci_dev->state_saved) { | ||
646 | pci_save_state(pci_dev); | ||
647 | if (!pci_is_bridge(pci_dev)) | ||
648 | pci_prepare_to_sleep(pci_dev); | ||
649 | } | ||
650 | |||
651 | pci_pm_set_unknown_state(pci_dev); | ||
652 | |||
653 | return 0; | ||
554 | } | 654 | } |
555 | 655 | ||
556 | static int pci_pm_resume_noirq(struct device *dev) | 656 | static int pci_pm_resume_noirq(struct device *dev) |
@@ -617,13 +717,13 @@ static int pci_pm_freeze(struct device *dev) | |||
617 | if (pci_has_legacy_pm_support(pci_dev)) | 717 | if (pci_has_legacy_pm_support(pci_dev)) |
618 | return pci_legacy_suspend(dev, PMSG_FREEZE); | 718 | return pci_legacy_suspend(dev, PMSG_FREEZE); |
619 | 719 | ||
720 | pci_dev->state_saved = false; | ||
721 | |||
620 | if (!pm) { | 722 | if (!pm) { |
621 | pci_pm_default_suspend(pci_dev); | 723 | pci_pm_default_suspend(pci_dev); |
622 | return 0; | 724 | return 0; |
623 | } | 725 | } |
624 | 726 | ||
625 | pci_dev->state_saved = false; | ||
626 | |||
627 | if (pm->freeze) { | 727 | if (pm->freeze) { |
628 | int error; | 728 | int error; |
629 | 729 | ||
@@ -633,9 +733,6 @@ static int pci_pm_freeze(struct device *dev) | |||
633 | return error; | 733 | return error; |
634 | } | 734 | } |
635 | 735 | ||
636 | if (!pci_dev->state_saved) | ||
637 | pci_save_state(pci_dev); | ||
638 | |||
639 | return 0; | 736 | return 0; |
640 | } | 737 | } |
641 | 738 | ||
@@ -643,20 +740,25 @@ static int pci_pm_freeze_noirq(struct device *dev) | |||
643 | { | 740 | { |
644 | struct pci_dev *pci_dev = to_pci_dev(dev); | 741 | struct pci_dev *pci_dev = to_pci_dev(dev); |
645 | struct device_driver *drv = dev->driver; | 742 | struct device_driver *drv = dev->driver; |
646 | int error = 0; | ||
647 | 743 | ||
648 | if (pci_has_legacy_pm_support(pci_dev)) | 744 | if (pci_has_legacy_pm_support(pci_dev)) |
649 | return pci_legacy_suspend_late(dev, PMSG_FREEZE); | 745 | return pci_legacy_suspend_late(dev, PMSG_FREEZE); |
650 | 746 | ||
651 | if (drv && drv->pm && drv->pm->freeze_noirq) { | 747 | if (drv && drv->pm && drv->pm->freeze_noirq) { |
748 | int error; | ||
749 | |||
652 | error = drv->pm->freeze_noirq(dev); | 750 | error = drv->pm->freeze_noirq(dev); |
653 | suspend_report_result(drv->pm->freeze_noirq, error); | 751 | suspend_report_result(drv->pm->freeze_noirq, error); |
752 | if (error) | ||
753 | return error; | ||
654 | } | 754 | } |
655 | 755 | ||
656 | if (!error) | 756 | if (!pci_dev->state_saved) |
657 | pci_pm_set_unknown_state(pci_dev); | 757 | pci_save_state(pci_dev); |
658 | 758 | ||
659 | return error; | 759 | pci_pm_set_unknown_state(pci_dev); |
760 | |||
761 | return 0; | ||
660 | } | 762 | } |
661 | 763 | ||
662 | static int pci_pm_thaw_noirq(struct device *dev) | 764 | static int pci_pm_thaw_noirq(struct device *dev) |
@@ -699,46 +801,56 @@ static int pci_pm_poweroff(struct device *dev) | |||
699 | { | 801 | { |
700 | struct pci_dev *pci_dev = to_pci_dev(dev); | 802 | struct pci_dev *pci_dev = to_pci_dev(dev); |
701 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 803 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
702 | int error = 0; | ||
703 | 804 | ||
704 | if (pci_has_legacy_pm_support(pci_dev)) | 805 | if (pci_has_legacy_pm_support(pci_dev)) |
705 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); | 806 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); |
706 | 807 | ||
808 | pci_dev->state_saved = false; | ||
809 | |||
707 | if (!pm) { | 810 | if (!pm) { |
708 | pci_pm_default_suspend(pci_dev); | 811 | pci_pm_default_suspend(pci_dev); |
709 | goto Fixup; | 812 | goto Fixup; |
710 | } | 813 | } |
711 | 814 | ||
712 | pci_dev->state_saved = false; | ||
713 | |||
714 | if (pm->poweroff) { | 815 | if (pm->poweroff) { |
816 | int error; | ||
817 | |||
715 | error = pm->poweroff(dev); | 818 | error = pm->poweroff(dev); |
716 | suspend_report_result(pm->poweroff, error); | 819 | suspend_report_result(pm->poweroff, error); |
820 | if (error) | ||
821 | return error; | ||
717 | } | 822 | } |
718 | 823 | ||
719 | if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) | ||
720 | pci_prepare_to_sleep(pci_dev); | ||
721 | |||
722 | Fixup: | 824 | Fixup: |
723 | pci_fixup_device(pci_fixup_suspend, pci_dev); | 825 | pci_fixup_device(pci_fixup_suspend, pci_dev); |
724 | 826 | ||
725 | return error; | 827 | return 0; |
726 | } | 828 | } |
727 | 829 | ||
728 | static int pci_pm_poweroff_noirq(struct device *dev) | 830 | static int pci_pm_poweroff_noirq(struct device *dev) |
729 | { | 831 | { |
832 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
730 | struct device_driver *drv = dev->driver; | 833 | struct device_driver *drv = dev->driver; |
731 | int error = 0; | ||
732 | 834 | ||
733 | if (pci_has_legacy_pm_support(to_pci_dev(dev))) | 835 | if (pci_has_legacy_pm_support(to_pci_dev(dev))) |
734 | return pci_legacy_suspend_late(dev, PMSG_HIBERNATE); | 836 | return pci_legacy_suspend_late(dev, PMSG_HIBERNATE); |
735 | 837 | ||
736 | if (drv && drv->pm && drv->pm->poweroff_noirq) { | 838 | if (!drv || !drv->pm) |
839 | return 0; | ||
840 | |||
841 | if (drv->pm->poweroff_noirq) { | ||
842 | int error; | ||
843 | |||
737 | error = drv->pm->poweroff_noirq(dev); | 844 | error = drv->pm->poweroff_noirq(dev); |
738 | suspend_report_result(drv->pm->poweroff_noirq, error); | 845 | suspend_report_result(drv->pm->poweroff_noirq, error); |
846 | if (error) | ||
847 | return error; | ||
739 | } | 848 | } |
740 | 849 | ||
741 | return error; | 850 | if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) |
851 | pci_prepare_to_sleep(pci_dev); | ||
852 | |||
853 | return 0; | ||
742 | } | 854 | } |
743 | 855 | ||
744 | static int pci_pm_restore_noirq(struct device *dev) | 856 | static int pci_pm_restore_noirq(struct device *dev) |
@@ -852,13 +964,23 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
852 | /* register with core */ | 964 | /* register with core */ |
853 | error = driver_register(&drv->driver); | 965 | error = driver_register(&drv->driver); |
854 | if (error) | 966 | if (error) |
855 | return error; | 967 | goto out; |
856 | 968 | ||
857 | error = pci_create_newid_file(drv); | 969 | error = pci_create_newid_file(drv); |
858 | if (error) | 970 | if (error) |
859 | driver_unregister(&drv->driver); | 971 | goto out_newid; |
860 | 972 | ||
973 | error = pci_create_removeid_file(drv); | ||
974 | if (error) | ||
975 | goto out_removeid; | ||
976 | out: | ||
861 | return error; | 977 | return error; |
978 | |||
979 | out_removeid: | ||
980 | pci_remove_newid_file(drv); | ||
981 | out_newid: | ||
982 | driver_unregister(&drv->driver); | ||
983 | goto out; | ||
862 | } | 984 | } |
863 | 985 | ||
864 | /** | 986 | /** |
@@ -874,6 +996,7 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
874 | void | 996 | void |
875 | pci_unregister_driver(struct pci_driver *drv) | 997 | pci_unregister_driver(struct pci_driver *drv) |
876 | { | 998 | { |
999 | pci_remove_removeid_file(drv); | ||
877 | pci_remove_newid_file(drv); | 1000 | pci_remove_newid_file(drv); |
878 | driver_unregister(&drv->driver); | 1001 | driver_unregister(&drv->driver); |
879 | pci_free_dynids(drv); | 1002 | pci_free_dynids(drv); |
@@ -973,6 +1096,7 @@ struct bus_type pci_bus_type = { | |||
973 | .remove = pci_device_remove, | 1096 | .remove = pci_device_remove, |
974 | .shutdown = pci_device_shutdown, | 1097 | .shutdown = pci_device_shutdown, |
975 | .dev_attrs = pci_dev_attrs, | 1098 | .dev_attrs = pci_dev_attrs, |
1099 | .bus_attrs = pci_bus_attrs, | ||
976 | .pm = PCI_PM_OPS_PTR, | 1100 | .pm = PCI_PM_OPS_PTR, |
977 | }; | 1101 | }; |
978 | 1102 | ||