Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cecdb193 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

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: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarToshi Kani <toshi.kani@hp.com>
Acked-by: default avatarYinghai Lu <yinghai@kernel.org>
Acked-by: default avatarYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
parent ae281795
Loading
Loading
Loading
Loading
+15 −49
Original line number Diff line number Diff line
@@ -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);