diff options
-rw-r--r-- | drivers/acpi/scan.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4d377a22622a..9bdcc187bf4b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -125,8 +125,8 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
125 | } | 125 | } |
126 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 126 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
127 | 127 | ||
128 | static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, | 128 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, |
129 | void *data, void **ret_p) | 129 | void **ret_p) |
130 | { | 130 | { |
131 | struct acpi_device *device = NULL; | 131 | struct acpi_device *device = NULL; |
132 | struct acpi_device_physical_node *pn; | 132 | struct acpi_device_physical_node *pn; |
@@ -136,6 +136,11 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, | |||
136 | if (acpi_bus_get_device(handle, &device)) | 136 | if (acpi_bus_get_device(handle, &device)) |
137 | return AE_OK; | 137 | return AE_OK; |
138 | 138 | ||
139 | if (device->handler && !device->handler->hotplug.enabled) { | ||
140 | *ret_p = &device->dev; | ||
141 | return AE_SUPPORT; | ||
142 | } | ||
143 | |||
139 | mutex_lock(&device->physical_node_lock); | 144 | mutex_lock(&device->physical_node_lock); |
140 | 145 | ||
141 | list_for_each_entry(pn, &device->physical_node_list, node) { | 146 | list_for_each_entry(pn, &device->physical_node_list, node) { |
@@ -168,8 +173,8 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, | |||
168 | return status; | 173 | return status; |
169 | } | 174 | } |
170 | 175 | ||
171 | static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, | 176 | static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, |
172 | void *data, void **ret_p) | 177 | void **ret_p) |
173 | { | 178 | { |
174 | struct acpi_device *device = NULL; | 179 | struct acpi_device *device = NULL; |
175 | struct acpi_device_physical_node *pn; | 180 | struct acpi_device_physical_node *pn; |
@@ -214,26 +219,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
214 | * If the first pass is successful, the second one isn't needed, though. | 219 | * If the first pass is successful, the second one isn't needed, though. |
215 | */ | 220 | */ |
216 | errdev = NULL; | 221 | errdev = NULL; |
217 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 222 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
218 | NULL, acpi_bus_offline_companions, | 223 | NULL, acpi_bus_offline, (void *)false, |
219 | (void *)false, (void **)&errdev); | 224 | (void **)&errdev); |
220 | acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev); | 225 | if (status == AE_SUPPORT) { |
226 | dev_warn(errdev, "Offline disabled.\n"); | ||
227 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | ||
228 | acpi_bus_online, NULL, NULL, NULL); | ||
229 | put_device(&device->dev); | ||
230 | return -EPERM; | ||
231 | } | ||
232 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); | ||
221 | if (errdev) { | 233 | if (errdev) { |
222 | errdev = NULL; | 234 | errdev = NULL; |
223 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 235 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
224 | NULL, acpi_bus_offline_companions, | 236 | NULL, acpi_bus_offline, (void *)true, |
225 | (void *)true , (void **)&errdev); | 237 | (void **)&errdev); |
226 | if (!errdev || acpi_force_hot_remove) | 238 | if (!errdev || acpi_force_hot_remove) |
227 | acpi_bus_offline_companions(handle, 0, (void *)true, | 239 | acpi_bus_offline(handle, 0, (void *)true, |
228 | (void **)&errdev); | 240 | (void **)&errdev); |
229 | 241 | ||
230 | if (errdev && !acpi_force_hot_remove) { | 242 | if (errdev && !acpi_force_hot_remove) { |
231 | dev_warn(errdev, "Offline failed.\n"); | 243 | dev_warn(errdev, "Offline failed.\n"); |
232 | acpi_bus_online_companions(handle, 0, NULL, NULL); | 244 | acpi_bus_online(handle, 0, NULL, NULL); |
233 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, | 245 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, |
234 | ACPI_UINT32_MAX, | 246 | ACPI_UINT32_MAX, acpi_bus_online, |
235 | acpi_bus_online_companions, NULL, | 247 | NULL, NULL, NULL); |
236 | NULL, NULL); | ||
237 | put_device(&device->dev); | 248 | put_device(&device->dev); |
238 | return -EBUSY; | 249 | return -EBUSY; |
239 | } | 250 | } |
@@ -290,10 +301,9 @@ static void acpi_bus_device_eject(void *context) | |||
290 | goto err_out; | 301 | goto err_out; |
291 | 302 | ||
292 | handler = device->handler; | 303 | handler = device->handler; |
293 | if (!handler || !handler->hotplug.enabled) { | 304 | if (!handler || !handler->hotplug.enabled) |
294 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 305 | goto err_support; |
295 | goto err_out; | 306 | |
296 | } | ||
297 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 307 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, |
298 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 308 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
299 | if (handler->hotplug.mode == AHM_CONTAINER) | 309 | if (handler->hotplug.mode == AHM_CONTAINER) |
@@ -301,14 +311,19 @@ static void acpi_bus_device_eject(void *context) | |||
301 | 311 | ||
302 | get_device(&device->dev); | 312 | get_device(&device->dev); |
303 | error = acpi_scan_hot_remove(device); | 313 | error = acpi_scan_hot_remove(device); |
304 | if (error) | 314 | if (error == -EPERM) { |
315 | goto err_support; | ||
316 | } else if (error) { | ||
305 | goto err_out; | 317 | goto err_out; |
318 | } | ||
306 | 319 | ||
307 | out: | 320 | out: |
308 | mutex_unlock(&acpi_scan_lock); | 321 | mutex_unlock(&acpi_scan_lock); |
309 | unlock_device_hotplug(); | 322 | unlock_device_hotplug(); |
310 | return; | 323 | return; |
311 | 324 | ||
325 | err_support: | ||
326 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
312 | err_out: | 327 | err_out: |
313 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, | 328 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, |
314 | NULL); | 329 | NULL); |