diff options
Diffstat (limited to 'drivers/acpi/device_pm.c')
-rw-r--r-- | drivers/acpi/device_pm.c | 75 |
1 files changed, 71 insertions, 4 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index c14a00d3dca..49a51277f81 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -900,14 +900,59 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume_early); */ int acpi_subsys_prepare(struct device *dev) { + struct acpi_device *adev = ACPI_COMPANION(dev); + u32 sys_target; + int ret, state; + + ret = pm_generic_prepare(dev); + if (ret < 0) + return ret; + + if (!adev || !pm_runtime_suspended(dev) + || device_may_wakeup(dev) != !!adev->wakeup.prepare_count) + return 0; + + sys_target = acpi_target_system_state(); + if (sys_target == ACPI_STATE_S0) + return 1; + + if (adev->power.flags.dsw_present) + return 0; + + ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state); + return !ret && state == adev->power.state; +} +EXPORT_SYMBOL_GPL(acpi_subsys_prepare); + +/** + * acpi_subsys_complete - Finalize device's resume during system resume. + * @dev: Device to handle. + */ +void acpi_subsys_complete(struct device *dev) +{ /* - * Follow PCI and resume devices suspended at run time before running - * their system suspend callbacks. + * If the device had been runtime-suspended before the system went into + * the sleep state it is going out of and it has never been resumed till + * now, resume it in case the firmware powered it up. */ + if (dev->power.direct_complete) + pm_request_resume(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_complete); + +/** + * acpi_subsys_suspend - Run the device driver's suspend callback. + * @dev: Device to handle. + * + * Follow PCI and resume devices suspended at run time before running their + * system suspend callbacks. + */ +int acpi_subsys_suspend(struct device *dev) +{ pm_runtime_resume(dev); - return pm_generic_prepare(dev); + return pm_generic_suspend(dev); } -EXPORT_SYMBOL_GPL(acpi_subsys_prepare); +EXPORT_SYMBOL_GPL(acpi_subsys_suspend); /** * acpi_subsys_suspend_late - Suspend device using ACPI. @@ -937,6 +982,24 @@ int acpi_subsys_resume_early(struct device *dev) return ret ? ret : pm_generic_resume_early(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_resume_early); + +/** + * acpi_subsys_freeze - Run the device driver's freeze callback. + * @dev: Device to handle. + */ +int acpi_subsys_freeze(struct device *dev) +{ + /* + * This used to be done in acpi_subsys_prepare() for all devices and + * some drivers may depend on it, so do it here. Ideally, however, + * runtime-suspended devices should not be touched during freeze/thaw + * transitions. + */ + pm_runtime_resume(dev); + return pm_generic_freeze(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_freeze); + #endif /* CONFIG_PM_SLEEP */ static struct dev_pm_domain acpi_general_pm_domain = { @@ -947,8 +1010,12 @@ static struct dev_pm_domain acpi_general_pm_domain = { #endif #ifdef CONFIG_PM_SLEEP .prepare = acpi_subsys_prepare, + .complete = acpi_subsys_complete, + .suspend = acpi_subsys_suspend, .suspend_late = acpi_subsys_suspend_late, .resume_early = acpi_subsys_resume_early, + .freeze = acpi_subsys_freeze, + .poweroff = acpi_subsys_suspend, .poweroff_late = acpi_subsys_suspend_late, .restore_early = acpi_subsys_resume_early, #endif |