aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:06 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:06 -0500
commit993cbe595dda731471a07f4f65575fadedc570dc (patch)
tree2fb3877c89bf031acdbae666fe4530d88eb5945f /drivers
parent0b224527323669c66e0a37ae05b04034bfcdce14 (diff)
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/power.c44
-rw-r--r--drivers/acpi/scan.c26
2 files changed, 32 insertions, 38 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 22a3d00d0359..242feca231eb 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -469,7 +469,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
469 */ 469 */
470int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) 470int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
471{ 471{
472 int i, err = 0; 472 int err = 0;
473 473
474 if (!dev || !dev->wakeup.flags.valid) 474 if (!dev || !dev->wakeup.flags.valid)
475 return -EINVAL; 475 return -EINVAL;
@@ -479,24 +479,17 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
479 if (dev->wakeup.prepare_count++) 479 if (dev->wakeup.prepare_count++)
480 goto out; 480 goto out;
481 481
482 /* Open power resource */ 482 err = acpi_power_on_list(&dev->wakeup.resources);
483 for (i = 0; i < dev->wakeup.resources.count; i++) { 483 if (err) {
484 int ret = acpi_power_on(dev->wakeup.resources.handles[i]); 484 dev_err(&dev->dev, "Cannot turn wakeup power resources on\n");
485 if (ret) { 485 dev->wakeup.flags.valid = 0;
486 printk(KERN_ERR PREFIX "Transition power state\n"); 486 } else {
487 dev->wakeup.flags.valid = 0; 487 /*
488 err = -ENODEV; 488 * Passing 3 as the third argument below means the device may be
489 goto err_out; 489 * put into arbitrary power state afterward.
490 } 490 */
491 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
491 } 492 }
492
493 /*
494 * Passing 3 as the third argument below means the device may be placed
495 * in arbitrary power state afterwards.
496 */
497 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
498
499 err_out:
500 if (err) 493 if (err)
501 dev->wakeup.prepare_count = 0; 494 dev->wakeup.prepare_count = 0;
502 495
@@ -513,7 +506,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
513 */ 506 */
514int acpi_disable_wakeup_device_power(struct acpi_device *dev) 507int acpi_disable_wakeup_device_power(struct acpi_device *dev)
515{ 508{
516 int i, err = 0; 509 int err = 0;
517 510
518 if (!dev || !dev->wakeup.flags.valid) 511 if (!dev || !dev->wakeup.flags.valid)
519 return -EINVAL; 512 return -EINVAL;
@@ -534,15 +527,10 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
534 if (err) 527 if (err)
535 goto out; 528 goto out;
536 529
537 /* Close power resource */ 530 err = acpi_power_off_list(&dev->wakeup.resources);
538 for (i = 0; i < dev->wakeup.resources.count; i++) { 531 if (err) {
539 int ret = acpi_power_off(dev->wakeup.resources.handles[i]); 532 dev_err(&dev->dev, "Cannot turn wakeup power resources off\n");
540 if (ret) { 533 dev->wakeup.flags.valid = 0;
541 printk(KERN_ERR PREFIX "Transition power state\n");
542 dev->wakeup.flags.valid = 0;
543 err = -ENODEV;
544 goto out;
545 }
546 } 534 }
547 535
548 out: 536 out:
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d557868c0081..e4ac46a9c664 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -479,6 +479,9 @@ static void acpi_free_power_resources_lists(struct acpi_device *device)
479{ 479{
480 int i; 480 int i;
481 481
482 if (device->wakeup.flags.valid)
483 acpi_power_resources_list_free(&device->wakeup.resources);
484
482 if (!device->flags.power_manageable) 485 if (!device->flags.power_manageable)
483 return; 486 return;
484 487
@@ -902,6 +905,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
902 if (!wakeup) 905 if (!wakeup)
903 return AE_BAD_PARAMETER; 906 return AE_BAD_PARAMETER;
904 907
908 INIT_LIST_HEAD(&wakeup->resources);
909
905 /* _PRW */ 910 /* _PRW */
906 status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer); 911 status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
907 if (ACPI_FAILURE(status)) { 912 if (ACPI_FAILURE(status)) {
@@ -948,19 +953,17 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
948 } 953 }
949 wakeup->sleep_state = element->integer.value; 954 wakeup->sleep_state = element->integer.value;
950 955
951 if ((package->package.count - 2) > ACPI_MAX_HANDLES) { 956 for (i = 2; i < package->package.count; i++) {
952 status = AE_NO_MEMORY; 957 acpi_handle rhandle;
953 goto out; 958
954 } 959 element = &(package->package.elements[i]);
955 wakeup->resources.count = package->package.count - 2;
956 for (i = 0; i < wakeup->resources.count; i++) {
957 element = &(package->package.elements[i + 2]);
958 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { 960 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
959 status = AE_BAD_DATA; 961 status = AE_BAD_DATA;
960 goto out; 962 goto out;
961 } 963 }
962 964 rhandle = element->reference.handle;
963 wakeup->resources.handles[i] = element->reference.handle; 965 acpi_add_power_resource(rhandle);
966 acpi_power_resources_list_add(rhandle, &wakeup->resources);
964 } 967 }
965 968
966 acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); 969 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 status = acpi_bus_extract_wakeup_device_power_package(device->handle, 1021 status = acpi_bus_extract_wakeup_device_power_package(device->handle,
1019 &device->wakeup); 1022 &device->wakeup);
1020 if (ACPI_FAILURE(status)) { 1023 if (ACPI_FAILURE(status)) {
1024 acpi_power_resources_list_free(&device->wakeup.resources);
1021 ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); 1025 ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
1022 return; 1026 return;
1023 } 1027 }
@@ -1491,9 +1495,11 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1491 acpi_handle temp; 1495 acpi_handle temp;
1492 1496
1493 status = acpi_get_handle(handle, "_PRW", &temp); 1497 status = acpi_get_handle(handle, "_PRW", &temp);
1494 if (ACPI_SUCCESS(status)) 1498 if (ACPI_SUCCESS(status)) {
1495 acpi_bus_extract_wakeup_device_power_package(handle, 1499 acpi_bus_extract_wakeup_device_power_package(handle,
1496 &wakeup); 1500 &wakeup);
1501 acpi_power_resources_list_free(&wakeup.resources);
1502 }
1497 return AE_CTRL_DEPTH; 1503 return AE_CTRL_DEPTH;
1498 } 1504 }
1499 1505