aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c55
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
213static 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
214static const struct acpi_dock_ops acpiphp_dock_ops = { 233static 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