mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 01:54:09 +08:00
ACPI / scan: Change the implementation of acpi_bus_trim()
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>
This commit is contained in:
parent
ae281795ec
commit
cecdb193c8
@ -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.
|
||||
* Execute acpi_bus_remove() as a post-order callback to remove device
|
||||
* nodes in the given namespace scope.
|
||||
*/
|
||||
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;
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user