diff options
-rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 125 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 42 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 2 |
4 files changed, 37 insertions, 134 deletions
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a0d42cf5b0c5..f4aa467c407e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -28,7 +28,6 @@ int init_acpi_device_notify(void); | |||
28 | int acpi_scan_init(void); | 28 | int acpi_scan_init(void); |
29 | void acpi_pci_root_init(void); | 29 | void acpi_pci_root_init(void); |
30 | void acpi_pci_link_init(void); | 30 | void acpi_pci_link_init(void); |
31 | void acpi_pci_root_hp_init(void); | ||
32 | void acpi_processor_init(void); | 31 | void acpi_processor_init(void); |
33 | void acpi_platform_init(void); | 32 | void acpi_platform_init(void); |
34 | int acpi_sysfs_init(void); | 33 | int acpi_sysfs_init(void); |
@@ -89,7 +88,6 @@ void acpi_device_add_finalize(struct acpi_device *device); | |||
89 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); | 88 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); |
90 | int acpi_bind_one(struct device *dev, acpi_handle handle); | 89 | int acpi_bind_one(struct device *dev, acpi_handle handle); |
91 | int acpi_unbind_one(struct device *dev); | 90 | int acpi_unbind_one(struct device *dev); |
92 | void acpi_device_hotplug(void *data, u32 ost_src); | ||
93 | bool acpi_device_is_present(struct acpi_device *adev); | 91 | bool acpi_device_is_present(struct acpi_device *adev); |
94 | 92 | ||
95 | /* -------------------------------------------------------------------------- | 93 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ca05064f3ff7..2dd11e0bac24 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -51,6 +51,12 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
51 | const struct acpi_device_id *not_used); | 51 | const struct acpi_device_id *not_used); |
52 | static void acpi_pci_root_remove(struct acpi_device *device); | 52 | static void acpi_pci_root_remove(struct acpi_device *device); |
53 | 53 | ||
54 | static int acpi_pci_root_scan_dependent(struct acpi_device *adev) | ||
55 | { | ||
56 | acpiphp_check_host_bridge(adev->handle); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
54 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ | 60 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ |
55 | | OSC_PCI_ASPM_SUPPORT \ | 61 | | OSC_PCI_ASPM_SUPPORT \ |
56 | | OSC_PCI_CLOCK_PM_SUPPORT \ | 62 | | OSC_PCI_CLOCK_PM_SUPPORT \ |
@@ -66,7 +72,8 @@ static struct acpi_scan_handler pci_root_handler = { | |||
66 | .attach = acpi_pci_root_add, | 72 | .attach = acpi_pci_root_add, |
67 | .detach = acpi_pci_root_remove, | 73 | .detach = acpi_pci_root_remove, |
68 | .hotplug = { | 74 | .hotplug = { |
69 | .ignore = true, | 75 | .enabled = true, |
76 | .scan_dependent = acpi_pci_root_scan_dependent, | ||
70 | }, | 77 | }, |
71 | }; | 78 | }; |
72 | 79 | ||
@@ -624,119 +631,9 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
624 | void __init acpi_pci_root_init(void) | 631 | void __init acpi_pci_root_init(void) |
625 | { | 632 | { |
626 | acpi_hest_init(); | 633 | acpi_hest_init(); |
627 | 634 | if (acpi_pci_disabled) | |
628 | if (!acpi_pci_disabled) { | ||
629 | pci_acpi_crs_quirks(); | ||
630 | acpi_scan_add_handler(&pci_root_handler); | ||
631 | } | ||
632 | } | ||
633 | /* Support root bridge hotplug */ | ||
634 | |||
635 | static void handle_root_bridge_insertion(acpi_handle handle) | ||
636 | { | ||
637 | struct acpi_device *device = NULL; | ||
638 | |||
639 | acpi_bus_get_device(handle, &device); | ||
640 | if (acpi_device_enumerated(device)) { | ||
641 | dev_printk(KERN_DEBUG, &device->dev, | ||
642 | "acpi device already exists; ignoring notify\n"); | ||
643 | return; | ||
644 | } | ||
645 | |||
646 | if (acpi_bus_scan(handle)) | ||
647 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); | ||
648 | } | ||
649 | |||
650 | static void hotplug_event_root(void *data, u32 type) | ||
651 | { | ||
652 | acpi_handle handle = data; | ||
653 | struct acpi_pci_root *root; | ||
654 | |||
655 | acpi_scan_lock_acquire(); | ||
656 | |||
657 | root = acpi_pci_find_root(handle); | ||
658 | |||
659 | switch (type) { | ||
660 | case ACPI_NOTIFY_BUS_CHECK: | ||
661 | /* bus enumerate */ | ||
662 | acpi_handle_printk(KERN_DEBUG, handle, | ||
663 | "Bus check notify on %s\n", __func__); | ||
664 | if (root) | ||
665 | acpiphp_check_host_bridge(handle); | ||
666 | else | ||
667 | handle_root_bridge_insertion(handle); | ||
668 | |||
669 | break; | ||
670 | |||
671 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
672 | /* device check */ | ||
673 | acpi_handle_printk(KERN_DEBUG, handle, | ||
674 | "Device check notify on %s\n", __func__); | ||
675 | if (!root) | ||
676 | handle_root_bridge_insertion(handle); | ||
677 | break; | ||
678 | |||
679 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
680 | /* request device eject */ | ||
681 | acpi_handle_printk(KERN_DEBUG, handle, | ||
682 | "Device eject notify on %s\n", __func__); | ||
683 | if (!root) | ||
684 | break; | ||
685 | |||
686 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | ||
687 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
688 | get_device(&root->device->dev); | ||
689 | |||
690 | acpi_scan_lock_release(); | ||
691 | |||
692 | acpi_device_hotplug(root->device, ACPI_NOTIFY_EJECT_REQUEST); | ||
693 | return; | 635 | return; |
694 | default: | ||
695 | acpi_handle_warn(handle, | ||
696 | "notify_handler: unknown event type 0x%x\n", | ||
697 | type); | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | acpi_scan_lock_release(); | ||
702 | } | ||
703 | |||
704 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | ||
705 | void *context) | ||
706 | { | ||
707 | acpi_hotplug_execute(hotplug_event_root, handle, type); | ||
708 | } | ||
709 | |||
710 | static acpi_status __init | ||
711 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
712 | { | ||
713 | acpi_status status; | ||
714 | int *count = (int *)context; | ||
715 | |||
716 | if (!acpi_is_root_bridge(handle)) | ||
717 | return AE_OK; | ||
718 | |||
719 | (*count)++; | ||
720 | |||
721 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
722 | handle_hotplug_event_root, NULL); | ||
723 | if (ACPI_FAILURE(status)) | ||
724 | acpi_handle_printk(KERN_DEBUG, handle, | ||
725 | "notify handler is not installed, exit status: %u\n", | ||
726 | (unsigned int)status); | ||
727 | else | ||
728 | acpi_handle_printk(KERN_DEBUG, handle, | ||
729 | "notify handler is installed\n"); | ||
730 | |||
731 | return AE_OK; | ||
732 | } | ||
733 | |||
734 | void __init acpi_pci_root_hp_init(void) | ||
735 | { | ||
736 | int num = 0; | ||
737 | |||
738 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
739 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
740 | 636 | ||
741 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | 637 | pci_acpi_crs_quirks(); |
638 | acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root"); | ||
742 | } | 639 | } |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index dd0ff9de9277..18865c86c463 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -283,17 +283,6 @@ static int acpi_scan_device_check(struct acpi_device *adev) | |||
283 | { | 283 | { |
284 | int error; | 284 | int error; |
285 | 285 | ||
286 | /* | ||
287 | * This function is only called for device objects for which matching | ||
288 | * scan handlers exist. The only situation in which the scan handler is | ||
289 | * not attached to this device object yet is when the device has just | ||
290 | * appeared (either it wasn't present at all before or it was removed | ||
291 | * and then added again). | ||
292 | */ | ||
293 | if (adev->handler) { | ||
294 | dev_warn(&adev->dev, "Already enumerated\n"); | ||
295 | return -EBUSY; | ||
296 | } | ||
297 | error = acpi_bus_scan(adev->handle); | 286 | error = acpi_bus_scan(adev->handle); |
298 | if (error) { | 287 | if (error) { |
299 | dev_warn(&adev->dev, "Namespace scan failure\n"); | 288 | dev_warn(&adev->dev, "Namespace scan failure\n"); |
@@ -309,10 +298,11 @@ static int acpi_scan_device_check(struct acpi_device *adev) | |||
309 | return 0; | 298 | return 0; |
310 | } | 299 | } |
311 | 300 | ||
312 | void acpi_device_hotplug(void *data, u32 src) | 301 | static void acpi_device_hotplug(void *data, u32 src) |
313 | { | 302 | { |
314 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 303 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
315 | struct acpi_device *adev = data; | 304 | struct acpi_device *adev = data; |
305 | struct acpi_scan_handler *handler; | ||
316 | int error; | 306 | int error; |
317 | 307 | ||
318 | lock_device_hotplug(); | 308 | lock_device_hotplug(); |
@@ -326,12 +316,32 @@ void acpi_device_hotplug(void *data, u32 src) | |||
326 | if (adev->handle == INVALID_ACPI_HANDLE) | 316 | if (adev->handle == INVALID_ACPI_HANDLE) |
327 | goto out; | 317 | goto out; |
328 | 318 | ||
319 | handler = adev->handler; | ||
320 | |||
329 | switch (src) { | 321 | switch (src) { |
330 | case ACPI_NOTIFY_BUS_CHECK: | 322 | case ACPI_NOTIFY_BUS_CHECK: |
331 | error = acpi_bus_scan(adev->handle); | 323 | if (handler) { |
324 | error = handler->hotplug.scan_dependent ? | ||
325 | handler->hotplug.scan_dependent(adev) : | ||
326 | acpi_bus_scan(adev->handle); | ||
327 | } else { | ||
328 | error = acpi_scan_device_check(adev); | ||
329 | } | ||
332 | break; | 330 | break; |
333 | case ACPI_NOTIFY_DEVICE_CHECK: | 331 | case ACPI_NOTIFY_DEVICE_CHECK: |
334 | error = acpi_scan_device_check(adev); | 332 | /* |
333 | * This code is only run for device objects for which matching | ||
334 | * scan handlers exist. The only situation in which the scan | ||
335 | * handler is not attached to this device object yet is when the | ||
336 | * device has just appeared (either it wasn't present at all | ||
337 | * before or it was removed and then added again). | ||
338 | */ | ||
339 | if (adev->handler) { | ||
340 | dev_warn(&adev->dev, "Already enumerated\n"); | ||
341 | error = -EBUSY; | ||
342 | } else { | ||
343 | error = acpi_scan_device_check(adev); | ||
344 | } | ||
335 | break; | 345 | break; |
336 | case ACPI_NOTIFY_EJECT_REQUEST: | 346 | case ACPI_NOTIFY_EJECT_REQUEST: |
337 | case ACPI_OST_EC_OSPM_EJECT: | 347 | case ACPI_OST_EC_OSPM_EJECT: |
@@ -1805,7 +1815,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) | |||
1805 | */ | 1815 | */ |
1806 | list_for_each_entry(hwid, &pnp.ids, list) { | 1816 | list_for_each_entry(hwid, &pnp.ids, list) { |
1807 | handler = acpi_scan_match_handler(hwid->id, NULL); | 1817 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1808 | if (handler && !handler->hotplug.ignore) { | 1818 | if (handler) { |
1809 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1819 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1810 | acpi_hotplug_notify_cb, handler); | 1820 | acpi_hotplug_notify_cb, handler); |
1811 | break; | 1821 | break; |
@@ -2083,8 +2093,6 @@ int __init acpi_scan_init(void) | |||
2083 | 2093 | ||
2084 | acpi_update_all_gpes(); | 2094 | acpi_update_all_gpes(); |
2085 | 2095 | ||
2086 | acpi_pci_root_hp_init(); | ||
2087 | |||
2088 | out: | 2096 | out: |
2089 | mutex_unlock(&acpi_scan_lock); | 2097 | mutex_unlock(&acpi_scan_lock); |
2090 | return result; | 2098 | return result; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e748dbfca9d5..2359c69f1680 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -100,8 +100,8 @@ enum acpi_hotplug_mode { | |||
100 | struct acpi_hotplug_profile { | 100 | struct acpi_hotplug_profile { |
101 | struct kobject kobj; | 101 | struct kobject kobj; |
102 | bool enabled:1; | 102 | bool enabled:1; |
103 | bool ignore:1; | ||
104 | enum acpi_hotplug_mode mode; | 103 | enum acpi_hotplug_mode mode; |
104 | int (*scan_dependent)(struct acpi_device *adev); | ||
105 | }; | 105 | }; |
106 | 106 | ||
107 | static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( | 107 | static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( |