aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-11-24 18:06:09 -0500
committerLen Brown <len.brown@intel.com>2011-01-12 04:48:43 -0500
commitd2ef555b57292cd818934636ac8e3414cc2a6762 (patch)
tree6fbe86ad458f20f146dbfb22d624052c644f9ac0 /drivers/acpi/power.c
parent32a00d274e877eab3ea7ab196b75c9be5170d25e (diff)
ACPI / PM: Add functions for manipulating lists of power resources
ACPI device power resources should be reference counted during device initialization, so that their reference counters are always up to date. It is convenient to do that with the help of a function that will reference count and possibly turn on power resources in a given list, so introduce that function, acpi_power_on_list(). For symmetry, introduce acpi_power_off_list() for performing the reverse operation and use the both of them to simplify acpi_power_transition(). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 9bd1b6044b55..95fedbdf4fb8 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -266,6 +266,35 @@ static int acpi_power_off_device(acpi_handle handle)
266 return result; 266 return result;
267} 267}
268 268
269static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res)
270{
271 int i;
272
273 for (i = num_res - 1; i >= 0 ; i--)
274 acpi_power_off_device(list->handles[i]);
275}
276
277static void acpi_power_off_list(struct acpi_handle_list *list)
278{
279 __acpi_power_off_list(list, list->count);
280}
281
282static int acpi_power_on_list(struct acpi_handle_list *list)
283{
284 int result = 0;
285 int i;
286
287 for (i = 0; i < list->count; i++) {
288 result = acpi_power_on(list->handles[i]);
289 if (result) {
290 __acpi_power_off_list(list, i);
291 break;
292 }
293 }
294
295 return result;
296}
297
269/** 298/**
270 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in 299 * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
271 * ACPI 3.0) _PSW (Power State Wake) 300 * ACPI 3.0) _PSW (Power State Wake)
@@ -458,10 +487,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
458 487
459int acpi_power_transition(struct acpi_device *device, int state) 488int acpi_power_transition(struct acpi_device *device, int state)
460{ 489{
461 int result = 0; 490 int result;
462 struct acpi_handle_list *cl = NULL; /* Current Resources */
463 struct acpi_handle_list *tl = NULL; /* Target Resources */
464 int i = 0;
465 491
466 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) 492 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
467 return -EINVAL; 493 return -EINVAL;
@@ -473,37 +499,20 @@ int acpi_power_transition(struct acpi_device *device, int state)
473 || (device->power.state > ACPI_STATE_D3)) 499 || (device->power.state > ACPI_STATE_D3))
474 return -ENODEV; 500 return -ENODEV;
475 501
476 cl = &device->power.states[device->power.state].resources;
477 tl = &device->power.states[state].resources;
478
479 /* TBD: Resources must be ordered. */ 502 /* TBD: Resources must be ordered. */
480 503
481 /* 504 /*
482 * First we reference all power resources required in the target list 505 * First we reference all power resources required in the target list
483 * (e.g. so the device doesn't lose power while transitioning). 506 * (e.g. so the device doesn't lose power while transitioning). Then,
507 * we dereference all power resources used in the current list.
484 */ 508 */
485 for (i = 0; i < tl->count; i++) { 509 result = acpi_power_on_list(&device->power.states[state].resources);
486 result = acpi_power_on(tl->handles[i]); 510 if (!result)
487 if (result) 511 acpi_power_off_list(
488 goto end; 512 &device->power.states[device->power.state].resources);
489 }
490 513
491 /* 514 /* We shouldn't change the state unless the above operations succeed. */
492 * Then we dereference all power resources used in the current list. 515 device->power.state = result ? ACPI_STATE_UNKNOWN : state;
493 */
494 for (i = 0; i < cl->count; i++) {
495 result = acpi_power_off_device(cl->handles[i]);
496 if (result)
497 goto end;
498 }
499
500 end:
501 if (result)
502 device->power.state = ACPI_STATE_UNKNOWN;
503 else {
504 /* We shouldn't change the state till all above operations succeed */
505 device->power.state = state;
506 }
507 516
508 return result; 517 return result;
509} 518}