diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-10 17:15:02 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-10 17:15:02 -0400 |
commit | 08e97ff2779ffd3e6eb05d28bafdbc1fbb531d20 (patch) | |
tree | ccb6de2eb69a1f6260cc9b7d442be2c394a80dda /drivers/pci | |
parent | 85fb0a1c35d86ed9a4de8d6cba79ba0801f7a1f7 (diff) | |
parent | a47d8c8e72a5fa2e69117674c4b0b6cc79c5bc53 (diff) |
Merge branch 'acpi-pci-hotplug'
* acpi-pci-hotplug:
ACPI / hotplug / PCI: Avoid parent bus rescans on spurious device checks
ACPI / hotplug / PCI: Use _OST to notify firmware about notify status
ACPI / hotplug / PCI: Avoid doing too much for spurious notifies
ACPI / hotplug / PCI: Don't trim devices before scanning the namespace
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index f6488adf3af1..0b7d23b4ad95 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -487,7 +487,6 @@ static void acpiphp_bus_add(acpi_handle handle) | |||
487 | { | 487 | { |
488 | struct acpi_device *adev = NULL; | 488 | struct acpi_device *adev = NULL; |
489 | 489 | ||
490 | acpiphp_bus_trim(handle); | ||
491 | acpi_bus_scan(handle); | 490 | acpi_bus_scan(handle); |
492 | acpi_bus_get_device(handle, &adev); | 491 | acpi_bus_get_device(handle, &adev); |
493 | if (adev) | 492 | if (adev) |
@@ -529,6 +528,16 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) | |||
529 | } | 528 | } |
530 | } | 529 | } |
531 | 530 | ||
531 | static int acpiphp_rescan_slot(struct acpiphp_slot *slot) | ||
532 | { | ||
533 | struct acpiphp_func *func; | ||
534 | |||
535 | list_for_each_entry(func, &slot->funcs, sibling) | ||
536 | acpiphp_bus_add(func_to_handle(func)); | ||
537 | |||
538 | return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0)); | ||
539 | } | ||
540 | |||
532 | /** | 541 | /** |
533 | * enable_slot - enable, configure a slot | 542 | * enable_slot - enable, configure a slot |
534 | * @slot: slot to be enabled | 543 | * @slot: slot to be enabled |
@@ -543,12 +552,9 @@ static void __ref enable_slot(struct acpiphp_slot *slot) | |||
543 | struct acpiphp_func *func; | 552 | struct acpiphp_func *func; |
544 | int max, pass; | 553 | int max, pass; |
545 | LIST_HEAD(add_list); | 554 | LIST_HEAD(add_list); |
555 | int nr_found; | ||
546 | 556 | ||
547 | list_for_each_entry(func, &slot->funcs, sibling) | 557 | nr_found = acpiphp_rescan_slot(slot); |
548 | acpiphp_bus_add(func_to_handle(func)); | ||
549 | |||
550 | pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); | ||
551 | |||
552 | max = acpiphp_max_busnr(bus); | 558 | max = acpiphp_max_busnr(bus); |
553 | for (pass = 0; pass < 2; pass++) { | 559 | for (pass = 0; pass < 2; pass++) { |
554 | list_for_each_entry(dev, &bus->devices, bus_list) { | 560 | list_for_each_entry(dev, &bus->devices, bus_list) { |
@@ -567,8 +573,11 @@ static void __ref enable_slot(struct acpiphp_slot *slot) | |||
567 | } | 573 | } |
568 | } | 574 | } |
569 | } | 575 | } |
570 | |||
571 | __pci_bus_assign_resources(bus, &add_list, NULL); | 576 | __pci_bus_assign_resources(bus, &add_list, NULL); |
577 | /* Nothing more to do here if there are no new devices on this bus. */ | ||
578 | if (!nr_found && (slot->flags & SLOT_ENABLED)) | ||
579 | return; | ||
580 | |||
572 | acpiphp_sanitize_bus(bus); | 581 | acpiphp_sanitize_bus(bus); |
573 | acpiphp_set_hpp_values(bus); | 582 | acpiphp_set_hpp_values(bus); |
574 | acpiphp_set_acpi_region(slot); | 583 | acpiphp_set_acpi_region(slot); |
@@ -837,11 +846,22 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
837 | case ACPI_NOTIFY_DEVICE_CHECK: | 846 | case ACPI_NOTIFY_DEVICE_CHECK: |
838 | /* device check */ | 847 | /* device check */ |
839 | dbg("%s: Device check notify on %s\n", __func__, objname); | 848 | dbg("%s: Device check notify on %s\n", __func__, objname); |
840 | if (bridge) | 849 | if (bridge) { |
841 | acpiphp_check_bridge(bridge); | 850 | acpiphp_check_bridge(bridge); |
842 | else | 851 | } else { |
843 | acpiphp_check_bridge(func->parent); | 852 | struct acpiphp_slot *slot = func->slot; |
853 | int ret; | ||
844 | 854 | ||
855 | /* | ||
856 | * Check if anything has changed in the slot and rescan | ||
857 | * from the parent if that's the case. | ||
858 | */ | ||
859 | mutex_lock(&slot->crit_sect); | ||
860 | ret = acpiphp_rescan_slot(slot); | ||
861 | mutex_unlock(&slot->crit_sect); | ||
862 | if (ret) | ||
863 | acpiphp_check_bridge(func->parent); | ||
864 | } | ||
845 | break; | 865 | break; |
846 | 866 | ||
847 | case ACPI_NOTIFY_EJECT_REQUEST: | 867 | case ACPI_NOTIFY_EJECT_REQUEST: |
@@ -867,6 +887,8 @@ static void hotplug_event_work(struct work_struct *work) | |||
867 | hotplug_event(hp_work->handle, hp_work->type, context); | 887 | hotplug_event(hp_work->handle, hp_work->type, context); |
868 | 888 | ||
869 | acpi_scan_lock_release(); | 889 | acpi_scan_lock_release(); |
890 | acpi_evaluate_hotplug_ost(hp_work->handle, hp_work->type, | ||
891 | ACPI_OST_SC_SUCCESS, NULL); | ||
870 | kfree(hp_work); /* allocated in handle_hotplug_event() */ | 892 | kfree(hp_work); /* allocated in handle_hotplug_event() */ |
871 | put_bridge(context->func.parent); | 893 | put_bridge(context->func.parent); |
872 | } | 894 | } |
@@ -882,11 +904,15 @@ static void hotplug_event_work(struct work_struct *work) | |||
882 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | 904 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) |
883 | { | 905 | { |
884 | struct acpiphp_context *context; | 906 | struct acpiphp_context *context; |
907 | u32 ost_code = ACPI_OST_SC_SUCCESS; | ||
885 | 908 | ||
886 | switch (type) { | 909 | switch (type) { |
887 | case ACPI_NOTIFY_BUS_CHECK: | 910 | case ACPI_NOTIFY_BUS_CHECK: |
888 | case ACPI_NOTIFY_DEVICE_CHECK: | 911 | case ACPI_NOTIFY_DEVICE_CHECK: |
912 | break; | ||
889 | case ACPI_NOTIFY_EJECT_REQUEST: | 913 | case ACPI_NOTIFY_EJECT_REQUEST: |
914 | ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS; | ||
915 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
890 | break; | 916 | break; |
891 | 917 | ||
892 | case ACPI_NOTIFY_DEVICE_WAKE: | 918 | case ACPI_NOTIFY_DEVICE_WAKE: |
@@ -895,20 +921,21 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
895 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 921 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
896 | acpi_handle_err(handle, "Device cannot be configured due " | 922 | acpi_handle_err(handle, "Device cannot be configured due " |
897 | "to a frequency mismatch\n"); | 923 | "to a frequency mismatch\n"); |
898 | return; | 924 | goto out; |
899 | 925 | ||
900 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 926 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
901 | acpi_handle_err(handle, "Device cannot be configured due " | 927 | acpi_handle_err(handle, "Device cannot be configured due " |
902 | "to a bus mode mismatch\n"); | 928 | "to a bus mode mismatch\n"); |
903 | return; | 929 | goto out; |
904 | 930 | ||
905 | case ACPI_NOTIFY_POWER_FAULT: | 931 | case ACPI_NOTIFY_POWER_FAULT: |
906 | acpi_handle_err(handle, "Device has suffered a power fault\n"); | 932 | acpi_handle_err(handle, "Device has suffered a power fault\n"); |
907 | return; | 933 | goto out; |
908 | 934 | ||
909 | default: | 935 | default: |
910 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); | 936 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); |
911 | return; | 937 | ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; |
938 | goto out; | ||
912 | } | 939 | } |
913 | 940 | ||
914 | mutex_lock(&acpiphp_context_lock); | 941 | mutex_lock(&acpiphp_context_lock); |
@@ -917,8 +944,14 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
917 | get_bridge(context->func.parent); | 944 | get_bridge(context->func.parent); |
918 | acpiphp_put_context(context); | 945 | acpiphp_put_context(context); |
919 | alloc_acpi_hp_work(handle, type, context, hotplug_event_work); | 946 | alloc_acpi_hp_work(handle, type, context, hotplug_event_work); |
947 | mutex_unlock(&acpiphp_context_lock); | ||
948 | return; | ||
920 | } | 949 | } |
921 | mutex_unlock(&acpiphp_context_lock); | 950 | mutex_unlock(&acpiphp_context_lock); |
951 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
952 | |||
953 | out: | ||
954 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
922 | } | 955 | } |
923 | 956 | ||
924 | /* | 957 | /* |