diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-17 08:11:07 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-17 08:11:07 -0500 |
commit | ef85bdbec444b42775a18580c6bfe1307a63ef0f (patch) | |
tree | ab98b0c41c1361438bff632a8a1cd739c63d8c53 /drivers | |
parent | 8bc5053bcdff09a6d1c6a61a79a9014884aa0a14 (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.h | 4 | ||||
-rw-r--r-- | drivers/acpi/power.c | 32 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 51 |
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 | -------------------------------------------------------------------------- */ |
52 | int acpi_power_init(void); | 52 | int acpi_power_init(void); |
53 | void acpi_power_resources_list_add(acpi_handle handle, struct list_head *list); | ||
54 | void acpi_power_resources_list_free(struct list_head *list); | 53 | void acpi_power_resources_list_free(struct list_head *list); |
54 | acpi_status acpi_extract_power_resources(union acpi_object *package, | ||
55 | unsigned int start, | ||
56 | struct list_head *list); | ||
55 | void acpi_add_power_resource(acpi_handle handle); | 57 | void acpi_add_power_resource(acpi_handle handle); |
56 | void acpi_power_add_remove_device(struct acpi_device *adev, bool add); | 58 | void acpi_power_add_remove_device(struct acpi_device *adev, bool add); |
57 | int acpi_device_sleep_wake(struct acpi_device *dev, | 59 | int 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 | ||
100 | void acpi_power_resources_list_add(acpi_handle handle, struct list_head *list) | 100 | static 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 | ||
136 | acpi_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 | |||
135 | static int acpi_power_get_state(acpi_handle handle, int *state) | 165 | static 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) | |||
1044 | static void acpi_bus_init_power_state(struct acpi_device *device, int state) | 1033 | static 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; |