[Update][PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different

From: Rafael J. Wysocki
Date: Wed Dec 12 2012 - 19:06:52 EST


From: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
Subject: ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different

The current ACPI namespace scanning code suggests that acpi_bus_add()
and acpi_bus_start() share some code. In fact, however, they are
completely different code paths (except for the initial checks), so
refactor the code to make that distinction visibly clear.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
---

Update is needed, because of a potential bug found in [1/6], as described here:

https://lkml.org/lkml/2012/12/12/460

Thanks,
Rafael

---
drivers/acpi/scan.c | 66 ++++++++++++++++++++++++++++------------------------
1 file changed, 36 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1626,10 +1626,9 @@ static acpi_status acpi_bus_check_add(ac
return AE_OK;
}

-static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
- void *context, void **not_used)
+static acpi_status acpi_bus_match_device(acpi_handle handle, u32 lvl,
+ void *not_used, void **ret_not_used)
{
- struct acpi_bus_ops *ops = context;
acpi_status status = AE_OK;
struct acpi_device *device;
unsigned long long sta_not_used;
@@ -1645,18 +1644,13 @@ static acpi_status acpi_bus_probe_start(
if (acpi_bus_get_device(handle, &device))
return AE_CTRL_DEPTH;

- if (ops->acpi_op_add) {
- if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
- /* This is a known good platform device. */
- acpi_create_platform_device(device);
- } else {
- int ret = device_attach(&device->dev);
- acpi_hot_add_bind(device);
- if (ret)
- status = AE_CTRL_DEPTH;
- }
- } else if (ops->acpi_op_start) {
- if (ACPI_FAILURE(acpi_start_single_object(device)))
+ if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+ /* This is a known good platform device. */
+ acpi_create_platform_device(device);
+ } else {
+ int ret = device_attach(&device->dev);
+ acpi_hot_add_bind(device);
+ if (ret)
status = AE_CTRL_DEPTH;
}
return status;
@@ -1679,7 +1673,7 @@ static int acpi_bus_scan(acpi_handle han
acpi_bus_check_add, NULL, ops, &device);
if (device)
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
- acpi_bus_probe_start, NULL, ops, NULL);
+ acpi_bus_match_device, NULL, NULL, NULL);
else
ret = -ENODEV;

@@ -1706,31 +1700,43 @@ int
acpi_bus_add(struct acpi_device **child,
struct acpi_device *parent, acpi_handle handle, int type)
{
- struct acpi_bus_ops ops;
-
- memset(&ops, 0, sizeof(ops));
- ops.acpi_op_add = 1;
+ struct acpi_bus_ops ops = { .acpi_op_add = 1, };

return acpi_bus_scan(handle, &ops, child);
}
EXPORT_SYMBOL(acpi_bus_add);

-int acpi_bus_start(struct acpi_device *device)
+static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
+ void *not_used, void **ret_not_used)
{
- struct acpi_bus_ops ops;
- int result;
+ struct acpi_device *device;
+ unsigned long long sta_not_used;
+ int type_not_used;
+ acpi_status status;

- if (!device)
- return -EINVAL;
+ /*
+ * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+ * namespace walks prematurely.
+ */
+ if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+ return AE_OK;

- memset(&ops, 0, sizeof(ops));
- ops.acpi_op_start = 1;
+ if (acpi_bus_get_device(handle, &device))
+ return AE_CTRL_DEPTH;

- result = acpi_bus_scan(device->handle, &ops, NULL);
+ status = acpi_start_single_object(device);
+ return ACPI_SUCCESS(status) ? status : AE_CTRL_DEPTH;
+}

- acpi_update_all_gpes();
+int acpi_bus_start(struct acpi_device *device)
+{
+ if (!device)
+ return -EINVAL;

- return result;
+ acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, ACPI_UINT32_MAX,
+ acpi_bus_start_device, NULL, NULL, NULL);
+ acpi_update_all_gpes();
+ return 0;
}
EXPORT_SYMBOL(acpi_bus_start);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/