Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 836aedb1 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

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: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cf860be6
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
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 −0
Original line number Diff line number Diff line
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.
+48 −1
Original line number Diff line number Diff line
@@ -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)
@@ -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;
}
@@ -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
	 */