diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cd929aed3613..e2a783fdb98f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -210,10 +210,29 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | |||
| 210 | } | 210 | } |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static void dock_event(acpi_handle handle, u32 type, void *data) | ||
| 214 | { | ||
| 215 | struct acpiphp_context *context; | ||
| 216 | |||
| 217 | mutex_lock(&acpiphp_context_lock); | ||
| 218 | context = acpiphp_get_context(handle); | ||
| 219 | if (!context || WARN_ON(context->handle != handle) | ||
| 220 | || context->func.parent->is_going_away) { | ||
| 221 | mutex_unlock(&acpiphp_context_lock); | ||
| 222 | return; | ||
| 223 | } | ||
| 224 | get_bridge(context->func.parent); | ||
| 225 | acpiphp_put_context(context); | ||
| 226 | mutex_unlock(&acpiphp_context_lock); | ||
| 227 | |||
| 228 | hotplug_event(handle, type, data); | ||
| 229 | |||
| 230 | put_bridge(context->func.parent); | ||
| 231 | } | ||
| 213 | 232 | ||
| 214 | static const struct acpi_dock_ops acpiphp_dock_ops = { | 233 | static const struct acpi_dock_ops acpiphp_dock_ops = { |
| 215 | .fixup = post_dock_fixups, | 234 | .fixup = post_dock_fixups, |
| 216 | .handler = hotplug_event, | 235 | .handler = dock_event, |
| 217 | }; | 236 | }; |
| 218 | 237 | ||
| 219 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ | 238 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ |
| @@ -441,7 +460,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
| 441 | list_del(&bridge->list); | 460 | list_del(&bridge->list); |
| 442 | mutex_unlock(&bridge_mutex); | 461 | mutex_unlock(&bridge_mutex); |
| 443 | 462 | ||
| 463 | mutex_lock(&acpiphp_context_lock); | ||
| 444 | bridge->is_going_away = true; | 464 | bridge->is_going_away = true; |
| 465 | mutex_unlock(&acpiphp_context_lock); | ||
| 445 | } | 466 | } |
| 446 | 467 | ||
| 447 | /** | 468 | /** |
| @@ -742,7 +763,7 @@ static void trim_stale_devices(struct pci_dev *dev) | |||
| 742 | 763 | ||
| 743 | /* The device is a bridge. so check the bus below it. */ | 764 | /* The device is a bridge. so check the bus below it. */ |
| 744 | pm_runtime_get_sync(&dev->dev); | 765 | pm_runtime_get_sync(&dev->dev); |
| 745 | list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) | 766 | list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list) |
| 746 | trim_stale_devices(child); | 767 | trim_stale_devices(child); |
| 747 | 768 | ||
| 748 | pm_runtime_put(&dev->dev); | 769 | pm_runtime_put(&dev->dev); |
| @@ -773,8 +794,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
| 773 | ; /* do nothing */ | 794 | ; /* do nothing */ |
| 774 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { | 795 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { |
| 775 | /* remove stale devices if any */ | 796 | /* remove stale devices if any */ |
| 776 | list_for_each_entry_safe(dev, tmp, &bus->devices, | 797 | list_for_each_entry_safe_reverse(dev, tmp, |
| 777 | bus_list) | 798 | &bus->devices, bus_list) |
| 778 | if (PCI_SLOT(dev->devfn) == slot->device) | 799 | if (PCI_SLOT(dev->devfn) == slot->device) |
| 779 | trim_stale_devices(dev); | 800 | trim_stale_devices(dev); |
| 780 | 801 | ||
| @@ -805,7 +826,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
| 805 | int i; | 826 | int i; |
| 806 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 827 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
| 807 | 828 | ||
| 808 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { | 829 | list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) { |
| 809 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { | 830 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { |
| 810 | struct resource *res = &dev->resource[i]; | 831 | struct resource *res = &dev->resource[i]; |
| 811 | if ((res->flags & type_mask) && !res->start && | 832 | if ((res->flags & type_mask) && !res->start && |
| @@ -829,7 +850,11 @@ void acpiphp_check_host_bridge(acpi_handle handle) | |||
| 829 | 850 | ||
| 830 | bridge = acpiphp_handle_to_bridge(handle); | 851 | bridge = acpiphp_handle_to_bridge(handle); |
| 831 | if (bridge) { | 852 | if (bridge) { |
| 853 | pci_lock_rescan_remove(); | ||
| 854 | |||
| 832 | acpiphp_check_bridge(bridge); | 855 | acpiphp_check_bridge(bridge); |
| 856 | |||
| 857 | pci_unlock_rescan_remove(); | ||
| 833 | put_bridge(bridge); | 858 | put_bridge(bridge); |
| 834 | } | 859 | } |
| 835 | } | 860 | } |
| @@ -852,6 +877,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 852 | 877 | ||
| 853 | mutex_unlock(&acpiphp_context_lock); | 878 | mutex_unlock(&acpiphp_context_lock); |
| 854 | 879 | ||
| 880 | pci_lock_rescan_remove(); | ||
| 855 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 881 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
| 856 | 882 | ||
| 857 | switch (type) { | 883 | switch (type) { |
| @@ -905,6 +931,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 905 | break; | 931 | break; |
| 906 | } | 932 | } |
| 907 | 933 | ||
| 934 | pci_unlock_rescan_remove(); | ||
| 908 | if (bridge) | 935 | if (bridge) |
| 909 | put_bridge(bridge); | 936 | put_bridge(bridge); |
| 910 | } | 937 | } |
| @@ -915,11 +942,9 @@ static void hotplug_event_work(void *data, u32 type) | |||
| 915 | acpi_handle handle = context->handle; | 942 | acpi_handle handle = context->handle; |
| 916 | 943 | ||
| 917 | acpi_scan_lock_acquire(); | 944 | acpi_scan_lock_acquire(); |
| 918 | pci_lock_rescan_remove(); | ||
| 919 | 945 | ||
| 920 | hotplug_event(handle, type, context); | 946 | hotplug_event(handle, type, context); |
| 921 | 947 | ||
| 922 | pci_unlock_rescan_remove(); | ||
| 923 | acpi_scan_lock_release(); | 948 | acpi_scan_lock_release(); |
| 924 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); | 949 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); |
| 925 | put_bridge(context->func.parent); | 950 | put_bridge(context->func.parent); |
| @@ -937,6 +962,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 937 | { | 962 | { |
| 938 | struct acpiphp_context *context; | 963 | struct acpiphp_context *context; |
| 939 | u32 ost_code = ACPI_OST_SC_SUCCESS; | 964 | u32 ost_code = ACPI_OST_SC_SUCCESS; |
| 965 | acpi_status status; | ||
| 940 | 966 | ||
| 941 | switch (type) { | 967 | switch (type) { |
| 942 | case ACPI_NOTIFY_BUS_CHECK: | 968 | case ACPI_NOTIFY_BUS_CHECK: |
| @@ -972,13 +998,20 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 972 | 998 | ||
| 973 | mutex_lock(&acpiphp_context_lock); | 999 | mutex_lock(&acpiphp_context_lock); |
| 974 | context = acpiphp_get_context(handle); | 1000 | context = acpiphp_get_context(handle); |
| 975 | if (context && !WARN_ON(context->handle != handle)) { | 1001 | if (!context || WARN_ON(context->handle != handle) |
| 976 | get_bridge(context->func.parent); | 1002 | || context->func.parent->is_going_away) |
| 977 | acpiphp_put_context(context); | 1003 | goto err_out; |
| 978 | acpi_hotplug_execute(hotplug_event_work, context, type); | 1004 | |
| 1005 | get_bridge(context->func.parent); | ||
| 1006 | acpiphp_put_context(context); | ||
| 1007 | status = acpi_hotplug_execute(hotplug_event_work, context, type); | ||
| 1008 | if (ACPI_SUCCESS(status)) { | ||
| 979 | mutex_unlock(&acpiphp_context_lock); | 1009 | mutex_unlock(&acpiphp_context_lock); |
| 980 | return; | 1010 | return; |
| 981 | } | 1011 | } |
| 1012 | put_bridge(context->func.parent); | ||
| 1013 | |||
| 1014 | err_out: | ||
| 982 | mutex_unlock(&acpiphp_context_lock); | 1015 | mutex_unlock(&acpiphp_context_lock); |
| 983 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 1016 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
| 984 | 1017 | ||
