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

Commit 5e6d4fe4 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Len Brown
Browse files

ACPI / PM: Introduce __acpi_bus_get_power()



It sometimes is necessary to get the power state of an ACPI device
without updating its device->power.state field, for example to
avoid inconsistencies between device->power.state and the reference
counters of the device's power resources.  For this purpose introduce
__acpi_bus_get_power() that will return the given device's power
state via a pointer (instead of modifying device->power.state)
and make acpi_bus_get_power() use it.

Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 30d3df41
Loading
Loading
Loading
Loading
+29 −19
Original line number Diff line number Diff line
@@ -196,34 +196,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data);
                                 Power Management
   -------------------------------------------------------------------------- */

int acpi_bus_get_power(acpi_handle handle, int *state)
static int __acpi_bus_get_power(struct acpi_device *device, int *state)
{
	int result = 0;
	acpi_status status = 0;
	struct acpi_device *device = NULL;
	unsigned long long psc = 0;


	result = acpi_bus_get_device(handle, &device);
	if (result)
		return result;
	if (!device || !state)
		return -EINVAL;

	*state = ACPI_STATE_UNKNOWN;

	if (!device->flags.power_manageable) {
		/* TBD: Non-recursive algorithm for walking up hierarchy */
		if (device->parent)
			*state = device->parent->power.state;
		else
			*state = ACPI_STATE_D0;
	} else {
	if (device->flags.power_manageable) {
		/*
		 * Get the device's power state either directly (via _PSC) or
		 * indirectly (via power resources).
		 */
		if (device->power.flags.power_resources) {
			result = acpi_power_get_inferred_state(device,
							&device->power.state);
			result = acpi_power_get_inferred_state(device, state);
			if (result)
				return result;
		} else if (device->power.flags.explicit_get) {
@@ -231,20 +221,40 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
						       NULL, &psc);
			if (ACPI_FAILURE(status))
				return -ENODEV;
			device->power.state = (int)psc;
			*state = (int)psc;
		}

		*state = device->power.state;
	} else {
		/* TBD: Non-recursive algorithm for walking up hierarchy. */
		*state = device->parent ?
			device->parent->power.state : ACPI_STATE_D0;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
			  device->pnp.bus_id, device->power.state));
			  device->pnp.bus_id, *state));

	return 0;
}


int acpi_bus_get_power(acpi_handle handle, int *state)
{
	struct acpi_device *device;
	int result;

	result = acpi_bus_get_device(handle, &device);
	if (result)
		return result;

	result = __acpi_bus_get_power(device, state);
	if (result)
		return result;

	device->power.state = *state;
	return 0;
}
EXPORT_SYMBOL(acpi_bus_get_power);


int acpi_bus_set_power(acpi_handle handle, int state)
{
	int result = 0;