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>
This commit is contained in:
parent
30d3df41b3
commit
5e6d4fe429
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue