static int __acpi_bus_get_power(struct acpi_device *device, int *state) { int result = ACPI_STATE_UNKNOWN; if (!device || !state) return -EINVAL; if (!device->flags.power_manageable) { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = device->parent ? device->parent->power.state : ACPI_STATE_D0; goto out; } /* * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ if (device->power.flags.explicit_get) { unsigned long long psc; acpi_status status = acpi_evaluate_integer(device->handle, "_PSC", NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; result = psc; } /* The test below covers ACPI_STATE_UNKNOWN too. */ if (result <= ACPI_STATE_D2) { ; /* Do nothing. */ } else if (device->power.flags.power_resources) { int error = acpi_power_get_inferred_state(device, &result); if (error) return error; } else if (result == ACPI_STATE_D3_HOT) { result = ACPI_STATE_D3; } /* * If we were unsure about the device parent's power state up to this * point, the fact that the device is in D0 implies that the parent has * to be in D0 too. */ if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN && result == ACPI_STATE_D0) device->parent->power.state = ACPI_STATE_D0; *state = result; out: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", device->pnp.bus_id, state_string(*state))); return 0; }
int acpi_bus_get_power ( acpi_handle handle, int *state) { int result = 0; acpi_status status = 0; struct acpi_device *device = NULL; unsigned long psc = 0; ACPI_FUNCTION_TRACE("acpi_bus_get_power"); result = acpi_bus_get_device(handle, &device); if (result) return_VALUE(result); *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 { /* * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ if (device->power.flags.explicit_get) { status = acpi_evaluate_integer(device->handle, "_PSC", NULL, &psc); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); device->power.state = (int) psc; } else if (device->power.flags.power_resources) { result = acpi_power_get_inferred_state(device); if (result) return_VALUE(result); } *state = device->power.state; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", device->pnp.bus_id, device->power.state)); return_VALUE(0); }
/* Resume the device when all power resources in _PR0 are on */ static void acpi_power_on_device(struct acpi_power_managed_device *device) { struct acpi_device *acpi_dev; acpi_handle handle = device->handle; int state; if (acpi_bus_get_device(handle, &acpi_dev)) return; if(acpi_power_get_inferred_state(acpi_dev, &state)) return; if (state == ACPI_STATE_D0 && pm_runtime_suspended(device->dev)) pm_request_resume(device->dev); }
static int __acpi_bus_get_power(struct acpi_device *device, int *state) { int result = 0; acpi_status status = 0; unsigned long long psc = 0; if (!device || !state) return -EINVAL; *state = ACPI_STATE_UNKNOWN; 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, state); if (result) return result; } else if (device->power.flags.explicit_get) { status = acpi_evaluate_integer(device->handle, "_PSC", NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; *state = (int)psc; } } 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, *state)); return 0; }
/** * acpi_device_get_power - Get power state of an ACPI device. * @device: Device to get the power state of. * @state: Place to store the power state of the device. * * This function does not update the device's power.state field, but it may * update its parent's power.state field (when the parent's power state is * unknown and the device's power state turns out to be D0). */ int acpi_device_get_power(struct acpi_device *device, int *state) { int result = ACPI_STATE_UNKNOWN; if (!device || !state) return -EINVAL; if (!device->flags.power_manageable) { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = device->parent ? device->parent->power.state : ACPI_STATE_D0; goto out; } /* * Get the device's power state from power resources settings and _PSC, * if available. */ if (device->power.flags.power_resources) { int error = acpi_power_get_inferred_state(device, &result); if (error) return error; } if (device->power.flags.explicit_get) { acpi_handle handle = device->handle; unsigned long long psc; acpi_status status; status = acpi_evaluate_integer(handle, "_PSC", NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; /* * The power resources settings may indicate a power state * shallower than the actual power state of the device. * * Moreover, on systems predating ACPI 4.0, if the device * doesn't depend on any power resources and _PSC returns 3, * that means "power off". We need to maintain compatibility * with those systems. */ if (psc > result && psc < ACPI_STATE_D3_COLD) result = psc; else if (result == ACPI_STATE_UNKNOWN) result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_COLD : psc; } /* * If we were unsure about the device parent's power state up to this * point, the fact that the device is in D0 implies that the parent has * to be in D0 too, except if ignore_parent is set. */ if (!device->power.flags.ignore_parent && device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN && result == ACPI_STATE_D0) device->parent->power.state = ACPI_STATE_D0; *state = result; out: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", device->pnp.bus_id, acpi_power_state_string(*state))); return 0; }