ACPI / PM: Introduce __acpi_bus_get_power()
authorRafael J. Wysocki <rjw@sisk.pl>
Wed, 24 Nov 2010 23:07:56 +0000 (00:07 +0100)
committerLen Brown <len.brown@intel.com>
Wed, 12 Jan 2011 09:48:44 +0000 (04:48 -0500)
It sometimes is necessary to get the power state of an ACPI device
without updating its device->power.state field, for example to
avoid inconsistencies between device->power.state and the reference
counters of the device's power resources.  For this purpose introduce
__acpi_bus_get_power() that will return the given device's power
state via a pointer (instead of modifying device->power.state)
and make acpi_bus_get_power() use it.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/bus.c

index a9fe8e6..9657abc 100644 (file)
@@ -196,34 +196,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data);
                                  Power Management
    -------------------------------------------------------------------------- */
 
-int acpi_bus_get_power(acpi_handle handle, int *state)
+static int __acpi_bus_get_power(struct acpi_device *device, int *state)
 {
        int result = 0;
        acpi_status status = 0;
-       struct acpi_device *device = NULL;
        unsigned long long psc = 0;
 
-
-       result = acpi_bus_get_device(handle, &device);
-       if (result)
-               return result;
+       if (!device || !state)
+               return -EINVAL;
 
        *state = ACPI_STATE_UNKNOWN;
 
-       if (!device->flags.power_manageable) {
-               /* TBD: Non-recursive algorithm for walking up hierarchy */
-               if (device->parent)
-                       *state = device->parent->power.state;
-               else
-                       *state = ACPI_STATE_D0;
-       } else {
+       if (device->flags.power_manageable) {
                /*
                 * Get the device's power state either directly (via _PSC) or
                 * indirectly (via power resources).
                 */
                if (device->power.flags.power_resources) {
-                       result = acpi_power_get_inferred_state(device,
-                                                       &device->power.state);
+                       result = acpi_power_get_inferred_state(device, state);
                        if (result)
                                return result;
                } else if (device->power.flags.explicit_get) {
@@ -231,20 +221,40 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
                                                       NULL, &psc);
                        if (ACPI_FAILURE(status))
                                return -ENODEV;
-                       device->power.state = (int)psc;
+                       *state = (int)psc;
                }
-
-               *state = device->power.state;
+       } else {
+               /* TBD: Non-recursive algorithm for walking up hierarchy. */
+               *state = device->parent ?
+                       device->parent->power.state : ACPI_STATE_D0;
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
-                         device->pnp.bus_id, device->power.state));
+                         device->pnp.bus_id, *state));
 
        return 0;
 }
 
+
+int acpi_bus_get_power(acpi_handle handle, int *state)
+{
+       struct acpi_device *device;
+       int result;
+
+       result = acpi_bus_get_device(handle, &device);
+       if (result)
+               return result;
+
+       result = __acpi_bus_get_power(device, state);
+       if (result)
+               return result;
+
+       device->power.state = *state;
+       return 0;
+}
 EXPORT_SYMBOL(acpi_bus_get_power);
 
+
 int acpi_bus_set_power(acpi_handle handle, int state)
 {
        int result = 0;