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

ACPI / scan: More straightforward preparation of ACPI device objects

Simplify the code preparing struct acpi_device objects for
registration by removing useless code, moving different pieces of
code into the functions they belong to and making a couple of int
functions always returning 0 void.

This also fixes a possible memory leak in ACPI device registration
error code path by making acpi_device_register() detach data from
device->handle if device_register() fails and prepares the scanning
code for special-casing ACPI power resources (next patch).
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent bc9b6407
...@@ -472,6 +472,7 @@ static void acpi_free_ids(struct acpi_device *device) ...@@ -472,6 +472,7 @@ static void acpi_free_ids(struct acpi_device *device)
kfree(id->id); kfree(id->id);
kfree(id); kfree(id);
} }
kfree(device->pnp.unique_id);
} }
static void acpi_device_release(struct device *dev) static void acpi_device_release(struct device *dev)
...@@ -479,7 +480,6 @@ static void acpi_device_release(struct device *dev) ...@@ -479,7 +480,6 @@ static void acpi_device_release(struct device *dev)
struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_device *acpi_dev = to_acpi_device(dev);
acpi_free_ids(acpi_dev); acpi_free_ids(acpi_dev);
kfree(acpi_dev->pnp.unique_id);
kfree(acpi_dev); kfree(acpi_dev);
} }
...@@ -623,6 +623,18 @@ static int acpi_device_register(struct acpi_device *device) ...@@ -623,6 +623,18 @@ static int acpi_device_register(struct acpi_device *device)
struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
int found = 0; int found = 0;
if (device->handle) {
acpi_status status;
status = acpi_attach_data(device->handle, acpi_bus_data_handler,
device);
if (ACPI_FAILURE(status)) {
acpi_handle_err(device->handle,
"Unable to attach device data\n");
return -ENODEV;
}
}
/* /*
* Linkage * Linkage
* ------- * -------
...@@ -637,8 +649,9 @@ static int acpi_device_register(struct acpi_device *device) ...@@ -637,8 +649,9 @@ static int acpi_device_register(struct acpi_device *device)
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
if (!new_bus_id) { if (!new_bus_id) {
printk(KERN_ERR PREFIX "Memory allocation error\n"); pr_err(PREFIX "Memory allocation error\n");
return -ENOMEM; result = -ENOMEM;
goto err_detach;
} }
mutex_lock(&acpi_device_lock); mutex_lock(&acpi_device_lock);
...@@ -677,7 +690,7 @@ static int acpi_device_register(struct acpi_device *device) ...@@ -677,7 +690,7 @@ static int acpi_device_register(struct acpi_device *device)
result = device_register(&device->dev); result = device_register(&device->dev);
if (result) { if (result) {
dev_err(&device->dev, "Error registering device\n"); dev_err(&device->dev, "Error registering device\n");
goto end; goto err;
} }
result = acpi_device_setup_files(device); result = acpi_device_setup_files(device);
...@@ -687,12 +700,16 @@ static int acpi_device_register(struct acpi_device *device) ...@@ -687,12 +700,16 @@ static int acpi_device_register(struct acpi_device *device)
device->removal_type = ACPI_BUS_REMOVAL_NORMAL; device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0; return 0;
end:
err:
mutex_lock(&acpi_device_lock); mutex_lock(&acpi_device_lock);
if (device->parent) if (device->parent)
list_del(&device->node); list_del(&device->node);
list_del(&device->wakeup_list); list_del(&device->wakeup_list);
mutex_unlock(&acpi_device_lock); mutex_unlock(&acpi_device_lock);
err_detach:
acpi_detach_data(device->handle, acpi_bus_data_handler);
return result; return result;
} }
...@@ -857,12 +874,6 @@ void acpi_bus_data_handler(acpi_handle handle, void *context) ...@@ -857,12 +874,6 @@ void acpi_bus_data_handler(acpi_handle handle, void *context)
return; return;
} }
static int acpi_bus_get_perf_flags(struct acpi_device *device)
{
device->performance.state = ACPI_STATE_UNKNOWN;
return 0;
}
static acpi_status static acpi_status
acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
struct acpi_device_wakeup *wakeup) struct acpi_device_wakeup *wakeup)
...@@ -1013,12 +1024,25 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) ...@@ -1013,12 +1024,25 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
static void acpi_bus_add_power_resource(acpi_handle handle); static void acpi_bus_add_power_resource(acpi_handle handle);
static int acpi_bus_get_power_flags(struct acpi_device *device) static void acpi_bus_get_power_flags(struct acpi_device *device)
{ {
acpi_status status = 0; acpi_status status = 0;
acpi_handle handle = NULL; acpi_handle handle = NULL;
u32 i = 0; u32 i = 0;
/* Power resources cannot be power manageable. */
if (device->device_type == ACPI_BUS_TYPE_POWER)
return;
/* Presence of _PS0|_PR0 indicates 'power manageable' */
status = acpi_get_handle(device->handle, "_PS0", &handle);
if (ACPI_FAILURE(status)) {
status = acpi_get_handle(device->handle, "_PR0", &handle);
if (ACPI_FAILURE(status))
return;
}
device->flags.power_manageable = 1;
/* /*
* Power Management Flags * Power Management Flags
...@@ -1084,16 +1108,13 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) ...@@ -1084,16 +1108,13 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1;
acpi_bus_init_power(device); acpi_bus_init_power(device);
return 0;
} }
static int acpi_bus_get_flags(struct acpi_device *device) static void acpi_bus_get_flags(struct acpi_device *device)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_handle temp = NULL; acpi_handle temp = NULL;
/* Presence of _STA indicates 'dynamic_status' */ /* Presence of _STA indicates 'dynamic_status' */
status = acpi_get_handle(device->handle, "_STA", &temp); status = acpi_get_handle(device->handle, "_STA", &temp);
if (ACPI_SUCCESS(status)) if (ACPI_SUCCESS(status))
...@@ -1113,21 +1134,6 @@ static int acpi_bus_get_flags(struct acpi_device *device) ...@@ -1113,21 +1134,6 @@ static int acpi_bus_get_flags(struct acpi_device *device)
if (ACPI_SUCCESS(status)) if (ACPI_SUCCESS(status))
device->flags.ejectable = 1; device->flags.ejectable = 1;
} }
/* Power resources cannot be power manageable. */
if (device->device_type == ACPI_BUS_TYPE_POWER)
return 0;
/* Presence of _PS0|_PR0 indicates 'power manageable' */
status = acpi_get_handle(device->handle, "_PS0", &temp);
if (ACPI_FAILURE(status))
status = acpi_get_handle(device->handle, "_PR0", &temp);
if (ACPI_SUCCESS(status))
device->flags.power_manageable = 1;
/* TBD: Performance management */
return 0;
} }
static void acpi_device_get_busid(struct acpi_device *device) static void acpi_device_get_busid(struct acpi_device *device)
...@@ -1352,27 +1358,18 @@ static void acpi_device_set_id(struct acpi_device *device) ...@@ -1352,27 +1358,18 @@ static void acpi_device_set_id(struct acpi_device *device)
} }
} }
static int acpi_device_set_context(struct acpi_device *device) static void acpi_init_device_object(struct acpi_device *device,
acpi_handle handle,
int type, unsigned long long sta)
{ {
acpi_status status; INIT_LIST_HEAD(&device->pnp.ids);
device->device_type = type;
/* device->handle = handle;
* Context device->parent = acpi_bus_get_parent(handle);
* ------- STRUCT_TO_INT(device->status) = sta;
* Attach this 'struct acpi_device' to the ACPI object. This makes acpi_device_get_busid(device);
* resolutions from handle->device very efficient. Fixed hardware acpi_device_set_id(device);
* devices have no handles, so we skip them. acpi_bus_get_flags(device);
*/
if (!device->handle)
return 0;
status = acpi_attach_data(device->handle,
acpi_bus_data_handler, device);
if (ACPI_SUCCESS(status))
return 0;
printk(KERN_ERR PREFIX "Error attaching device data\n");
return -ENODEV;
} }
static int acpi_add_single_object(struct acpi_device **child, static int acpi_add_single_object(struct acpi_device **child,
...@@ -1389,78 +1386,25 @@ static int acpi_add_single_object(struct acpi_device **child, ...@@ -1389,78 +1386,25 @@ static int acpi_add_single_object(struct acpi_device **child,
return -ENOMEM; return -ENOMEM;
} }
INIT_LIST_HEAD(&device->pnp.ids); acpi_init_device_object(device, handle, type, sta);
device->device_type = type; acpi_bus_get_power_flags(device);
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
STRUCT_TO_INT(device->status) = sta;
acpi_device_get_busid(device);
/*
* Flags
* -----
* Note that we only look for object handles -- cannot evaluate objects
* until we know the device is present and properly initialized.
*/
result = acpi_bus_get_flags(device);
if (result)
goto end;
/*
* Initialize Device
* -----------------
* TBD: Synch with Core's enumeration/initialization process.
*/
acpi_device_set_id(device);
/*
* Power Management
* ----------------
*/
if (device->flags.power_manageable) {
result = acpi_bus_get_power_flags(device);
if (result)
goto end;
}
/*
* Wakeup device management
*-----------------------
*/
acpi_bus_get_wakeup_device_flags(device); acpi_bus_get_wakeup_device_flags(device);
/*
* Performance Management
* ----------------------
*/
if (device->flags.performance_manageable) {
result = acpi_bus_get_perf_flags(device);
if (result)
goto end;
}
if ((result = acpi_device_set_context(device)))
goto end;
device->flags.match_driver = match_driver; device->flags.match_driver = match_driver;
result = acpi_device_register(device); result = acpi_device_register(device);
if (result) {
end:
if (!result) {
acpi_power_add_remove_device(device, true);
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Adding %s [%s] parent %s\n", dev_name(&device->dev),
(char *) buffer.pointer,
device->parent ? dev_name(&device->parent->dev) :
"(null)"));
kfree(buffer.pointer);
*child = device;
} else
acpi_device_release(&device->dev); acpi_device_release(&device->dev);
return result;
}
return result; acpi_power_add_remove_device(device, true);
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n",
dev_name(&device->dev), (char *) buffer.pointer,
device->parent ? dev_name(&device->parent->dev) : "(null)"));
kfree(buffer.pointer);
*child = device;
return 0;
} }
#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
......
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