Commit 993cbe59 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPI / PM: Take order attribute of wakeup power resources into account

ACPI power resources have an order attribute that should be taken
into account when turning them on and off, but it is not used now.

Modify the power resources management code to preserve the
spec-compliant ordering of wakeup power resources.
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 0b224527
...@@ -469,7 +469,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev, ...@@ -469,7 +469,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
*/ */
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
{ {
int i, err = 0; int err = 0;
if (!dev || !dev->wakeup.flags.valid) if (!dev || !dev->wakeup.flags.valid)
return -EINVAL; return -EINVAL;
...@@ -479,24 +479,17 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) ...@@ -479,24 +479,17 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
if (dev->wakeup.prepare_count++) if (dev->wakeup.prepare_count++)
goto out; goto out;
/* Open power resource */ err = acpi_power_on_list(&dev->wakeup.resources);
for (i = 0; i < dev->wakeup.resources.count; i++) { if (err) {
int ret = acpi_power_on(dev->wakeup.resources.handles[i]); dev_err(&dev->dev, "Cannot turn wakeup power resources on\n");
if (ret) { dev->wakeup.flags.valid = 0;
printk(KERN_ERR PREFIX "Transition power state\n"); } else {
dev->wakeup.flags.valid = 0; /*
err = -ENODEV; * Passing 3 as the third argument below means the device may be
goto err_out; * put into arbitrary power state afterward.
} */
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
} }
/*
* Passing 3 as the third argument below means the device may be placed
* in arbitrary power state afterwards.
*/
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
err_out:
if (err) if (err)
dev->wakeup.prepare_count = 0; dev->wakeup.prepare_count = 0;
...@@ -513,7 +506,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) ...@@ -513,7 +506,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
*/ */
int acpi_disable_wakeup_device_power(struct acpi_device *dev) int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{ {
int i, err = 0; int err = 0;
if (!dev || !dev->wakeup.flags.valid) if (!dev || !dev->wakeup.flags.valid)
return -EINVAL; return -EINVAL;
...@@ -534,15 +527,10 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) ...@@ -534,15 +527,10 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
if (err) if (err)
goto out; goto out;
/* Close power resource */ err = acpi_power_off_list(&dev->wakeup.resources);
for (i = 0; i < dev->wakeup.resources.count; i++) { if (err) {
int ret = acpi_power_off(dev->wakeup.resources.handles[i]); dev_err(&dev->dev, "Cannot turn wakeup power resources off\n");
if (ret) { dev->wakeup.flags.valid = 0;
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
err = -ENODEV;
goto out;
}
} }
out: out:
......
...@@ -479,6 +479,9 @@ static void acpi_free_power_resources_lists(struct acpi_device *device) ...@@ -479,6 +479,9 @@ static void acpi_free_power_resources_lists(struct acpi_device *device)
{ {
int i; int i;
if (device->wakeup.flags.valid)
acpi_power_resources_list_free(&device->wakeup.resources);
if (!device->flags.power_manageable) if (!device->flags.power_manageable)
return; return;
...@@ -902,6 +905,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, ...@@ -902,6 +905,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
if (!wakeup) if (!wakeup)
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;
INIT_LIST_HEAD(&wakeup->resources);
/* _PRW */ /* _PRW */
status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer); status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -948,19 +953,17 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, ...@@ -948,19 +953,17 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
} }
wakeup->sleep_state = element->integer.value; wakeup->sleep_state = element->integer.value;
if ((package->package.count - 2) > ACPI_MAX_HANDLES) { for (i = 2; i < package->package.count; i++) {
status = AE_NO_MEMORY; acpi_handle rhandle;
goto out;
} element = &(package->package.elements[i]);
wakeup->resources.count = package->package.count - 2;
for (i = 0; i < wakeup->resources.count; i++) {
element = &(package->package.elements[i + 2]);
if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
status = AE_BAD_DATA; status = AE_BAD_DATA;
goto out; goto out;
} }
rhandle = element->reference.handle;
wakeup->resources.handles[i] = element->reference.handle; acpi_add_power_resource(rhandle);
acpi_power_resources_list_add(rhandle, &wakeup->resources);
} }
acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
...@@ -1018,6 +1021,7 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) ...@@ -1018,6 +1021,7 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
status = acpi_bus_extract_wakeup_device_power_package(device->handle, status = acpi_bus_extract_wakeup_device_power_package(device->handle,
&device->wakeup); &device->wakeup);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
acpi_power_resources_list_free(&device->wakeup.resources);
ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
return; return;
} }
...@@ -1491,9 +1495,11 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, ...@@ -1491,9 +1495,11 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
acpi_handle temp; acpi_handle temp;
status = acpi_get_handle(handle, "_PRW", &temp); status = acpi_get_handle(handle, "_PRW", &temp);
if (ACPI_SUCCESS(status)) if (ACPI_SUCCESS(status)) {
acpi_bus_extract_wakeup_device_power_package(handle, acpi_bus_extract_wakeup_device_power_package(handle,
&wakeup); &wakeup);
acpi_power_resources_list_free(&wakeup.resources);
}
return AE_CTRL_DEPTH; return AE_CTRL_DEPTH;
} }
......
...@@ -242,7 +242,7 @@ struct acpi_device_wakeup { ...@@ -242,7 +242,7 @@ struct acpi_device_wakeup {
acpi_handle gpe_device; acpi_handle gpe_device;
u64 gpe_number; u64 gpe_number;
u64 sleep_state; u64 sleep_state;
struct acpi_handle_list resources; struct list_head resources;
struct acpi_device_wakeup_flags flags; struct acpi_device_wakeup_flags flags;
int prepare_count; int prepare_count;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment