Exemple #1
0
/**
 * acpi_dev_pm_attach - Prepare device for ACPI power management.
 * @dev: Device to prepare.
 * @power_on: Whether or not to power on the device.
 *
 * If @dev has a valid ACPI handle that has a valid struct acpi_device object
 * attached to it, install a wakeup notification handler for the device and
 * add it to the general ACPI PM domain.  If @power_on is set, the device will
 * be put into the ACPI D0 state before the function returns.
 *
 * This assumes that the @dev's bus type uses generic power management callbacks
 * (or doesn't use any power management callbacks at all).
 *
 * Callers must ensure proper synchronization of this function with power
 * management callbacks.
 */
int acpi_dev_pm_attach(struct device *dev, bool power_on)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);

	if (!adev)
		return -ENODEV;

	if (dev->pm_domain)
		return -EEXIST;

	/*
	 * Only attach the power domain to the first device if the
	 * companion is shared by multiple. This is to prevent doing power
	 * management twice.
	 */
	if (!acpi_device_is_first_physical_node(adev, dev))
		return -EBUSY;

	acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
	dev_pm_domain_set(dev, &acpi_general_pm_domain);
	if (power_on) {
		acpi_dev_pm_full_power(adev);
		__acpi_device_run_wake(adev, false);
	}
	return 0;
}
Exemple #2
0
/**
 * acpi_dev_resume_early - Put device into the full-power state using ACPI.
 * @dev: Device to put into the full-power state.
 *
 * Put the given device into the full-power state using the standard ACPI
 * mechanism during system transition to the working state.  Set the power
 * state of the device to ACPI D0 and disable remote wakeup.
 */
int acpi_dev_resume_early(struct device *dev)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
	int error;

	if (!adev)
		return 0;

	error = acpi_dev_pm_full_power(adev);
	__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
	return error;
}
Exemple #3
0
/**
 * acpi_dev_runtime_resume - Put device into the full-power state using ACPI.
 * @dev: Device to put into the full-power state.
 *
 * Put the given device into the full-power state using the standard ACPI
 * mechanism at run time.  Set the power state of the device to ACPI D0 and
 * disable remote wakeup.
 */
int acpi_dev_runtime_resume(struct device *dev)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
	int error;

	if (!adev)
		return 0;

	error = acpi_dev_pm_full_power(adev);
	__acpi_device_run_wake(adev, false);
	return error;
}
Exemple #4
0
/**
 * acpi_dev_pm_attach - Prepare device for ACPI power management.
 * @dev: Device to prepare.
 * @power_on: Whether or not to power on the device.
 *
 * If @dev has a valid ACPI handle that has a valid struct acpi_device object
 * attached to it, install a wakeup notification handler for the device and
 * add it to the general ACPI PM domain.  If @power_on is set, the device will
 * be put into the ACPI D0 state before the function returns.
 *
 * This assumes that the @dev's bus type uses generic power management callbacks
 * (or doesn't use any power management callbacks at all).
 *
 * Callers must ensure proper synchronization of this function with power
 * management callbacks.
 */
int acpi_dev_pm_attach(struct device *dev, bool power_on)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);

	if (!adev)
		return -ENODEV;

	if (dev->pm_domain)
		return -EEXIST;

	acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
	dev->pm_domain = &acpi_general_pm_domain;
	if (power_on) {
		acpi_dev_pm_full_power(adev);
		__acpi_device_run_wake(adev, false);
	}
	return 0;
}
Exemple #5
0
/**
 * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI.
 * @dev: Device to put into a low-power state.
 *
 * Put the given device into a runtime low-power state using the standard ACPI
 * mechanism.  Set up remote wakeup if desired, choose the state to put the
 * device into (this checks if remote wakeup is expected to work too), and set
 * the power state of the device.
 */
int acpi_dev_runtime_suspend(struct device *dev)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
	bool remote_wakeup;
	int error;

	if (!adev)
		return 0;

	remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
				PM_QOS_FLAGS_NONE;
	error = __acpi_device_run_wake(adev, remote_wakeup);
	if (remote_wakeup && error)
		return -EAGAIN;

	error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
	if (error)
		__acpi_device_run_wake(adev, false);

	return error;
}
Exemple #6
0
/**
 * acpi_dev_pm_detach - Remove ACPI power management from the device.
 * @dev: Device to take care of.
 * @power_off: Whether or not to try to remove power from the device.
 *
 * Remove the device from the general ACPI PM domain and remove its wakeup
 * notifier.  If @power_off is set, additionally remove power from the device if
 * possible.
 *
 * Callers must ensure proper synchronization of this function with power
 * management callbacks.
 */
void acpi_dev_pm_detach(struct device *dev, bool power_off)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);

	if (adev && dev->pm_domain == &acpi_general_pm_domain) {
		dev->pm_domain = NULL;
		acpi_remove_pm_notifier(adev, acpi_wakeup_device);
		if (power_off) {
			/*
			 * If the device's PM QoS resume latency limit or flags
			 * have been exposed to user space, they have to be
			 * hidden at this point, so that they don't affect the
			 * choice of the low-power state to put the device into.
			 */
			dev_pm_qos_hide_latency_limit(dev);
			dev_pm_qos_hide_flags(dev);
			__acpi_device_run_wake(adev, false);
			acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
		}
	}
}
Exemple #7
0
/**
 * acpi_dev_suspend_late - Put device into a low-power state using ACPI.
 * @dev: Device to put into a low-power state.
 *
 * Put the given device into a low-power state during system transition to a
 * sleep state using the standard ACPI mechanism.  Set up system wakeup if
 * desired, choose the state to put the device into (this checks if system
 * wakeup is expected to work too), and set the power state of the device.
 */
int acpi_dev_suspend_late(struct device *dev)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
	u32 target_state;
	bool wakeup;
	int error;

	if (!adev)
		return 0;

	target_state = acpi_target_system_state();
	wakeup = device_may_wakeup(dev);
	error = __acpi_device_sleep_wake(adev, target_state, wakeup);
	if (wakeup && error)
		return error;

	error = acpi_dev_pm_low_power(dev, adev, target_state);
	if (error)
		__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);

	return error;
}