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.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index cd929aed3613..7c7a388c85ab 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/**
@@ -709,6 +730,17 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
709 return (unsigned int)sta; 730 return (unsigned int)sta;
710} 731}
711 732
733static inline bool device_status_valid(unsigned int sta)
734{
735 /*
736 * ACPI spec says that _STA may return bit 0 clear with bit 3 set
737 * if the device is valid but does not require a device driver to be
738 * loaded (Section 6.3.7 of ACPI 5.0A).
739 */
740 unsigned int mask = ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_FUNCTIONING;
741 return (sta & mask) == mask;
742}
743
712/** 744/**
713 * trim_stale_devices - remove PCI devices that are not responding. 745 * trim_stale_devices - remove PCI devices that are not responding.
714 * @dev: PCI device to start walking the hierarchy from. 746 * @dev: PCI device to start walking the hierarchy from.
@@ -724,7 +756,7 @@ static void trim_stale_devices(struct pci_dev *dev)
724 unsigned long long sta; 756 unsigned long long sta;
725 757
726 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 758 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
727 alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL) 759 alive = (ACPI_SUCCESS(status) && device_status_valid(sta))
728 || acpiphp_no_hotplug(handle); 760 || acpiphp_no_hotplug(handle);
729 } 761 }
730 if (!alive) { 762 if (!alive) {
@@ -742,7 +774,7 @@ static void trim_stale_devices(struct pci_dev *dev)
742 774
743 /* The device is a bridge. so check the bus below it. */ 775 /* The device is a bridge. so check the bus below it. */
744 pm_runtime_get_sync(&dev->dev); 776 pm_runtime_get_sync(&dev->dev);
745 list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) 777 list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
746 trim_stale_devices(child); 778 trim_stale_devices(child);
747 779
748 pm_runtime_put(&dev->dev); 780 pm_runtime_put(&dev->dev);
@@ -771,10 +803,10 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
771 mutex_lock(&slot->crit_sect); 803 mutex_lock(&slot->crit_sect);
772 if (slot_no_hotplug(slot)) { 804 if (slot_no_hotplug(slot)) {
773 ; /* do nothing */ 805 ; /* do nothing */
774 } else if (get_slot_status(slot) == ACPI_STA_ALL) { 806 } else if (device_status_valid(get_slot_status(slot))) {
775 /* remove stale devices if any */ 807 /* remove stale devices if any */
776 list_for_each_entry_safe(dev, tmp, &bus->devices, 808 list_for_each_entry_safe_reverse(dev, tmp,
777 bus_list) 809 &bus->devices, bus_list)
778 if (PCI_SLOT(dev->devfn) == slot->device) 810 if (PCI_SLOT(dev->devfn) == slot->device)
779 trim_stale_devices(dev); 811 trim_stale_devices(dev);
780 812
@@ -805,7 +837,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
805 int i; 837 int i;
806 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; 838 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
807 839
808 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { 840 list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
809 for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { 841 for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
810 struct resource *res = &dev->resource[i]; 842 struct resource *res = &dev->resource[i];
811 if ((res->flags & type_mask) && !res->start && 843 if ((res->flags & type_mask) && !res->start &&
@@ -829,7 +861,11 @@ void acpiphp_check_host_bridge(acpi_handle handle)
829 861
830 bridge = acpiphp_handle_to_bridge(handle); 862 bridge = acpiphp_handle_to_bridge(handle);
831 if (bridge) { 863 if (bridge) {
864 pci_lock_rescan_remove();
865
832 acpiphp_check_bridge(bridge); 866 acpiphp_check_bridge(bridge);
867
868 pci_unlock_rescan_remove();
833 put_bridge(bridge); 869 put_bridge(bridge);
834 } 870 }
835} 871}
@@ -852,6 +888,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
852 888
853 mutex_unlock(&acpiphp_context_lock); 889 mutex_unlock(&acpiphp_context_lock);
854 890
891 pci_lock_rescan_remove();
855 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); 892 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
856 893
857 switch (type) { 894 switch (type) {
@@ -905,6 +942,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
905 break; 942 break;
906 } 943 }
907 944
945 pci_unlock_rescan_remove();
908 if (bridge) 946 if (bridge)
909 put_bridge(bridge); 947 put_bridge(bridge);
910} 948}
@@ -915,11 +953,9 @@ static void hotplug_event_work(void *data, u32 type)
915 acpi_handle handle = context->handle; 953 acpi_handle handle = context->handle;
916 954
917 acpi_scan_lock_acquire(); 955 acpi_scan_lock_acquire();
918 pci_lock_rescan_remove();
919 956
920 hotplug_event(handle, type, context); 957 hotplug_event(handle, type, context);
921 958
922 pci_unlock_rescan_remove();
923 acpi_scan_lock_release(); 959 acpi_scan_lock_release();
924 acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); 960 acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
925 put_bridge(context->func.parent); 961 put_bridge(context->func.parent);
@@ -937,6 +973,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
937{ 973{
938 struct acpiphp_context *context; 974 struct acpiphp_context *context;
939 u32 ost_code = ACPI_OST_SC_SUCCESS; 975 u32 ost_code = ACPI_OST_SC_SUCCESS;
976 acpi_status status;
940 977
941 switch (type) { 978 switch (type) {
942 case ACPI_NOTIFY_BUS_CHECK: 979 case ACPI_NOTIFY_BUS_CHECK:
@@ -972,13 +1009,20 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
972 1009
973 mutex_lock(&acpiphp_context_lock); 1010 mutex_lock(&acpiphp_context_lock);
974 context = acpiphp_get_context(handle); 1011 context = acpiphp_get_context(handle);
975 if (context && !WARN_ON(context->handle != handle)) { 1012 if (!context || WARN_ON(context->handle != handle)
976 get_bridge(context->func.parent); 1013 || context->func.parent->is_going_away)
977 acpiphp_put_context(context); 1014 goto err_out;
978 acpi_hotplug_execute(hotplug_event_work, context, type); 1015
1016 get_bridge(context->func.parent);
1017 acpiphp_put_context(context);
1018 status = acpi_hotplug_execute(hotplug_event_work, context, type);
1019 if (ACPI_SUCCESS(status)) {
979 mutex_unlock(&acpiphp_context_lock); 1020 mutex_unlock(&acpiphp_context_lock);
980 return; 1021 return;
981 } 1022 }
1023 put_bridge(context->func.parent);
1024
1025 err_out:
982 mutex_unlock(&acpiphp_context_lock); 1026 mutex_unlock(&acpiphp_context_lock);
983 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; 1027 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
984 1028