diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 43 |
3 files changed, 43 insertions, 7 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 1592dbe4f904..b6162be4df40 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -77,6 +77,8 @@ struct acpiphp_bridge { | |||
77 | 77 | ||
78 | /* PCI-to-PCI bridge device */ | 78 | /* PCI-to-PCI bridge device */ |
79 | struct pci_dev *pci_dev; | 79 | struct pci_dev *pci_dev; |
80 | |||
81 | bool is_going_away; | ||
80 | }; | 82 | }; |
81 | 83 | ||
82 | 84 | ||
@@ -150,6 +152,7 @@ struct acpiphp_attention_info | |||
150 | /* slot flags */ | 152 | /* slot flags */ |
151 | 153 | ||
152 | #define SLOT_ENABLED (0x00000001) | 154 | #define SLOT_ENABLED (0x00000001) |
155 | #define SLOT_IS_GOING_AWAY (0x00000002) | ||
153 | 156 | ||
154 | /* function flags */ | 157 | /* function flags */ |
155 | 158 | ||
@@ -169,7 +172,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); | |||
169 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); | 172 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); |
170 | 173 | ||
171 | int acpiphp_enable_slot(struct acpiphp_slot *slot); | 174 | int acpiphp_enable_slot(struct acpiphp_slot *slot); |
172 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | 175 | int acpiphp_disable_slot(struct acpiphp_slot *slot); |
173 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); | 176 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); |
174 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); | 177 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); |
175 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); | 178 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); |
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index dca66bc44578..728c31f4c2c5 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -156,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
156 | pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); | 156 | pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); |
157 | 157 | ||
158 | /* disable the specified slot */ | 158 | /* disable the specified slot */ |
159 | return acpiphp_disable_and_eject_slot(slot->acpi_slot); | 159 | return acpiphp_disable_slot(slot->acpi_slot); |
160 | } | 160 | } |
161 | 161 | ||
162 | 162 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1cf605f67673..641ba6761bd7 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -430,6 +430,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
430 | pr_err("failed to remove notify handler\n"); | 430 | pr_err("failed to remove notify handler\n"); |
431 | } | 431 | } |
432 | } | 432 | } |
433 | slot->flags |= SLOT_IS_GOING_AWAY; | ||
433 | if (slot->slot) | 434 | if (slot->slot) |
434 | acpiphp_unregister_hotplug_slot(slot); | 435 | acpiphp_unregister_hotplug_slot(slot); |
435 | } | 436 | } |
@@ -437,6 +438,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
437 | mutex_lock(&bridge_mutex); | 438 | mutex_lock(&bridge_mutex); |
438 | list_del(&bridge->list); | 439 | list_del(&bridge->list); |
439 | mutex_unlock(&bridge_mutex); | 440 | mutex_unlock(&bridge_mutex); |
441 | |||
442 | bridge->is_going_away = true; | ||
440 | } | 443 | } |
441 | 444 | ||
442 | /** | 445 | /** |
@@ -736,6 +739,10 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
736 | { | 739 | { |
737 | struct acpiphp_slot *slot; | 740 | struct acpiphp_slot *slot; |
738 | 741 | ||
742 | /* Bail out if the bridge is going away. */ | ||
743 | if (bridge->is_going_away) | ||
744 | return; | ||
745 | |||
739 | list_for_each_entry(slot, &bridge->slots, node) { | 746 | list_for_each_entry(slot, &bridge->slots, node) { |
740 | struct pci_bus *bus = slot->bus; | 747 | struct pci_bus *bus = slot->bus; |
741 | struct pci_dev *dev, *tmp; | 748 | struct pci_dev *dev, *tmp; |
@@ -805,6 +812,8 @@ void acpiphp_check_host_bridge(acpi_handle handle) | |||
805 | } | 812 | } |
806 | } | 813 | } |
807 | 814 | ||
815 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | ||
816 | |||
808 | static void hotplug_event(acpi_handle handle, u32 type, void *data) | 817 | static void hotplug_event(acpi_handle handle, u32 type, void *data) |
809 | { | 818 | { |
810 | struct acpiphp_context *context = data; | 819 | struct acpiphp_context *context = data; |
@@ -834,6 +843,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
834 | } else { | 843 | } else { |
835 | struct acpiphp_slot *slot = func->slot; | 844 | struct acpiphp_slot *slot = func->slot; |
836 | 845 | ||
846 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
847 | break; | ||
848 | |||
837 | mutex_lock(&slot->crit_sect); | 849 | mutex_lock(&slot->crit_sect); |
838 | enable_slot(slot); | 850 | enable_slot(slot); |
839 | mutex_unlock(&slot->crit_sect); | 851 | mutex_unlock(&slot->crit_sect); |
@@ -849,6 +861,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
849 | struct acpiphp_slot *slot = func->slot; | 861 | struct acpiphp_slot *slot = func->slot; |
850 | int ret; | 862 | int ret; |
851 | 863 | ||
864 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
865 | break; | ||
866 | |||
852 | /* | 867 | /* |
853 | * Check if anything has changed in the slot and rescan | 868 | * Check if anything has changed in the slot and rescan |
854 | * from the parent if that's the case. | 869 | * from the parent if that's the case. |
@@ -878,9 +893,11 @@ static void hotplug_event_work(void *data, u32 type) | |||
878 | acpi_handle handle = context->handle; | 893 | acpi_handle handle = context->handle; |
879 | 894 | ||
880 | acpi_scan_lock_acquire(); | 895 | acpi_scan_lock_acquire(); |
896 | pci_lock_rescan_remove(); | ||
881 | 897 | ||
882 | hotplug_event(handle, type, context); | 898 | hotplug_event(handle, type, context); |
883 | 899 | ||
900 | pci_unlock_rescan_remove(); | ||
884 | acpi_scan_lock_release(); | 901 | acpi_scan_lock_release(); |
885 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); | 902 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); |
886 | put_bridge(context->func.parent); | 903 | put_bridge(context->func.parent); |
@@ -1048,12 +1065,19 @@ void acpiphp_remove_slots(struct pci_bus *bus) | |||
1048 | */ | 1065 | */ |
1049 | int acpiphp_enable_slot(struct acpiphp_slot *slot) | 1066 | int acpiphp_enable_slot(struct acpiphp_slot *slot) |
1050 | { | 1067 | { |
1068 | pci_lock_rescan_remove(); | ||
1069 | |||
1070 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
1071 | return -ENODEV; | ||
1072 | |||
1051 | mutex_lock(&slot->crit_sect); | 1073 | mutex_lock(&slot->crit_sect); |
1052 | /* configure all functions */ | 1074 | /* configure all functions */ |
1053 | if (!(slot->flags & SLOT_ENABLED)) | 1075 | if (!(slot->flags & SLOT_ENABLED)) |
1054 | enable_slot(slot); | 1076 | enable_slot(slot); |
1055 | 1077 | ||
1056 | mutex_unlock(&slot->crit_sect); | 1078 | mutex_unlock(&slot->crit_sect); |
1079 | |||
1080 | pci_unlock_rescan_remove(); | ||
1057 | return 0; | 1081 | return 0; |
1058 | } | 1082 | } |
1059 | 1083 | ||
@@ -1061,10 +1085,12 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
1061 | * acpiphp_disable_and_eject_slot - power off and eject slot | 1085 | * acpiphp_disable_and_eject_slot - power off and eject slot |
1062 | * @slot: ACPI PHP slot | 1086 | * @slot: ACPI PHP slot |
1063 | */ | 1087 | */ |
1064 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | 1088 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) |
1065 | { | 1089 | { |
1066 | struct acpiphp_func *func; | 1090 | struct acpiphp_func *func; |
1067 | int retval = 0; | 1091 | |
1092 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
1093 | return -ENODEV; | ||
1068 | 1094 | ||
1069 | mutex_lock(&slot->crit_sect); | 1095 | mutex_lock(&slot->crit_sect); |
1070 | 1096 | ||
@@ -1082,9 +1108,18 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | |||
1082 | } | 1108 | } |
1083 | 1109 | ||
1084 | mutex_unlock(&slot->crit_sect); | 1110 | mutex_unlock(&slot->crit_sect); |
1085 | return retval; | 1111 | return 0; |
1086 | } | 1112 | } |
1087 | 1113 | ||
1114 | int acpiphp_disable_slot(struct acpiphp_slot *slot) | ||
1115 | { | ||
1116 | int ret; | ||
1117 | |||
1118 | pci_lock_rescan_remove(); | ||
1119 | ret = acpiphp_disable_and_eject_slot(slot); | ||
1120 | pci_unlock_rescan_remove(); | ||
1121 | return ret; | ||
1122 | } | ||
1088 | 1123 | ||
1089 | /* | 1124 | /* |
1090 | * slot enabled: 1 | 1125 | * slot enabled: 1 |
@@ -1095,7 +1130,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | |||
1095 | return (slot->flags & SLOT_ENABLED); | 1130 | return (slot->flags & SLOT_ENABLED); |
1096 | } | 1131 | } |
1097 | 1132 | ||
1098 | |||
1099 | /* | 1133 | /* |
1100 | * latch open: 1 | 1134 | * latch open: 1 |
1101 | * latch closed: 0 | 1135 | * latch closed: 0 |
@@ -1105,7 +1139,6 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | |||
1105 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); | 1139 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); |
1106 | } | 1140 | } |
1107 | 1141 | ||
1108 | |||
1109 | /* | 1142 | /* |
1110 | * adapter presence : 1 | 1143 | * adapter presence : 1 |
1111 | * absence : 0 | 1144 | * absence : 0 |