OSDN Git Service

ACPI / scan: Change the implementation of acpi_bus_trim()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 15 Jan 2013 12:24:02 +0000 (13:24 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 15 Jan 2013 12:24:02 +0000 (13:24 +0100)
The current acpi_bus_trim() implementation is not really
straightforward and may be simplified significantly by using
acpi_walk_namespace() with acpi_bus_remove() as a post-order
callback.

Observe that acpi_bus_remove(), as called by acpi_bus_trim(), cannot
actually fail, because its first argument is guaranteed not to be
NULL thanks to the acpi_bus_get_device() check in acpi_bus_trim(),
so simply move the acpi_bus_get_device() check to acpi_bus_remove()
and use acpi_walk_namespace() to execute it for every device under
start->handle as a post-order callback.  The, run it directly for
start->handle itself.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
drivers/acpi/scan.c

index d14ce44..1ee62bd 100644 (file)
@@ -1374,17 +1374,20 @@ static int acpi_device_set_context(struct acpi_device *device)
        return -ENODEV;
 }
 
-static int acpi_bus_remove(struct acpi_device *dev)
+static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
+                                  void *not_used, void **ret_not_used)
 {
-       if (!dev)
-               return -EINVAL;
+       struct acpi_device *dev = NULL;
+
+       if (acpi_bus_get_device(handle, &dev))
+               return AE_OK;
 
        dev->removal_type = ACPI_BUS_REMOVAL_EJECT;
        device_release_driver(&dev->dev);
 
        acpi_device_unregister(dev);
 
-       return 0;
+       return AE_OK;
 }
 
 static int acpi_add_single_object(struct acpi_device **child,
@@ -1641,51 +1644,14 @@ EXPORT_SYMBOL(acpi_bus_add);
 
 int acpi_bus_trim(struct acpi_device *start)
 {
-       acpi_status status;
-       struct acpi_device *parent, *child;
-       acpi_handle phandle, chandle;
-       acpi_object_type type;
-       u32 level = 1;
-       int err = 0;
-
-       parent = start;
-       phandle = start->handle;
-       child = chandle = NULL;
-
-       while ((level > 0) && parent && (!err)) {
-               status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
-                                             chandle, &chandle);
-
-               /*
-                * If this scope is exhausted then move our way back up.
-                */
-               if (ACPI_FAILURE(status)) {
-                       level--;
-                       chandle = phandle;
-                       acpi_get_parent(phandle, &phandle);
-                       child = parent;
-                       parent = parent->parent;
-                       err = acpi_bus_remove(child);
-                       continue;
-               }
-
-               status = acpi_get_type(chandle, &type);
-               if (ACPI_FAILURE(status)) {
-                       continue;
-               }
-               /*
-                * If there is a device corresponding to chandle then
-                * parse it (depth-first).
-                */
-               if (acpi_bus_get_device(chandle, &child) == 0) {
-                       level++;
-                       phandle = chandle;
-                       chandle = NULL;
-                       parent = child;
-               }
-               continue;
-       }
-       return err;
+       /*
+        * Execute acpi_bus_remove() as a post-order callback to remove device
+        * nodes in the given namespace scope.
+        */
+       acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
+                           acpi_bus_remove, NULL, NULL);
+       acpi_bus_remove(start->handle, 0, NULL, NULL);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_bus_trim);