diff options
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r-- | drivers/acpi/power.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ab21cb1c8c7..a1718e56103b 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power"); | |||
54 | #define ACPI_POWER_RESOURCE_STATE_OFF 0x00 | 54 | #define ACPI_POWER_RESOURCE_STATE_OFF 0x00 |
55 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 | 55 | #define ACPI_POWER_RESOURCE_STATE_ON 0x01 |
56 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF | 56 | #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF |
57 | |||
58 | #ifdef MODULE_PARAM_PREFIX | ||
59 | #undef MODULE_PARAM_PREFIX | ||
60 | #endif | ||
61 | #define MODULE_PARAM_PREFIX "acpi." | ||
62 | int acpi_power_nocheck; | ||
63 | module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); | ||
64 | |||
57 | static int acpi_power_add(struct acpi_device *device); | 65 | static int acpi_power_add(struct acpi_device *device); |
58 | static int acpi_power_remove(struct acpi_device *device, int type); | 66 | static int acpi_power_remove(struct acpi_device *device, int type); |
59 | static int acpi_power_resume(struct acpi_device *device); | 67 | static int acpi_power_resume(struct acpi_device *device); |
@@ -128,16 +136,16 @@ acpi_power_get_context(acpi_handle handle, | |||
128 | return 0; | 136 | return 0; |
129 | } | 137 | } |
130 | 138 | ||
131 | static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) | 139 | static int acpi_power_get_state(acpi_handle handle, int *state) |
132 | { | 140 | { |
133 | acpi_status status = AE_OK; | 141 | acpi_status status = AE_OK; |
134 | unsigned long sta = 0; | 142 | unsigned long long sta = 0; |
135 | 143 | ||
136 | 144 | ||
137 | if (!resource || !state) | 145 | if (!handle || !state) |
138 | return -EINVAL; | 146 | return -EINVAL; |
139 | 147 | ||
140 | status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); | 148 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
141 | if (ACPI_FAILURE(status)) | 149 | if (ACPI_FAILURE(status)) |
142 | return -ENODEV; | 150 | return -ENODEV; |
143 | 151 | ||
@@ -145,7 +153,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state | |||
145 | ACPI_POWER_RESOURCE_STATE_OFF; | 153 | ACPI_POWER_RESOURCE_STATE_OFF; |
146 | 154 | ||
147 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", | 155 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", |
148 | resource->name, state ? "on" : "off")); | 156 | acpi_ut_get_node_name(handle), state ? "on" : "off")); |
149 | 157 | ||
150 | return 0; | 158 | return 0; |
151 | } | 159 | } |
@@ -153,7 +161,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state | |||
153 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | 161 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) |
154 | { | 162 | { |
155 | int result = 0, state1; | 163 | int result = 0, state1; |
156 | struct acpi_power_resource *resource = NULL; | ||
157 | u32 i = 0; | 164 | u32 i = 0; |
158 | 165 | ||
159 | 166 | ||
@@ -161,12 +168,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
161 | return -EINVAL; | 168 | return -EINVAL; |
162 | 169 | ||
163 | /* The state of the list is 'on' IFF all resources are 'on'. */ | 170 | /* The state of the list is 'on' IFF all resources are 'on'. */ |
171 | /* */ | ||
164 | 172 | ||
165 | for (i = 0; i < list->count; i++) { | 173 | for (i = 0; i < list->count; i++) { |
166 | result = acpi_power_get_context(list->handles[i], &resource); | 174 | /* |
167 | if (result) | 175 | * The state of the power resource can be obtained by |
168 | return result; | 176 | * using the ACPI handle. In such case it is unnecessary to |
169 | result = acpi_power_get_state(resource, &state1); | 177 | * get the Power resource first and then get its state again. |
178 | */ | ||
179 | result = acpi_power_get_state(list->handles[i], &state1); | ||
170 | if (result) | 180 | if (result) |
171 | return result; | 181 | return result; |
172 | 182 | ||
@@ -226,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
226 | if (ACPI_FAILURE(status)) | 236 | if (ACPI_FAILURE(status)) |
227 | return -ENODEV; | 237 | return -ENODEV; |
228 | 238 | ||
229 | result = acpi_power_get_state(resource, &state); | 239 | if (!acpi_power_nocheck) { |
230 | if (result) | 240 | /* |
231 | return result; | 241 | * If acpi_power_nocheck is set, it is unnecessary to check |
232 | if (state != ACPI_POWER_RESOURCE_STATE_ON) | 242 | * the power state after power transition. |
233 | return -ENOEXEC; | 243 | */ |
234 | 244 | result = acpi_power_get_state(resource->device->handle, | |
245 | &state); | ||
246 | if (result) | ||
247 | return result; | ||
248 | if (state != ACPI_POWER_RESOURCE_STATE_ON) | ||
249 | return -ENOEXEC; | ||
250 | } | ||
235 | /* Update the power resource's _device_ power state */ | 251 | /* Update the power resource's _device_ power state */ |
236 | resource->device->power.state = ACPI_STATE_D0; | 252 | resource->device->power.state = ACPI_STATE_D0; |
237 | 253 | ||
@@ -277,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
277 | if (ACPI_FAILURE(status)) | 293 | if (ACPI_FAILURE(status)) |
278 | return -ENODEV; | 294 | return -ENODEV; |
279 | 295 | ||
280 | result = acpi_power_get_state(resource, &state); | 296 | if (!acpi_power_nocheck) { |
281 | if (result) | 297 | /* |
282 | return result; | 298 | * If acpi_power_nocheck is set, it is unnecessary to check |
283 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) | 299 | * the power state after power transition. |
284 | return -ENOEXEC; | 300 | */ |
301 | result = acpi_power_get_state(handle, &state); | ||
302 | if (result) | ||
303 | return result; | ||
304 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) | ||
305 | return -ENOEXEC; | ||
306 | } | ||
285 | 307 | ||
286 | /* Update the power resource's _device_ power state */ | 308 | /* Update the power resource's _device_ power state */ |
287 | resource->device->power.state = ACPI_STATE_D3; | 309 | resource->device->power.state = ACPI_STATE_D3; |
@@ -555,7 +577,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) | |||
555 | if (!resource) | 577 | if (!resource) |
556 | goto end; | 578 | goto end; |
557 | 579 | ||
558 | result = acpi_power_get_state(resource, &state); | 580 | result = acpi_power_get_state(resource->device->handle, &state); |
559 | if (result) | 581 | if (result) |
560 | goto end; | 582 | goto end; |
561 | 583 | ||
@@ -657,7 +679,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
657 | strcpy(resource->name, device->pnp.bus_id); | 679 | strcpy(resource->name, device->pnp.bus_id); |
658 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 680 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
659 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 681 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
660 | acpi_driver_data(device) = resource; | 682 | device->driver_data = resource; |
661 | 683 | ||
662 | /* Evalute the object to get the system level and resource order. */ | 684 | /* Evalute the object to get the system level and resource order. */ |
663 | status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); | 685 | status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); |
@@ -668,7 +690,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
668 | resource->system_level = acpi_object.power_resource.system_level; | 690 | resource->system_level = acpi_object.power_resource.system_level; |
669 | resource->order = acpi_object.power_resource.resource_order; | 691 | resource->order = acpi_object.power_resource.resource_order; |
670 | 692 | ||
671 | result = acpi_power_get_state(resource, &state); | 693 | result = acpi_power_get_state(device->handle, &state); |
672 | if (result) | 694 | if (result) |
673 | goto end; | 695 | goto end; |
674 | 696 | ||
@@ -733,9 +755,9 @@ static int acpi_power_resume(struct acpi_device *device) | |||
733 | if (!device || !acpi_driver_data(device)) | 755 | if (!device || !acpi_driver_data(device)) |
734 | return -EINVAL; | 756 | return -EINVAL; |
735 | 757 | ||
736 | resource = (struct acpi_power_resource *)acpi_driver_data(device); | 758 | resource = acpi_driver_data(device); |
737 | 759 | ||
738 | result = acpi_power_get_state(resource, &state); | 760 | result = acpi_power_get_state(device->handle, &state); |
739 | if (result) | 761 | if (result) |
740 | return result; | 762 | return result; |
741 | 763 | ||