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( |
