From ade3e7fef794781c0798d0cf0f046123842ba550 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 25 Nov 2010 00:08:36 +0100 Subject: ACPI / PM: Add function for device power state initialization Add function acpi_bus_init_power() for getting the initial power state of an ACPI device and reference counting its power resources as appropriate. Make acpi_bus_get_power_flags() use the new function instead of acpi_bus_get_power() that updates device->power.state without reference counting the device's power resources. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/scan.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/acpi/scan.c') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 29ef505c487b..ef8e659771e1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -901,10 +901,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) device->power.states[ACPI_STATE_D3].flags.valid = 1; device->power.states[ACPI_STATE_D3].power = 0; - /* TBD: System wake support and resource requirements. */ - - device->power.state = ACPI_STATE_UNKNOWN; - acpi_bus_get_power(device->handle, &(device->power.state)); + acpi_bus_init_power(device); return 0; } -- cgit v1.2.3 From 97d9a9e9f5ee68f20005ca5aa77c6b684e7cace8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 25 Nov 2010 00:10:02 +0100 Subject: ACPI / PM: Register acpi_power_driver early The ACPI device driver used for handling power resources, acpi_power_driver, creates a struct acpi_power_resource object for each ACPI device representing a power resource. These objects are then used when setting and reading the power states of devices using the corresponding power resources. Unfortunately, acpi_power_driver is registered after acpi_scan_init() that may add devices using the power resources before acpi_power_driver has a chance to create struct acpi_power_resource objects for them (specifically, the power resources may be referred to during the scanning process through acpi_bus_get_power() before they have been initialized). As the first step towards fixing this issue, move the registration of acpi_power_driver into acpi_scan_init() so that power resource devices can be initialized by it as soon as they have been found in the namespace. Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/scan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi/scan.c') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ef8e659771e1..2951a27303cb 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1570,6 +1570,8 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); } + acpi_power_init(); + /* * Enumerate devices in the ACPI namespace. */ -- cgit v1.2.3 From bf325f9538d8c89312be305b9779edbcb436af00 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 25 Nov 2010 00:10:44 +0100 Subject: 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 Signed-off-by: Len Brown --- drivers/acpi/scan.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/acpi/scan.c') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2951a27303cb..cb7956c23ca4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -847,6 +847,8 @@ end: 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 @@ end: #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) { -- cgit v1.2.3