aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
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
commit0b224527323669c66e0a37ae05b04034bfcdce14 (patch)
treeb7332e4f7492220d651374a5de56ebd03cbb22e5 /drivers/acpi/scan.c
parent722c929f32616943d2b67332068f09c08e81eec8 (diff)
ACPI / PM: Take order attribute of 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 power resources that power states of devices depend on (analogous changes will be done separately for power resources used for wakeup). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index c7ea9c2649a4..d557868c0081 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -475,11 +475,25 @@ void acpi_free_ids(struct acpi_device *device)
475 kfree(device->pnp.unique_id); 475 kfree(device->pnp.unique_id);
476} 476}
477 477
478static void acpi_free_power_resources_lists(struct acpi_device *device)
479{
480 int i;
481
482 if (!device->flags.power_manageable)
483 return;
484
485 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
486 struct acpi_device_power_state *ps = &device->power.states[i];
487 acpi_power_resources_list_free(&ps->resources);
488 }
489}
490
478static void acpi_device_release(struct device *dev) 491static void acpi_device_release(struct device *dev)
479{ 492{
480 struct acpi_device *acpi_dev = to_acpi_device(dev); 493 struct acpi_device *acpi_dev = to_acpi_device(dev);
481 494
482 acpi_free_ids(acpi_dev); 495 acpi_free_ids(acpi_dev);
496 acpi_free_power_resources_lists(acpi_dev);
483 kfree(acpi_dev); 497 kfree(acpi_dev);
484} 498}
485 499
@@ -1055,17 +1069,22 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
1055 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { 1069 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
1056 struct acpi_device_power_state *ps = &device->power.states[i]; 1070 struct acpi_device_power_state *ps = &device->power.states[i];
1057 char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; 1071 char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
1072 struct acpi_handle_list resources;
1058 1073
1074 INIT_LIST_HEAD(&ps->resources);
1059 /* Evaluate "_PRx" to se if power resources are referenced */ 1075 /* Evaluate "_PRx" to se if power resources are referenced */
1060 acpi_evaluate_reference(device->handle, object_name, NULL, 1076 acpi_evaluate_reference(device->handle, object_name, NULL,
1061 &ps->resources); 1077 &resources);
1062 if (ps->resources.count) { 1078 if (resources.count) {
1063 int j; 1079 int j;
1064 1080
1065 device->power.flags.power_resources = 1; 1081 device->power.flags.power_resources = 1;
1066 for (j = 0; j < ps->resources.count; j++) { 1082 for (j = 0; j < resources.count; j++) {
1067 acpi_handle rhandle = ps->resources.handles[j]; 1083 acpi_handle rhandle = resources.handles[j];
1084
1068 acpi_add_power_resource(rhandle); 1085 acpi_add_power_resource(rhandle);
1086 acpi_power_resources_list_add(rhandle,
1087 &ps->resources);
1069 } 1088 }
1070 } 1089 }
1071 1090
@@ -1079,7 +1098,7 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
1079 * State is valid if there are means to put the device into it. 1098 * State is valid if there are means to put the device into it.
1080 * D3hot is only valid if _PR3 present. 1099 * D3hot is only valid if _PR3 present.
1081 */ 1100 */
1082 if (ps->resources.count || 1101 if (resources.count ||
1083 (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) { 1102 (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) {
1084 ps->flags.valid = 1; 1103 ps->flags.valid = 1;
1085 ps->flags.os_accessible = 1; 1104 ps->flags.os_accessible = 1;
@@ -1089,6 +1108,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
1089 ps->latency = -1; /* Unknown - driver assigned */ 1108 ps->latency = -1; /* Unknown - driver assigned */
1090 } 1109 }
1091 1110
1111 INIT_LIST_HEAD(&device->power.states[ACPI_STATE_D3_COLD].resources);
1112
1092 /* Set defaults for D0 and D3 states (always valid) */ 1113 /* Set defaults for D0 and D3 states (always valid) */
1093 device->power.states[ACPI_STATE_D0].flags.valid = 1; 1114 device->power.states[ACPI_STATE_D0].flags.valid = 1;
1094 device->power.states[ACPI_STATE_D0].power = 100; 1115 device->power.states[ACPI_STATE_D0].power = 100;