summaryrefslogtreecommitdiff
path: root/drivers/acpi/bus.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-11-25 02:07:56 +0300
committerLen Brown <len.brown@intel.com>2011-01-12 12:48:44 +0300
commit5e6d4fe4296782f1f095575b8213a97c3e925a16 (patch)
tree3d2376b9b18536acfa20777172ab132a475bb0ae /drivers/acpi/bus.c
parent30d3df41b32b1ea63d3ebc52ef5644cbe41520f4 (diff)
downloadlinux-5e6d4fe4296782f1f095575b8213a97c3e925a16.tar.xz
ACPI / PM: Introduce __acpi_bus_get_power()
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>
Diffstat (limited to 'drivers/acpi/bus.c')
-rw-r--r--drivers/acpi/bus.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index a9fe8e6bc40e..9657abc4a7fb 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -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;