ACPI / PM: Register power resource devices as soon as they are needed

Depending on the organization of the ACPI namespace, power resource
device objects may generally be scanned after the "regular" device
objects that they are referred from through _PRn.  This, in turn, may
cause acpi_bus_get_power_flags() to attempt to access them through
acpi_bus_init_power() before they are registered (and initialized by
acpi_power_driver).  [This is not a theoretical issue, it actually
happens for one PnP device on my testbed HP nx6325.]

To fix this problem, make acpi_bus_get_power_flags() attempt to
register power resource devices as soon as they have been found in
the _PRn output for any other devices.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
Rafael J. Wysocki 2010-11-25 00:10:44 +01:00 committed by Len Brown
parent 97d9a9e9f5
commit bf325f9538
1 changed files with 20 additions and 0 deletions

View File

@ -847,6 +847,8 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
return 0;
}
static void acpi_bus_add_power_resource(acpi_handle handle);
static int acpi_bus_get_power_flags(struct acpi_device *device)
{
acpi_status status = 0;
@ -875,8 +877,12 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
acpi_evaluate_reference(device->handle, object_name, NULL,
&ps->resources);
if (ps->resources.count) {
int j;
device->power.flags.power_resources = 1;
ps->flags.valid = 1;
for (j = 0; j < ps->resources.count; j++)
acpi_bus_add_power_resource(ps->resources.handles[j]);
}
/* Evaluate "_PSx" to see if we can do explicit sets */
@ -1323,6 +1329,20 @@ static int acpi_add_single_object(struct acpi_device **child,
#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
static void acpi_bus_add_power_resource(acpi_handle handle)
{
struct acpi_bus_ops ops = {
.acpi_op_add = 1,
.acpi_op_start = 1,
};
struct acpi_device *device = NULL;
acpi_bus_get_device(handle, &device);
if (!device)
acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
ACPI_STA_DEFAULT, &ops);
}
static int acpi_bus_type_and_status(acpi_handle handle, int *type,
unsigned long long *sta)
{