aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:07 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:07 -0500
commitef85bdbec444b42775a18580c6bfe1307a63ef0f (patch)
treeab98b0c41c1361438bff632a8a1cd739c63d8c53 /drivers
parent8bc5053bcdff09a6d1c6a61a79a9014884aa0a14 (diff)
ACPI / scan: Consolidate extraction of power resources lists
The lists of ACPI power resources are currently extracted in two different ways, one for wakeup power resources and one for power resources that device power states depend on. There is no reason why it should be done differently in those two cases, so introduce a common routine for extracting power resources lists from data returned by AML, acpi_extract_power_resources(), and make the namespace scanning code use it for both wakeup and device power states power resources. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/internal.h4
-rw-r--r--drivers/acpi/power.c32
-rw-r--r--drivers/acpi/scan.c51
3 files changed, 55 insertions, 32 deletions
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index e28068a765a9..c35435e3d760 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -50,8 +50,10 @@ void acpi_free_ids(struct acpi_device *device);
50 Power Resource 50 Power Resource
51 -------------------------------------------------------------------------- */ 51 -------------------------------------------------------------------------- */
52int acpi_power_init(void); 52int acpi_power_init(void);
53void acpi_power_resources_list_add(acpi_handle handle, struct list_head *list);
54void acpi_power_resources_list_free(struct list_head *list); 53void acpi_power_resources_list_free(struct list_head *list);
54acpi_status acpi_extract_power_resources(union acpi_object *package,
55 unsigned int start,
56 struct list_head *list);
55void acpi_add_power_resource(acpi_handle handle); 57void acpi_add_power_resource(acpi_handle handle);
56void acpi_power_add_remove_device(struct acpi_device *adev, bool add); 58void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
57int acpi_device_sleep_wake(struct acpi_device *dev, 59int acpi_device_sleep_wake(struct acpi_device *dev,
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 242feca231eb..4b93c97aff9f 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -97,7 +97,8 @@ static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
97 return container_of(device, struct acpi_power_resource, device); 97 return container_of(device, struct acpi_power_resource, device);
98} 98}
99 99
100void acpi_power_resources_list_add(acpi_handle handle, struct list_head *list) 100static void acpi_power_resources_list_add(acpi_handle handle,
101 struct list_head *list)
101{ 102{
102 struct acpi_power_resource *resource = acpi_power_get_context(handle); 103 struct acpi_power_resource *resource = acpi_power_get_context(handle);
103 struct acpi_power_resource_entry *entry; 104 struct acpi_power_resource_entry *entry;
@@ -132,6 +133,35 @@ void acpi_power_resources_list_free(struct list_head *list)
132 } 133 }
133} 134}
134 135
136acpi_status acpi_extract_power_resources(union acpi_object *package,
137 unsigned int start,
138 struct list_head *list)
139{
140 acpi_status status = AE_OK;
141 unsigned int i;
142
143 for (i = start; i < package->package.count; i++) {
144 union acpi_object *element = &package->package.elements[i];
145 acpi_handle rhandle;
146
147 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
148 status = AE_BAD_DATA;
149 break;
150 }
151 rhandle = element->reference.handle;
152 if (!rhandle) {
153 status = AE_NULL_ENTRY;
154 break;
155 }
156 acpi_add_power_resource(rhandle);
157 acpi_power_resources_list_add(rhandle, list);
158 }
159 if (ACPI_FAILURE(status))
160 acpi_power_resources_list_free(list);
161
162 return status;
163}
164
135static int acpi_power_get_state(acpi_handle handle, int *state) 165static int acpi_power_get_state(acpi_handle handle, int *state)
136{ 166{
137 acpi_status status = AE_OK; 167 acpi_status status = AE_OK;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 8da315418d94..d80df969f64a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -900,7 +900,6 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
900 union acpi_object *package = NULL; 900 union acpi_object *package = NULL;
901 union acpi_object *element = NULL; 901 union acpi_object *element = NULL;
902 acpi_status status; 902 acpi_status status;
903 int i = 0;
904 903
905 if (!wakeup) 904 if (!wakeup)
906 return AE_BAD_PARAMETER; 905 return AE_BAD_PARAMETER;
@@ -953,18 +952,9 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
953 } 952 }
954 wakeup->sleep_state = element->integer.value; 953 wakeup->sleep_state = element->integer.value;
955 954
956 for (i = 2; i < package->package.count; i++) { 955 status = acpi_extract_power_resources(package, 2, &wakeup->resources);
957 acpi_handle rhandle; 956 if (ACPI_FAILURE(status))
958 957 goto out;
959 element = &(package->package.elements[i]);
960 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
961 status = AE_BAD_DATA;
962 goto out;
963 }
964 rhandle = element->reference.handle;
965 acpi_add_power_resource(rhandle);
966 acpi_power_resources_list_add(rhandle, &wakeup->resources);
967 }
968 958
969 acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); 959 acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
970 960
@@ -1021,7 +1011,6 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
1021 status = acpi_bus_extract_wakeup_device_power_package(device->handle, 1011 status = acpi_bus_extract_wakeup_device_power_package(device->handle,
1022 &device->wakeup); 1012 &device->wakeup);
1023 if (ACPI_FAILURE(status)) { 1013 if (ACPI_FAILURE(status)) {
1024 acpi_power_resources_list_free(&device->wakeup.resources);
1025 ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); 1014 ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
1026 return; 1015 return;
1027 } 1016 }
@@ -1044,30 +1033,32 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
1044static void acpi_bus_init_power_state(struct acpi_device *device, int state) 1033static void acpi_bus_init_power_state(struct acpi_device *device, int state)
1045{ 1034{
1046 struct acpi_device_power_state *ps = &device->power.states[state]; 1035 struct acpi_device_power_state *ps = &device->power.states[state];
1047 char object_name[5] = { '_', 'P', 'R', '0' + state, '\0' }; 1036 char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' };
1048 struct acpi_handle_list resources; 1037 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1049 acpi_handle handle; 1038 acpi_handle handle;
1050 acpi_status status; 1039 acpi_status status;
1051 1040
1052 INIT_LIST_HEAD(&ps->resources); 1041 INIT_LIST_HEAD(&ps->resources);
1053 1042
1054 /* Evaluate "_PRx" to se if power resources are referenced */ 1043 /* Evaluate "_PRx" to get referenced power resources */
1055 acpi_evaluate_reference(device->handle, object_name, NULL, &resources); 1044 status = acpi_evaluate_object(device->handle, pathname, NULL, &buffer);
1056 if (resources.count) { 1045 if (ACPI_SUCCESS(status)) {
1057 int j; 1046 union acpi_object *package = buffer.pointer;
1058 1047
1059 device->power.flags.power_resources = 1; 1048 if (buffer.length && package
1060 for (j = 0; j < resources.count; j++) { 1049 && package->type == ACPI_TYPE_PACKAGE
1061 acpi_handle rhandle = resources.handles[j]; 1050 && package->package.count) {
1062 1051 status = acpi_extract_power_resources(package, 0,
1063 acpi_add_power_resource(rhandle); 1052 &ps->resources);
1064 acpi_power_resources_list_add(rhandle, &ps->resources); 1053 if (ACPI_SUCCESS(status))
1054 device->power.flags.power_resources = 1;
1065 } 1055 }
1056 ACPI_FREE(buffer.pointer);
1066 } 1057 }
1067 1058
1068 /* Evaluate "_PSx" to see if we can do explicit sets */ 1059 /* Evaluate "_PSx" to see if we can do explicit sets */
1069 object_name[2] = 'S'; 1060 pathname[2] = 'S';
1070 status = acpi_get_handle(device->handle, object_name, &handle); 1061 status = acpi_get_handle(device->handle, pathname, &handle);
1071 if (ACPI_SUCCESS(status)) 1062 if (ACPI_SUCCESS(status))
1072 ps->flags.explicit_set = 1; 1063 ps->flags.explicit_set = 1;
1073 1064
@@ -1075,7 +1066,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
1075 * State is valid if there are means to put the device into it. 1066 * State is valid if there are means to put the device into it.
1076 * D3hot is only valid if _PR3 present. 1067 * D3hot is only valid if _PR3 present.
1077 */ 1068 */
1078 if (resources.count 1069 if (!list_empty(&ps->resources)
1079 || (ps->flags.explicit_set && state < ACPI_STATE_D3_HOT)) { 1070 || (ps->flags.explicit_set && state < ACPI_STATE_D3_HOT)) {
1080 ps->flags.valid = 1; 1071 ps->flags.valid = 1;
1081 ps->flags.os_accessible = 1; 1072 ps->flags.os_accessible = 1;