ACPI / PM: Check status of power resources under mutexes
It certainly is not a good idea to execute _ON or _OFF and _STA for the same power resource at the same time which may happen in some circumstances in theory. To prevent that from happening, read the power state of each power resource under its mutex, as that will prevent the state from being changed at the same time. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
parent
36237fa0a7
commit
d0515d9fec
|
@ -145,9 +145,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
|
||||||
|
|
||||||
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
|
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
|
||||||
{
|
{
|
||||||
int result = 0, state1;
|
int cur_state;
|
||||||
u32 i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
|
||||||
if (!list || !state)
|
if (!list || !state)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -155,25 +154,33 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
|
||||||
/* The state of the list is 'on' IFF all resources are 'on'. */
|
/* The state of the list is 'on' IFF all resources are 'on'. */
|
||||||
|
|
||||||
for (i = 0; i < list->count; i++) {
|
for (i = 0; i < list->count; i++) {
|
||||||
/*
|
struct acpi_power_resource *resource;
|
||||||
* The state of the power resource can be obtained by
|
acpi_handle handle = list->handles[i];
|
||||||
* using the ACPI handle. In such case it is unnecessary to
|
int result;
|
||||||
* get the Power resource first and then get its state again.
|
|
||||||
*/
|
result = acpi_power_get_context(handle, &resource);
|
||||||
result = acpi_power_get_state(list->handles[i], &state1);
|
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
*state = state1;
|
mutex_lock(&resource->resource_lock);
|
||||||
|
|
||||||
if (*state != ACPI_POWER_RESOURCE_STATE_ON)
|
result = acpi_power_get_state(handle, &cur_state);
|
||||||
|
|
||||||
|
mutex_unlock(&resource->resource_lock);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
|
||||||
*state ? "on" : "off"));
|
cur_state ? "on" : "off"));
|
||||||
|
|
||||||
return result;
|
*state = cur_state;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __acpi_power_on(struct acpi_power_resource *resource)
|
static int __acpi_power_on(struct acpi_power_resource *resource)
|
||||||
|
|
Loading…
Reference in New Issue