aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-22 15:55:43 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-22 15:55:43 -0500
commit443fc8202272190c4693209b772edba46cd7fe61 (patch)
treeeb3be8b00e5ca6f3e06416b443c1cb56671895de /drivers/acpi/scan.c
parent46394fd017c0615982a3d29d45ced14bea9c526d (diff)
ACPI / hotplug: Rework generic code to handle suprise removals
The generic ACPI hotplug code used for several types of device doesn't handle surprise removals, mostly because those devices currently cannot be removed by surprise in the majority of systems. However, surprise removals should be handled by that code as well as surprise additions of devices, so make it do that. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c85
1 files changed, 59 insertions, 26 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b1b8f4304597..06db2c036085 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -276,18 +276,72 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
276 return 0; 276 return 0;
277} 277}
278 278
279static int acpi_scan_device_not_present(struct acpi_device *adev)
280{
281 if (!acpi_device_enumerated(adev)) {
282 dev_warn(&adev->dev, "Still not present\n");
283 return -EALREADY;
284 }
285 acpi_bus_trim(adev);
286 return 0;
287}
288
279static int acpi_scan_device_check(struct acpi_device *adev) 289static int acpi_scan_device_check(struct acpi_device *adev)
280{ 290{
281 int error; 291 int error;
282 292
293 acpi_bus_get_status(adev);
294 if (adev->status.present || adev->status.functional) {
295 /*
296 * This function is only called for device objects for which
297 * matching scan handlers exist. The only situation in which
298 * the scan handler is not attached to this device object yet
299 * is when the device has just appeared (either it wasn't
300 * present at all before or it was removed and then added
301 * again).
302 */
303 if (adev->handler) {
304 dev_warn(&adev->dev, "Already enumerated\n");
305 return -EALREADY;
306 }
307 error = acpi_bus_scan(adev->handle);
308 if (error) {
309 dev_warn(&adev->dev, "Namespace scan failure\n");
310 return error;
311 }
312 if (!adev->handler) {
313 dev_warn(&adev->dev, "Enumeration failure\n");
314 error = -ENODEV;
315 }
316 } else {
317 error = acpi_scan_device_not_present(adev);
318 }
319 return error;
320}
321
322static int acpi_scan_bus_check(struct acpi_device *adev)
323{
324 struct acpi_scan_handler *handler = adev->handler;
325 struct acpi_device *child;
326 int error;
327
328 acpi_bus_get_status(adev);
329 if (!(adev->status.present || adev->status.functional)) {
330 acpi_scan_device_not_present(adev);
331 return 0;
332 }
333 if (handler && handler->hotplug.scan_dependent)
334 return handler->hotplug.scan_dependent(adev);
335
283 error = acpi_bus_scan(adev->handle); 336 error = acpi_bus_scan(adev->handle);
284 if (error) { 337 if (error) {
285 dev_warn(&adev->dev, "Namespace scan failure\n"); 338 dev_warn(&adev->dev, "Namespace scan failure\n");
286 return error; 339 return error;
287 } 340 }
288 if (!adev->handler) { 341 list_for_each_entry(child, &adev->children, node) {
289 dev_warn(&adev->dev, "Enumeration failure\n"); 342 error = acpi_scan_bus_check(child);
290 return -ENODEV; 343 if (error)
344 return error;
291 } 345 }
292 return 0; 346 return 0;
293} 347}
@@ -296,7 +350,6 @@ static void acpi_device_hotplug(void *data, u32 src)
296{ 350{
297 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; 351 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
298 struct acpi_device *adev = data; 352 struct acpi_device *adev = data;
299 struct acpi_scan_handler *handler;
300 int error; 353 int error;
301 354
302 lock_device_hotplug(); 355 lock_device_hotplug();
@@ -310,32 +363,12 @@ static void acpi_device_hotplug(void *data, u32 src)
310 if (adev->handle == INVALID_ACPI_HANDLE) 363 if (adev->handle == INVALID_ACPI_HANDLE)
311 goto out; 364 goto out;
312 365
313 handler = adev->handler;
314
315 switch (src) { 366 switch (src) {
316 case ACPI_NOTIFY_BUS_CHECK: 367 case ACPI_NOTIFY_BUS_CHECK:
317 if (handler) { 368 error = acpi_scan_bus_check(adev);
318 error = handler->hotplug.scan_dependent ?
319 handler->hotplug.scan_dependent(adev) :
320 acpi_bus_scan(adev->handle);
321 } else {
322 error = acpi_scan_device_check(adev);
323 }
324 break; 369 break;
325 case ACPI_NOTIFY_DEVICE_CHECK: 370 case ACPI_NOTIFY_DEVICE_CHECK:
326 /* 371 error = acpi_scan_device_check(adev);
327 * This code is only run for device objects for which matching
328 * scan handlers exist. The only situation in which the scan
329 * handler is not attached to this device object yet is when the
330 * device has just appeared (either it wasn't present at all
331 * before or it was removed and then added again).
332 */
333 if (adev->handler) {
334 dev_warn(&adev->dev, "Already enumerated\n");
335 error = -EBUSY;
336 } else {
337 error = acpi_scan_device_check(adev);
338 }
339 break; 372 break;
340 case ACPI_NOTIFY_EJECT_REQUEST: 373 case ACPI_NOTIFY_EJECT_REQUEST:
341 case ACPI_OST_EC_OSPM_EJECT: 374 case ACPI_OST_EC_OSPM_EJECT: