aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 23:15:35 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 23:15:35 -0500
commit52cfd503ad7176d23a5dd7af3981744feb60622f (patch)
tree0a8aeaaf4acbc86ac682f18632b8070c1c6b7ba1 /drivers/acpi/power.c
parentdc8e7e3ec60bd5ef7868aa88755e9d4c948dc5cc (diff)
parent4263d9a3ae4d15785897d0543bb59316c84ee605 (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (59 commits) ACPI / PM: Fix build problems for !CONFIG_ACPI related to NVS rework ACPI: fix resource check message ACPI / Battery: Update information on info notification and resume ACPI: Drop device flag wake_capable ACPI: Always check if _PRW is present before trying to evaluate it ACPI / PM: Check status of power resources under mutexes ACPI / PM: Rename acpi_power_off_device() ACPI / PM: Drop acpi_power_nocheck ACPI / PM: Drop acpi_bus_get_power() Platform / x86: Make fujitsu_laptop use acpi_bus_update_power() ACPI / Fan: Rework the handling of power resources ACPI / PM: Register power resource devices as soon as they are needed ACPI / PM: Register acpi_power_driver early ACPI / PM: Add function for updating device power state consistently ACPI / PM: Add function for device power state initialization ACPI / PM: Introduce __acpi_bus_get_power() ACPI / PM: Introduce function for refcounting device power resources ACPI / PM: Add functions for manipulating lists of power resources ACPI / PM: Prevent acpi_power_get_inferred_state() from making changes ACPICA: Update version to 20101209 ...
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c128
1 files changed, 72 insertions, 56 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 4c9c2fb5d98f..9ac2a9fa90ff 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -56,9 +56,6 @@ ACPI_MODULE_NAME("power");
56#define ACPI_POWER_RESOURCE_STATE_ON 0x01 56#define ACPI_POWER_RESOURCE_STATE_ON 0x01
57#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF 57#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
58 58
59int acpi_power_nocheck;
60module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
61
62static int acpi_power_add(struct acpi_device *device); 59static int acpi_power_add(struct acpi_device *device);
63static int acpi_power_remove(struct acpi_device *device, int type); 60static int acpi_power_remove(struct acpi_device *device, int type);
64static int acpi_power_resume(struct acpi_device *device); 61static int acpi_power_resume(struct acpi_device *device);
@@ -148,9 +145,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
148 145
149static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) 146static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
150{ 147{
151 int result = 0, state1; 148 int cur_state;
152 u32 i = 0; 149 int i = 0;
153
154 150
155 if (!list || !state) 151 if (!list || !state)
156 return -EINVAL; 152 return -EINVAL;
@@ -158,25 +154,33 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
158 /* The state of the list is 'on' IFF all resources are 'on'. */ 154 /* The state of the list is 'on' IFF all resources are 'on'. */
159 155
160 for (i = 0; i < list->count; i++) { 156 for (i = 0; i < list->count; i++) {
161 /* 157 struct acpi_power_resource *resource;
162 * The state of the power resource can be obtained by 158 acpi_handle handle = list->handles[i];
163 * using the ACPI handle. In such case it is unnecessary to 159 int result;
164 * get the Power resource first and then get its state again. 160
165 */ 161 result = acpi_power_get_context(handle, &resource);
166 result = acpi_power_get_state(list->handles[i], &state1);
167 if (result) 162 if (result)
168 return result; 163 return result;
169 164
170 *state = state1; 165 mutex_lock(&resource->resource_lock);
171 166
172 if (*state != ACPI_POWER_RESOURCE_STATE_ON) 167 result = acpi_power_get_state(handle, &cur_state);
168
169 mutex_unlock(&resource->resource_lock);
170
171 if (result)
172 return result;
173
174 if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
173 break; 175 break;
174 } 176 }
175 177
176 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", 178 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
177 *state ? "on" : "off")); 179 cur_state ? "on" : "off"));
178 180
179 return result; 181 *state = cur_state;
182
183 return 0;
180} 184}
181 185
182static int __acpi_power_on(struct acpi_power_resource *resource) 186static int __acpi_power_on(struct acpi_power_resource *resource)
@@ -222,7 +226,7 @@ static int acpi_power_on(acpi_handle handle)
222 return result; 226 return result;
223} 227}
224 228
225static int acpi_power_off_device(acpi_handle handle) 229static int acpi_power_off(acpi_handle handle)
226{ 230{
227 int result = 0; 231 int result = 0;
228 acpi_status status = AE_OK; 232 acpi_status status = AE_OK;
@@ -266,6 +270,35 @@ static int acpi_power_off_device(acpi_handle handle)
266 return result; 270 return result;
267} 271}
268 272
273static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res)
274{
275 int i;
276
277 for (i = num_res - 1; i >= 0 ; i--)
278 acpi_power_off(list->handles[i]);
279}
280
281static void acpi_power_off_list(struct acpi_handle_list *list)
282{
283 __acpi_power_off_list(list, list->count);
284}
285
286static int acpi_power_on_list(struct acpi_handle_list *list)
287{
288 int result = 0;
289 int i;
290
291 for (i = 0; i < list->count; i++) {
292 result = acpi_power_on(list->handles[i]);
293 if (result) {
294 __acpi_power_off_list(list, i);
295 break;
296 }
297 }
298
299 return result;
300}
301
269/** 302/**
270 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in 303 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
271 * ACPI 3.0) _PSW (Power State Wake) 304 * ACPI 3.0) _PSW (Power State Wake)
@@ -404,8 +437,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
404 437
405 /* Close power resource */ 438 /* Close power resource */
406 for (i = 0; i < dev->wakeup.resources.count; i++) { 439 for (i = 0; i < dev->wakeup.resources.count; i++) {
407 int ret = acpi_power_off_device( 440 int ret = acpi_power_off(dev->wakeup.resources.handles[i]);
408 dev->wakeup.resources.handles[i]);
409 if (ret) { 441 if (ret) {
410 printk(KERN_ERR PREFIX "Transition power state\n"); 442 printk(KERN_ERR PREFIX "Transition power state\n");
411 dev->wakeup.flags.valid = 0; 443 dev->wakeup.flags.valid = 0;
@@ -423,19 +455,16 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
423 Device Power Management 455 Device Power Management
424 -------------------------------------------------------------------------- */ 456 -------------------------------------------------------------------------- */
425 457
426int acpi_power_get_inferred_state(struct acpi_device *device) 458int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
427{ 459{
428 int result = 0; 460 int result = 0;
429 struct acpi_handle_list *list = NULL; 461 struct acpi_handle_list *list = NULL;
430 int list_state = 0; 462 int list_state = 0;
431 int i = 0; 463 int i = 0;
432 464
433 465 if (!device || !state)
434 if (!device)
435 return -EINVAL; 466 return -EINVAL;
436 467
437 device->power.state = ACPI_STATE_UNKNOWN;
438
439 /* 468 /*
440 * We know a device's inferred power state when all the resources 469 * We know a device's inferred power state when all the resources
441 * required for a given D-state are 'on'. 470 * required for a given D-state are 'on'.
@@ -450,22 +479,26 @@ int acpi_power_get_inferred_state(struct acpi_device *device)
450 return result; 479 return result;
451 480
452 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { 481 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
453 device->power.state = i; 482 *state = i;
454 return 0; 483 return 0;
455 } 484 }
456 } 485 }
457 486
458 device->power.state = ACPI_STATE_D3; 487 *state = ACPI_STATE_D3;
459
460 return 0; 488 return 0;
461} 489}
462 490
491int acpi_power_on_resources(struct acpi_device *device, int state)
492{
493 if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3)
494 return -EINVAL;
495
496 return acpi_power_on_list(&device->power.states[state].resources);
497}
498
463int acpi_power_transition(struct acpi_device *device, int state) 499int acpi_power_transition(struct acpi_device *device, int state)
464{ 500{
465 int result = 0; 501 int result;
466 struct acpi_handle_list *cl = NULL; /* Current Resources */
467 struct acpi_handle_list *tl = NULL; /* Target Resources */
468 int i = 0;
469 502
470 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) 503 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
471 return -EINVAL; 504 return -EINVAL;
@@ -477,37 +510,20 @@ int acpi_power_transition(struct acpi_device *device, int state)
477 || (device->power.state > ACPI_STATE_D3)) 510 || (device->power.state > ACPI_STATE_D3))
478 return -ENODEV; 511 return -ENODEV;
479 512
480 cl = &device->power.states[device->power.state].resources;
481 tl = &device->power.states[state].resources;
482
483 /* TBD: Resources must be ordered. */ 513 /* TBD: Resources must be ordered. */
484 514
485 /* 515 /*
486 * First we reference all power resources required in the target list 516 * First we reference all power resources required in the target list
487 * (e.g. so the device doesn't lose power while transitioning). 517 * (e.g. so the device doesn't lose power while transitioning). Then,
518 * we dereference all power resources used in the current list.
488 */ 519 */
489 for (i = 0; i < tl->count; i++) { 520 result = acpi_power_on_list(&device->power.states[state].resources);
490 result = acpi_power_on(tl->handles[i]); 521 if (!result)
491 if (result) 522 acpi_power_off_list(
492 goto end; 523 &device->power.states[device->power.state].resources);
493 }
494 524
495 /* 525 /* We shouldn't change the state unless the above operations succeed. */
496 * Then we dereference all power resources used in the current list. 526 device->power.state = result ? ACPI_STATE_UNKNOWN : state;
497 */
498 for (i = 0; i < cl->count; i++) {
499 result = acpi_power_off_device(cl->handles[i]);
500 if (result)
501 goto end;
502 }
503
504 end:
505 if (result)
506 device->power.state = ACPI_STATE_UNKNOWN;
507 else {
508 /* We shouldn't change the state till all above operations succeed */
509 device->power.state = state;
510 }
511 527
512 return result; 528 return result;
513} 529}