]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
ACPI / PM: Expose current status of ACPI power resources
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 24 Jan 2013 11:50:09 +0000 (12:50 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 24 Jan 2013 11:50:09 +0000 (12:50 +0100)
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>
Documentation/ABI/testing/sysfs-devices-resource_in_use [new file with mode: 0644]
drivers/acpi/power.c
drivers/acpi/scan.c
include/acpi/acpi_bus.h

diff --git a/Documentation/ABI/testing/sysfs-devices-resource_in_use b/Documentation/ABI/testing/sysfs-devices-resource_in_use
new file mode 100644 (file)
index 0000000..b4a3bc5
--- /dev/null
@@ -0,0 +1,12 @@
+What:          /sys/devices/.../resource_in_use
+Date:          January 2013
+Contact:       Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+               The /sys/devices/.../resource_in_use attribute is only present
+               for device objects representing ACPI power resources.
+
+               If present, it contains a number (0 or 1) representing the
+               current status of the given power resource (0 means that the
+               resource is not in use and therefore it has been turned off).
+
+               This attribute is read-only.
index 3f16dd4db23e82275cf9129255e931d3081736f4..946720a4db57d7c4b745f6a5a148ba9da29d77c4 100644 (file)
@@ -87,6 +87,12 @@ static DEFINE_MUTEX(power_resource_list_lock);
                              Power Resource Management
    -------------------------------------------------------------------------- */
 
+static inline
+struct acpi_power_resource *to_power_resource(struct acpi_device *device)
+{
+       return container_of(device, struct acpi_power_resource, device);
+}
+
 static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
 {
        struct acpi_device *device;
@@ -94,7 +100,7 @@ static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
        if (acpi_bus_get_device(handle, &device))
                return NULL;
 
-       return container_of(device, struct acpi_power_resource, device);
+       return to_power_resource(device);
 }
 
 static int acpi_power_resources_list_add(acpi_handle handle,
@@ -678,6 +684,21 @@ static void acpi_release_power_resource(struct device *dev)
        kfree(resource);
 }
 
+static ssize_t acpi_power_in_use_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf) {
+       struct acpi_power_resource *resource;
+
+       resource = to_power_resource(to_acpi_device(dev));
+       return sprintf(buf, "%u\n", !!resource->ref_count);
+}
+static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);
+
+static void acpi_power_sysfs_remove(struct acpi_device *device)
+{
+       device_remove_file(&device->dev, &dev_attr_resource_in_use);
+}
+
 int acpi_add_power_resource(acpi_handle handle)
 {
        struct acpi_power_resource *resource;
@@ -725,6 +746,9 @@ int acpi_add_power_resource(acpi_handle handle)
        if (result)
                goto err;
 
+       if (!device_create_file(&device->dev, &dev_attr_resource_in_use))
+               device->remove = acpi_power_sysfs_remove;
+
        mutex_lock(&power_resource_list_lock);
        list_add(&resource->list_node, &acpi_power_resource_list);
        mutex_unlock(&power_resource_list_lock);
index 9761d589f3f5ee8de3cadf6562630add238ecaff..9801837876b7bcd2be21ee66ec859b81040c7e81 100644 (file)
@@ -791,6 +791,9 @@ static void acpi_device_unregister(struct acpi_device *device)
 
        acpi_power_add_remove_device(device, false);
        acpi_device_remove_files(device);
+       if (device->remove)
+               device->remove(device);
+
        device_del(&device->dev);
        /*
         * Drop the reference counts of all power resources the device depends
index fca1b9cb27d977347c351a9e706683d1bb39cf2c..aef56a9f4e7033fe0a6afa878771cf3f679d5d7e 100644 (file)
@@ -280,6 +280,7 @@ struct acpi_device {
        struct mutex physical_node_lock;
        DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
        struct list_head power_dependent;
+       void (*remove)(struct acpi_device *);
 };
 
 static inline void *acpi_driver_data(struct acpi_device *d)