diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-24 06:49:59 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-24 06:49:59 -0500 |
commit | 836aedb1414d4724b2ec68dd19810960c593720c (patch) | |
tree | 4f826283e16638ba521f5d31b021d79166cfde99 | |
parent | cf860be639d86ed77af179c925085ae0721ae602 (diff) |
ACPI / PM: Expose power states of ACPI devices to user space
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>
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-power_state | 20 | ||||
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-real_power_state | 23 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 49 |
3 files changed, 91 insertions, 1 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power_state b/Documentation/ABI/testing/sysfs-devices-power_state new file mode 100644 index 000000000000..7ad9546748f0 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-power_state | |||
@@ -0,0 +1,20 @@ | |||
1 | What: /sys/devices/.../power_state | ||
2 | Date: January 2013 | ||
3 | Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
4 | Description: | ||
5 | The /sys/devices/.../power_state attribute is only present for | ||
6 | device objects representing ACPI device nodes that provide power | ||
7 | management methods. | ||
8 | |||
9 | If present, it contains a string representing the current ACPI | ||
10 | power state of the given device node. Its possible values, | ||
11 | "D0", "D1", "D2", "D3hot", and "D3cold", reflect the power state | ||
12 | names defined by the ACPI specification (ACPI 4 and above). | ||
13 | |||
14 | If the device node uses shared ACPI power resources, this state | ||
15 | determines a list of power resources required not to be turned | ||
16 | off. However, some power resources needed by the device node in | ||
17 | higher-power (lower-number) states may also be ON because of | ||
18 | some other devices using them at the moment. | ||
19 | |||
20 | This attribute is read-only. | ||
diff --git a/Documentation/ABI/testing/sysfs-devices-real_power_state b/Documentation/ABI/testing/sysfs-devices-real_power_state new file mode 100644 index 000000000000..8b3527c82a7d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-real_power_state | |||
@@ -0,0 +1,23 @@ | |||
1 | What: /sys/devices/.../real_power_state | ||
2 | Date: January 2013 | ||
3 | Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
4 | Description: | ||
5 | The /sys/devices/.../real_power_state attribute is only present | ||
6 | for device objects representing ACPI device nodes that provide | ||
7 | power management methods and use ACPI power resources for power | ||
8 | management. | ||
9 | |||
10 | If present, it contains a string representing the real ACPI | ||
11 | power state of the given device node as returned by the _PSC | ||
12 | control method or inferred from the configuration of power | ||
13 | resources. Its possible values, "D0", "D1", "D2", "D3hot", and | ||
14 | "D3cold", reflect the power state names defined by the ACPI | ||
15 | specification (ACPI 4 and above). | ||
16 | |||
17 | In some situations the value of this attribute may be different | ||
18 | from the value of the /sys/devices/.../power_state attribute for | ||
19 | the same device object. If that happens, some shared power | ||
20 | resources used by the device node are only ON because of some | ||
21 | other devices using them at the moment. | ||
22 | |||
23 | This attribute is read-only. | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8b3b18846c8c..9761d589f3f5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -178,6 +178,32 @@ err_out: | |||
178 | } | 178 | } |
179 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); | 179 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); |
180 | 180 | ||
181 | static ssize_t real_power_state_show(struct device *dev, | ||
182 | struct device_attribute *attr, char *buf) | ||
183 | { | ||
184 | struct acpi_device *adev = to_acpi_device(dev); | ||
185 | int state; | ||
186 | int ret; | ||
187 | |||
188 | ret = acpi_device_get_power(adev, &state); | ||
189 | if (ret) | ||
190 | return ret; | ||
191 | |||
192 | return sprintf(buf, "%s\n", acpi_power_state_string(state)); | ||
193 | } | ||
194 | |||
195 | static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL); | ||
196 | |||
197 | static ssize_t power_state_show(struct device *dev, | ||
198 | struct device_attribute *attr, char *buf) | ||
199 | { | ||
200 | struct acpi_device *adev = to_acpi_device(dev); | ||
201 | |||
202 | return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state)); | ||
203 | } | ||
204 | |||
205 | static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); | ||
206 | |||
181 | static ssize_t | 207 | static ssize_t |
182 | acpi_eject_store(struct device *d, struct device_attribute *attr, | 208 | acpi_eject_store(struct device *d, struct device_attribute *attr, |
183 | const char *buf, size_t count) | 209 | const char *buf, size_t count) |
@@ -369,8 +395,22 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
369 | * hot-removal function from userland. | 395 | * hot-removal function from userland. |
370 | */ | 396 | */ |
371 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); | 397 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); |
372 | if (ACPI_SUCCESS(status)) | 398 | if (ACPI_SUCCESS(status)) { |
373 | result = device_create_file(&dev->dev, &dev_attr_eject); | 399 | result = device_create_file(&dev->dev, &dev_attr_eject); |
400 | if (result) | ||
401 | return result; | ||
402 | } | ||
403 | |||
404 | if (dev->flags.power_manageable) { | ||
405 | result = device_create_file(&dev->dev, &dev_attr_power_state); | ||
406 | if (result) | ||
407 | return result; | ||
408 | |||
409 | if (dev->power.flags.power_resources) | ||
410 | result = device_create_file(&dev->dev, | ||
411 | &dev_attr_real_power_state); | ||
412 | } | ||
413 | |||
374 | end: | 414 | end: |
375 | return result; | 415 | return result; |
376 | } | 416 | } |
@@ -380,6 +420,13 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
380 | acpi_status status; | 420 | acpi_status status; |
381 | acpi_handle temp; | 421 | acpi_handle temp; |
382 | 422 | ||
423 | if (dev->flags.power_manageable) { | ||
424 | device_remove_file(&dev->dev, &dev_attr_power_state); | ||
425 | if (dev->power.flags.power_resources) | ||
426 | device_remove_file(&dev->dev, | ||
427 | &dev_attr_real_power_state); | ||
428 | } | ||
429 | |||
383 | /* | 430 | /* |
384 | * If device has _STR, remove 'description' file | 431 | * If device has _STR, remove 'description' file |
385 | */ | 432 | */ |