aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-11 16:41:48 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-11 16:41:48 -0400
commit41a2a4665d401f79912a3da83ff9ef3e502bc12e (patch)
treec1183d82f60df38205921e293a022d47d90268b2 /drivers/acpi/power.c
parent75eb2d13acca49c3c4f1c96fb04d6c9fd6013e78 (diff)
ACPI / PM: Expose lists of device wakeup power resources to user space
Commit 18a3870 (ACPI / PM: Expose lists of device power resources to user space) exposed the lists of ACPI power resources associated with power states of ACPI devices, but it didn't expose the lists of ACPI wakeup power resources, which also is necessary to get the full picture of dependencies between ACPI devices and power resources. For this reason, for every ACPI device node having a list of ACPI wakeup power resources associated with it, expose that list to user space in analogy with commit 18a3870. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 34f5ef11d427..0e3f57674fd1 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -459,57 +459,79 @@ static struct attribute_group attr_groups[] = {
459 }, 459 },
460}; 460};
461 461
462static void acpi_power_hide_list(struct acpi_device *adev, int state) 462static struct attribute_group wakeup_attr_group = {
463 .name = "power_resources_wakeup",
464 .attrs = attrs,
465};
466
467static void acpi_power_hide_list(struct acpi_device *adev,
468 struct list_head *resources,
469 struct attribute_group *attr_group)
463{ 470{
464 struct acpi_device_power_state *ps = &adev->power.states[state];
465 struct acpi_power_resource_entry *entry; 471 struct acpi_power_resource_entry *entry;
466 472
467 if (list_empty(&ps->resources)) 473 if (list_empty(resources))
468 return; 474 return;
469 475
470 list_for_each_entry_reverse(entry, &ps->resources, node) { 476 list_for_each_entry_reverse(entry, resources, node) {
471 struct acpi_device *res_dev = &entry->resource->device; 477 struct acpi_device *res_dev = &entry->resource->device;
472 478
473 sysfs_remove_link_from_group(&adev->dev.kobj, 479 sysfs_remove_link_from_group(&adev->dev.kobj,
474 attr_groups[state].name, 480 attr_group->name,
475 dev_name(&res_dev->dev)); 481 dev_name(&res_dev->dev));
476 } 482 }
477 sysfs_remove_group(&adev->dev.kobj, &attr_groups[state]); 483 sysfs_remove_group(&adev->dev.kobj, attr_group);
478} 484}
479 485
480static void acpi_power_expose_list(struct acpi_device *adev, int state) 486static void acpi_power_expose_list(struct acpi_device *adev,
487 struct list_head *resources,
488 struct attribute_group *attr_group)
481{ 489{
482 struct acpi_device_power_state *ps = &adev->power.states[state];
483 struct acpi_power_resource_entry *entry; 490 struct acpi_power_resource_entry *entry;
484 int ret; 491 int ret;
485 492
486 if (list_empty(&ps->resources)) 493 if (list_empty(resources))
487 return; 494 return;
488 495
489 ret = sysfs_create_group(&adev->dev.kobj, &attr_groups[state]); 496 ret = sysfs_create_group(&adev->dev.kobj, attr_group);
490 if (ret) 497 if (ret)
491 return; 498 return;
492 499
493 list_for_each_entry(entry, &ps->resources, node) { 500 list_for_each_entry(entry, resources, node) {
494 struct acpi_device *res_dev = &entry->resource->device; 501 struct acpi_device *res_dev = &entry->resource->device;
495 502
496 ret = sysfs_add_link_to_group(&adev->dev.kobj, 503 ret = sysfs_add_link_to_group(&adev->dev.kobj,
497 attr_groups[state].name, 504 attr_group->name,
498 &res_dev->dev.kobj, 505 &res_dev->dev.kobj,
499 dev_name(&res_dev->dev)); 506 dev_name(&res_dev->dev));
500 if (ret) { 507 if (ret) {
501 acpi_power_hide_list(adev, state); 508 acpi_power_hide_list(adev, resources, attr_group);
502 break; 509 break;
503 } 510 }
504 } 511 }
505} 512}
506 513
514static void acpi_power_expose_hide(struct acpi_device *adev,
515 struct list_head *resources,
516 struct attribute_group *attr_group,
517 bool expose)
518{
519 if (expose)
520 acpi_power_expose_list(adev, resources, attr_group);
521 else
522 acpi_power_hide_list(adev, resources, attr_group);
523}
524
507void acpi_power_add_remove_device(struct acpi_device *adev, bool add) 525void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
508{ 526{
509 struct acpi_device_power_state *ps; 527 struct acpi_device_power_state *ps;
510 struct acpi_power_resource_entry *entry; 528 struct acpi_power_resource_entry *entry;
511 int state; 529 int state;
512 530
531 if (adev->wakeup.flags.valid)
532 acpi_power_expose_hide(adev, &adev->wakeup.resources,
533 &wakeup_attr_group, add);
534
513 if (!adev->power.flags.power_resources) 535 if (!adev->power.flags.power_resources)
514 return; 536 return;
515 537
@@ -523,12 +545,10 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
523 acpi_power_remove_dependent(resource, adev); 545 acpi_power_remove_dependent(resource, adev);
524 } 546 }
525 547
526 for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) { 548 for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
527 if (add) 549 acpi_power_expose_hide(adev,
528 acpi_power_expose_list(adev, state); 550 &adev->power.states[state].resources,
529 else 551 &attr_groups[state], add);
530 acpi_power_hide_list(adev, state);
531 }
532} 552}
533 553
534int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) 554int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)