aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dock.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-30 17:46:42 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-14 19:33:11 -0400
commit37f908778f20bbcc35ab9a98a5b584329c6abf08 (patch)
tree1b8dfacd079665a19dee7a876fb79f68e75da505 /drivers/acpi/dock.c
parent96c0a4d4902c3d5f56bde95d3e2d96689ca64b6d (diff)
ACPI / dock: Walk list in reverse order during removal of devices
If there are indirect dependencies between devices in a dock station's dependent devices list, they may be broken if the devices are removed in the same order in which they have been added. For this reason, make the code in handle_eject_request() walk the list of dependent devices in reverse order. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org>
Diffstat (limited to 'drivers/acpi/dock.c')
-rw-r--r--drivers/acpi/dock.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 7c86d01346e6..41c5d04a89c1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -337,9 +337,29 @@ static void dock_remove_acpi_device(acpi_handle handle)
337} 337}
338 338
339/** 339/**
340 * hotplug_dock_devices - insert or remove devices on the dock station 340 * hot_remove_dock_devices - Remove dock station devices.
341 * @ds: Dock station.
342 */
343static void hot_remove_dock_devices(struct dock_station *ds)
344{
345 struct dock_dependent_device *dd;
346
347 /*
348 * Walk the list in reverse order so that devices that have been added
349 * last are removed first (in case there are some indirect dependencies
350 * between them).
351 */
352 list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
353 dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
354
355 list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
356 dock_remove_acpi_device(dd->handle);
357}
358
359/**
360 * hotplug_dock_devices - Insert devices on a dock station.
341 * @ds: the dock station 361 * @ds: the dock station
342 * @event: either bus check or eject request 362 * @event: either bus check or device check request
343 * 363 *
344 * Some devices on the dock station need to have drivers called 364 * Some devices on the dock station need to have drivers called
345 * to perform hotplug operations after a dock event has occurred. 365 * to perform hotplug operations after a dock event has occurred.
@@ -350,24 +370,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
350{ 370{
351 struct dock_dependent_device *dd; 371 struct dock_dependent_device *dd;
352 372
353 /* 373 /* Call driver specific hotplug functions. */
354 * First call driver specific hotplug functions
355 */
356 list_for_each_entry(dd, &ds->dependent_devices, list) 374 list_for_each_entry(dd, &ds->dependent_devices, list)
357 dock_hotplug_event(dd, event, false); 375 dock_hotplug_event(dd, event, false);
358 376
359 /* 377 /*
360 * Now make sure that an acpi_device is created for each 378 * Now make sure that an acpi_device is created for each dependent
361 * dependent device, or removed if this is an eject request. 379 * device. That will cause scan handlers to be attached to device
362 * This will cause acpi_drivers to be stopped/started if they 380 * objects or acpi_drivers to be stopped/started if they are present.
363 * exist
364 */ 381 */
365 list_for_each_entry(dd, &ds->dependent_devices, list) { 382 list_for_each_entry(dd, &ds->dependent_devices, list)
366 if (event == ACPI_NOTIFY_EJECT_REQUEST) 383 dock_create_acpi_device(dd->handle);
367 dock_remove_acpi_device(dd->handle);
368 else
369 dock_create_acpi_device(dd->handle);
370 }
371} 384}
372 385
373static void dock_event(struct dock_station *ds, u32 event, int num) 386static void dock_event(struct dock_station *ds, u32 event, int num)
@@ -588,7 +601,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
588 */ 601 */
589 dock_event(ds, event, UNDOCK_EVENT); 602 dock_event(ds, event, UNDOCK_EVENT);
590 603
591 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); 604 hot_remove_dock_devices(ds);
592 undock(ds); 605 undock(ds);
593 acpi_evaluate_lck(ds->handle, 0); 606 acpi_evaluate_lck(ds->handle, 0);
594 acpi_evaluate_ej0(ds->handle); 607 acpi_evaluate_ej0(ds->handle);