Commit b1c0f99bfb89cd9b42e3119ab822a8102fa87909

Authored by Rafael J. Wysocki
1 parent 836aedb141

ACPI / PM: Expose current status of ACPI power resources

Since ACPI power resources are going to be used more extensively on
new hardware platforms, it becomes necessary for user space (powertop
in particular) to observe some properties of those resources for
diagnostics purposes.

For this reason, expose the current status of each ACPI power
resource to user space via sysfs by adding a new resource_in_use
attribute to the sysfs directory representing the given power
resource.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 4 changed files with 41 additions and 1 deletions Side-by-side Diff

Documentation/ABI/testing/sysfs-devices-resource_in_use
  1 +What: /sys/devices/.../resource_in_use
  2 +Date: January 2013
  3 +Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  4 +Description:
  5 + The /sys/devices/.../resource_in_use attribute is only present
  6 + for device objects representing ACPI power resources.
  7 +
  8 + If present, it contains a number (0 or 1) representing the
  9 + current status of the given power resource (0 means that the
  10 + resource is not in use and therefore it has been turned off).
  11 +
  12 + This attribute is read-only.
drivers/acpi/power.c
... ... @@ -87,6 +87,12 @@
87 87 Power Resource Management
88 88 -------------------------------------------------------------------------- */
89 89  
  90 +static inline
  91 +struct acpi_power_resource *to_power_resource(struct acpi_device *device)
  92 +{
  93 + return container_of(device, struct acpi_power_resource, device);
  94 +}
  95 +
90 96 static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
91 97 {
92 98 struct acpi_device *device;
... ... @@ -94,7 +100,7 @@
94 100 if (acpi_bus_get_device(handle, &device))
95 101 return NULL;
96 102  
97   - return container_of(device, struct acpi_power_resource, device);
  103 + return to_power_resource(device);
98 104 }
99 105  
100 106 static int acpi_power_resources_list_add(acpi_handle handle,
... ... @@ -678,6 +684,21 @@
678 684 kfree(resource);
679 685 }
680 686  
  687 +static ssize_t acpi_power_in_use_show(struct device *dev,
  688 + struct device_attribute *attr,
  689 + char *buf) {
  690 + struct acpi_power_resource *resource;
  691 +
  692 + resource = to_power_resource(to_acpi_device(dev));
  693 + return sprintf(buf, "%u\n", !!resource->ref_count);
  694 +}
  695 +static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);
  696 +
  697 +static void acpi_power_sysfs_remove(struct acpi_device *device)
  698 +{
  699 + device_remove_file(&device->dev, &dev_attr_resource_in_use);
  700 +}
  701 +
681 702 int acpi_add_power_resource(acpi_handle handle)
682 703 {
683 704 struct acpi_power_resource *resource;
... ... @@ -724,6 +745,9 @@
724 745 result = acpi_device_add(device, acpi_release_power_resource);
725 746 if (result)
726 747 goto err;
  748 +
  749 + if (!device_create_file(&device->dev, &dev_attr_resource_in_use))
  750 + device->remove = acpi_power_sysfs_remove;
727 751  
728 752 mutex_lock(&power_resource_list_lock);
729 753 list_add(&resource->list_node, &acpi_power_resource_list);
... ... @@ -791,6 +791,9 @@
791 791  
792 792 acpi_power_add_remove_device(device, false);
793 793 acpi_device_remove_files(device);
  794 + if (device->remove)
  795 + device->remove(device);
  796 +
794 797 device_del(&device->dev);
795 798 /*
796 799 * Drop the reference counts of all power resources the device depends
include/acpi/acpi_bus.h
... ... @@ -280,6 +280,7 @@
280 280 struct mutex physical_node_lock;
281 281 DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
282 282 struct list_head power_dependent;
  283 + void (*remove)(struct acpi_device *);
283 284 };
284 285  
285 286 static inline void *acpi_driver_data(struct acpi_device *d)