aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c102
1 files changed, 56 insertions, 46 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 67dedeed144c..0003f1009885 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);
@@ -213,11 +210,13 @@ static int acpi_power_on(acpi_handle handle)
213 resource->name)); 210 resource->name));
214 } else { 211 } else {
215 result = __acpi_power_on(resource); 212 result = __acpi_power_on(resource);
213 if (result)
214 resource->ref_count--;
216 } 215 }
217 216
218 mutex_unlock(&resource->resource_lock); 217 mutex_unlock(&resource->resource_lock);
219 218
220 return 0; 219 return result;
221} 220}
222 221
223static int acpi_power_off_device(acpi_handle handle) 222static int acpi_power_off_device(acpi_handle handle)
@@ -264,6 +263,35 @@ static int acpi_power_off_device(acpi_handle handle)
264 return result; 263 return result;
265} 264}
266 265
266static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res)
267{
268 int i;
269
270 for (i = num_res - 1; i >= 0 ; i--)
271 acpi_power_off_device(list->handles[i]);
272}
273
274static void acpi_power_off_list(struct acpi_handle_list *list)
275{
276 __acpi_power_off_list(list, list->count);
277}
278
279static int acpi_power_on_list(struct acpi_handle_list *list)
280{
281 int result = 0;
282 int i;
283
284 for (i = 0; i < list->count; i++) {
285 result = acpi_power_on(list->handles[i]);
286 if (result) {
287 __acpi_power_off_list(list, i);
288 break;
289 }
290 }
291
292 return result;
293}
294
267/** 295/**
268 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in 296 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
269 * ACPI 3.0) _PSW (Power State Wake) 297 * ACPI 3.0) _PSW (Power State Wake)
@@ -421,19 +449,16 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
421 Device Power Management 449 Device Power Management
422 -------------------------------------------------------------------------- */ 450 -------------------------------------------------------------------------- */
423 451
424int acpi_power_get_inferred_state(struct acpi_device *device) 452int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
425{ 453{
426 int result = 0; 454 int result = 0;
427 struct acpi_handle_list *list = NULL; 455 struct acpi_handle_list *list = NULL;
428 int list_state = 0; 456 int list_state = 0;
429 int i = 0; 457 int i = 0;
430 458
431 459 if (!device || !state)
432 if (!device)
433 return -EINVAL; 460 return -EINVAL;
434 461
435 device->power.state = ACPI_STATE_UNKNOWN;
436
437 /* 462 /*
438 * We know a device's inferred power state when all the resources 463 * We know a device's inferred power state when all the resources
439 * required for a given D-state are 'on'. 464 * required for a given D-state are 'on'.
@@ -448,66 +473,51 @@ int acpi_power_get_inferred_state(struct acpi_device *device)
448 return result; 473 return result;
449 474
450 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { 475 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
451 device->power.state = i; 476 *state = i;
452 return 0; 477 return 0;
453 } 478 }
454 } 479 }
455 480
456 device->power.state = ACPI_STATE_D3; 481 *state = ACPI_STATE_D3;
457
458 return 0; 482 return 0;
459} 483}
460 484
461int acpi_power_transition(struct acpi_device *device, int state) 485int acpi_power_on_resources(struct acpi_device *device, int state)
462{ 486{
463 int result = 0; 487 if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3)
464 struct acpi_handle_list *cl = NULL; /* Current Resources */ 488 return -EINVAL;
465 struct acpi_handle_list *tl = NULL; /* Target Resources */
466 int i = 0;
467 489
490 return acpi_power_on_list(&device->power.states[state].resources);
491}
492
493int acpi_power_transition(struct acpi_device *device, int state)
494{
495 int result;
468 496
469 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) 497 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
470 return -EINVAL; 498 return -EINVAL;
471 499
500 if (device->power.state == state)
501 return 0;
502
472 if ((device->power.state < ACPI_STATE_D0) 503 if ((device->power.state < ACPI_STATE_D0)
473 || (device->power.state > ACPI_STATE_D3)) 504 || (device->power.state > ACPI_STATE_D3))
474 return -ENODEV; 505 return -ENODEV;
475 506
476 cl = &device->power.states[device->power.state].resources;
477 tl = &device->power.states[state].resources;
478
479 /* TBD: Resources must be ordered. */ 507 /* TBD: Resources must be ordered. */
480 508
481 /* 509 /*
482 * First we reference all power resources required in the target list 510 * First we reference all power resources required in the target list
483 * (e.g. so the device doesn't lose power while transitioning). 511 * (e.g. so the device doesn't lose power while transitioning). Then,
512 * we dereference all power resources used in the current list.
484 */ 513 */
485 for (i = 0; i < tl->count; i++) { 514 result = acpi_power_on_list(&device->power.states[state].resources);
486 result = acpi_power_on(tl->handles[i]); 515 if (!result)
487 if (result) 516 acpi_power_off_list(
488 goto end; 517 &device->power.states[device->power.state].resources);
489 }
490
491 if (device->power.state == state) {
492 goto end;
493 }
494
495 /*
496 * Then we dereference all power resources used in the current list.
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 518
504 end: 519 /* We shouldn't change the state unless the above operations succeed. */
505 if (result) 520 device->power.state = result ? ACPI_STATE_UNKNOWN : state;
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 521
512 return result; 522 return result;
513} 523}