Commit a976a2ac authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPI: scan: Walk ACPI device's children using driver core

Instead of walking the list of children of an ACPI device directly, use
acpi_dev_for_each_child() or acpi_dev_for_each_child_reverse() to carry
out an action for all of the given ACPI device's children.

This will help to eliminate the children list head from struct
acpi_device as it is redundant and it is used in questionable ways
in some places (in particular, locking is needed for walking the
list pointed to it safely, but it is often missing).
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parent ff32e599
...@@ -334,10 +334,9 @@ static int acpi_scan_device_check(struct acpi_device *adev) ...@@ -334,10 +334,9 @@ static int acpi_scan_device_check(struct acpi_device *adev)
return error; return error;
} }
static int acpi_scan_bus_check(struct acpi_device *adev) static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
{ {
struct acpi_scan_handler *handler = adev->handler; struct acpi_scan_handler *handler = adev->handler;
struct acpi_device *child;
int error; int error;
acpi_bus_get_status(adev); acpi_bus_get_status(adev);
...@@ -353,19 +352,14 @@ static int acpi_scan_bus_check(struct acpi_device *adev) ...@@ -353,19 +352,14 @@ static int acpi_scan_bus_check(struct acpi_device *adev)
dev_warn(&adev->dev, "Namespace scan failure\n"); dev_warn(&adev->dev, "Namespace scan failure\n");
return error; return error;
} }
list_for_each_entry(child, &adev->children, node) { return acpi_dev_for_each_child(adev, acpi_scan_bus_check, NULL);
error = acpi_scan_bus_check(child);
if (error)
return error;
}
return 0;
} }
static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type) static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
{ {
switch (type) { switch (type) {
case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_BUS_CHECK:
return acpi_scan_bus_check(adev); return acpi_scan_bus_check(adev, NULL);
case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_NOTIFY_DEVICE_CHECK:
return acpi_scan_device_check(adev); return acpi_scan_device_check(adev);
case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_NOTIFY_EJECT_REQUEST:
...@@ -2187,9 +2181,8 @@ static int acpi_scan_attach_handler(struct acpi_device *device) ...@@ -2187,9 +2181,8 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
return ret; return ret;
} }
static void acpi_bus_attach(struct acpi_device *device, bool first_pass) static int acpi_bus_attach(struct acpi_device *device, void *first_pass)
{ {
struct acpi_device *child;
bool skip = !first_pass && device->flags.visited; bool skip = !first_pass && device->flags.visited;
acpi_handle ejd; acpi_handle ejd;
int ret; int ret;
...@@ -2206,7 +2199,7 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass) ...@@ -2206,7 +2199,7 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
device->flags.initialized = false; device->flags.initialized = false;
acpi_device_clear_enumerated(device); acpi_device_clear_enumerated(device);
device->flags.power_manageable = 0; device->flags.power_manageable = 0;
return; return 0;
} }
if (device->handler) if (device->handler)
goto ok; goto ok;
...@@ -2224,7 +2217,7 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass) ...@@ -2224,7 +2217,7 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
ret = acpi_scan_attach_handler(device); ret = acpi_scan_attach_handler(device);
if (ret < 0) if (ret < 0)
return; return 0;
device->flags.match_driver = true; device->flags.match_driver = true;
if (ret > 0 && !device->flags.enumeration_by_parent) { if (ret > 0 && !device->flags.enumeration_by_parent) {
...@@ -2234,19 +2227,20 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass) ...@@ -2234,19 +2227,20 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
ret = device_attach(&device->dev); ret = device_attach(&device->dev);
if (ret < 0) if (ret < 0)
return; return 0;
if (device->pnp.type.platform_id || device->flags.enumeration_by_parent) if (device->pnp.type.platform_id || device->flags.enumeration_by_parent)
acpi_default_enumeration(device); acpi_default_enumeration(device);
else else
acpi_device_set_enumerated(device); acpi_device_set_enumerated(device);
ok: ok:
list_for_each_entry(child, &device->children, node) acpi_dev_for_each_child(device, acpi_bus_attach, first_pass);
acpi_bus_attach(child, first_pass);
if (!skip && device->handler && device->handler->hotplug.notify_online) if (!skip && device->handler && device->handler->hotplug.notify_online)
device->handler->hotplug.notify_online(device); device->handler->hotplug.notify_online(device);
return 0;
} }
static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data) static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
...@@ -2274,7 +2268,7 @@ static void acpi_scan_clear_dep_fn(struct work_struct *work) ...@@ -2274,7 +2268,7 @@ static void acpi_scan_clear_dep_fn(struct work_struct *work)
cdw = container_of(work, struct acpi_scan_clear_dep_work, work); cdw = container_of(work, struct acpi_scan_clear_dep_work, work);
acpi_scan_lock_acquire(); acpi_scan_lock_acquire();
acpi_bus_attach(cdw->adev, true); acpi_bus_attach(cdw->adev, (void *)true);
acpi_scan_lock_release(); acpi_scan_lock_release();
acpi_dev_put(cdw->adev); acpi_dev_put(cdw->adev);
...@@ -2432,7 +2426,7 @@ int acpi_bus_scan(acpi_handle handle) ...@@ -2432,7 +2426,7 @@ int acpi_bus_scan(acpi_handle handle)
if (!device) if (!device)
return -ENODEV; return -ENODEV;
acpi_bus_attach(device, true); acpi_bus_attach(device, (void *)true);
if (!acpi_bus_scan_second_pass) if (!acpi_bus_scan_second_pass)
return 0; return 0;
...@@ -2446,25 +2440,17 @@ int acpi_bus_scan(acpi_handle handle) ...@@ -2446,25 +2440,17 @@ int acpi_bus_scan(acpi_handle handle)
acpi_bus_check_add_2, NULL, NULL, acpi_bus_check_add_2, NULL, NULL,
(void **)&device); (void **)&device);
acpi_bus_attach(device, false); acpi_bus_attach(device, NULL);
return 0; return 0;
} }
EXPORT_SYMBOL(acpi_bus_scan); EXPORT_SYMBOL(acpi_bus_scan);
/** static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
* acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
* @adev: Root of the ACPI namespace scope to walk.
*
* Must be called under acpi_scan_lock.
*/
void acpi_bus_trim(struct acpi_device *adev)
{ {
struct acpi_scan_handler *handler = adev->handler; struct acpi_scan_handler *handler = adev->handler;
struct acpi_device *child;
list_for_each_entry_reverse(child, &adev->children, node) acpi_dev_for_each_child_reverse(adev, acpi_bus_trim_one, NULL);
acpi_bus_trim(child);
adev->flags.match_driver = false; adev->flags.match_driver = false;
if (handler) { if (handler) {
...@@ -2482,6 +2468,19 @@ void acpi_bus_trim(struct acpi_device *adev) ...@@ -2482,6 +2468,19 @@ void acpi_bus_trim(struct acpi_device *adev)
acpi_device_set_power(adev, ACPI_STATE_D3_COLD); acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
adev->flags.initialized = false; adev->flags.initialized = false;
acpi_device_clear_enumerated(adev); acpi_device_clear_enumerated(adev);
return 0;
}
/**
* acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
* @adev: Root of the ACPI namespace scope to walk.
*
* Must be called under acpi_scan_lock.
*/
void acpi_bus_trim(struct acpi_device *adev)
{
acpi_bus_trim_one(adev, NULL);
} }
EXPORT_SYMBOL_GPL(acpi_bus_trim); EXPORT_SYMBOL_GPL(acpi_bus_trim);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment