Skip to content

Commit

Permalink
ACPI / PM: Expose power states of ACPI devices to user space
Browse files Browse the repository at this point in the history
Make it possible to retrieve the current power state of a device with
ACPI power management from user space via sysfs by adding two new
attributes, power_state and real_power_state, to the sysfs directory
associated with the struct acpi_device object representing the
device's ACPI node.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rafael J. Wysocki committed Jan 24, 2013
1 parent cf860be commit 836aedb
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
20 changes: 20 additions & 0 deletions Documentation/ABI/testing/sysfs-devices-power_state
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
What: /sys/devices/.../power_state
Date: January 2013
Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Description:
The /sys/devices/.../power_state attribute is only present for
device objects representing ACPI device nodes that provide power
management methods.

If present, it contains a string representing the current ACPI
power state of the given device node. Its possible values,
"D0", "D1", "D2", "D3hot", and "D3cold", reflect the power state
names defined by the ACPI specification (ACPI 4 and above).

If the device node uses shared ACPI power resources, this state
determines a list of power resources required not to be turned
off. However, some power resources needed by the device node in
higher-power (lower-number) states may also be ON because of
some other devices using them at the moment.

This attribute is read-only.
23 changes: 23 additions & 0 deletions Documentation/ABI/testing/sysfs-devices-real_power_state
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
What: /sys/devices/.../real_power_state
Date: January 2013
Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Description:
The /sys/devices/.../real_power_state attribute is only present
for device objects representing ACPI device nodes that provide
power management methods and use ACPI power resources for power
management.

If present, it contains a string representing the real ACPI
power state of the given device node as returned by the _PSC
control method or inferred from the configuration of power
resources. Its possible values, "D0", "D1", "D2", "D3hot", and
"D3cold", reflect the power state names defined by the ACPI
specification (ACPI 4 and above).

In some situations the value of this attribute may be different
from the value of the /sys/devices/.../power_state attribute for
the same device object. If that happens, some shared power
resources used by the device node are only ON because of some
other devices using them at the moment.

This attribute is read-only.
49 changes: 48 additions & 1 deletion drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,32 @@ void acpi_bus_hot_remove_device(void *context)
}
EXPORT_SYMBOL(acpi_bus_hot_remove_device);

static ssize_t real_power_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct acpi_device *adev = to_acpi_device(dev);
int state;
int ret;

ret = acpi_device_get_power(adev, &state);
if (ret)
return ret;

return sprintf(buf, "%s\n", acpi_power_state_string(state));
}

static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);

static ssize_t power_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct acpi_device *adev = to_acpi_device(dev);

return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
}

static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);

static ssize_t
acpi_eject_store(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
Expand Down Expand Up @@ -369,8 +395,22 @@ static int acpi_device_setup_files(struct acpi_device *dev)
* hot-removal function from userland.
*/
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
if (ACPI_SUCCESS(status)) {
result = device_create_file(&dev->dev, &dev_attr_eject);
if (result)
return result;
}

if (dev->flags.power_manageable) {
result = device_create_file(&dev->dev, &dev_attr_power_state);
if (result)
return result;

if (dev->power.flags.power_resources)
result = device_create_file(&dev->dev,
&dev_attr_real_power_state);
}

end:
return result;
}
Expand All @@ -380,6 +420,13 @@ static void acpi_device_remove_files(struct acpi_device *dev)
acpi_status status;
acpi_handle temp;

if (dev->flags.power_manageable) {
device_remove_file(&dev->dev, &dev_attr_power_state);
if (dev->power.flags.power_resources)
device_remove_file(&dev->dev,
&dev_attr_real_power_state);
}

/*
* If device has _STR, remove 'description' file
*/
Expand Down

0 comments on commit 836aedb

Please sign in to comment.