Commit 998d759e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Greg Kroah-Hartman

ACPI: PM: Simplify and fix PM domain hibernation callbacks

[ Upstream commit 3cd7957e ]

First, after a previous change causing all runtime-suspended devices
in the ACPI PM domain (and ACPI LPSS devices) to be resumed before
creating a snapshot image of memory during hibernation, it is not
necessary to worry about the case in which them might be left in
runtime-suspend any more, so get rid of the code related to that from
ACPI PM domain and ACPI LPSS hibernation callbacks.

Second, it is not correct to use pm_generic_resume_early() and
acpi_subsys_resume_noirq() in hibernation "restore" callbacks (which
currently happens in the ACPI PM domain and ACPI LPSS), so introduce
proper _restore_late and _restore_noirq callbacks for the ACPI PM
domain and ACPI LPSS.

Fixes: 05087360 (ACPI / PM: Take SMART_SUSPEND driver flag into account)
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent bad2aed1
...@@ -1086,16 +1086,62 @@ static int acpi_lpss_resume_noirq(struct device *dev) ...@@ -1086,16 +1086,62 @@ static int acpi_lpss_resume_noirq(struct device *dev)
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
int ret; int ret;
ret = acpi_subsys_resume_noirq(dev); /* Follow acpi_subsys_resume_noirq(). */
if (dev_pm_may_skip_resume(dev))
return 0;
if (dev_pm_smart_suspend_and_suspended(dev))
pm_runtime_set_active(dev);
ret = pm_generic_resume_noirq(dev);
if (ret) if (ret)
return ret; return ret;
if (!dev_pm_may_skip_resume(dev) && pdata->dev_desc->resume_from_noirq) if (!pdata->dev_desc->resume_from_noirq)
ret = acpi_lpss_do_resume_early(dev); return 0;
return ret; /*
* The driver's ->resume_early callback will be invoked by
* acpi_lpss_do_resume_early(), with the assumption that the driver
* really wanted to run that code in ->resume_noirq, but it could not
* run before acpi_dev_resume() and the driver expected the latter to be
* called in the "early" phase.
*/
return acpi_lpss_do_resume_early(dev);
}
static int acpi_lpss_do_restore_early(struct device *dev)
{
int ret = acpi_lpss_resume(dev);
return ret ? ret : pm_generic_restore_early(dev);
}
static int acpi_lpss_restore_early(struct device *dev)
{
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
if (pdata->dev_desc->resume_from_noirq)
return 0;
return acpi_lpss_do_restore_early(dev);
} }
static int acpi_lpss_restore_noirq(struct device *dev)
{
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
int ret;
ret = pm_generic_restore_noirq(dev);
if (ret)
return ret;
if (!pdata->dev_desc->resume_from_noirq)
return 0;
/* This is analogous to what happens in acpi_lpss_resume_noirq(). */
return acpi_lpss_do_restore_early(dev);
}
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static int acpi_lpss_runtime_suspend(struct device *dev) static int acpi_lpss_runtime_suspend(struct device *dev)
...@@ -1129,14 +1175,11 @@ static struct dev_pm_domain acpi_lpss_pm_domain = { ...@@ -1129,14 +1175,11 @@ static struct dev_pm_domain acpi_lpss_pm_domain = {
.resume_noirq = acpi_lpss_resume_noirq, .resume_noirq = acpi_lpss_resume_noirq,
.resume_early = acpi_lpss_resume_early, .resume_early = acpi_lpss_resume_early,
.freeze = acpi_subsys_freeze, .freeze = acpi_subsys_freeze,
.freeze_late = acpi_subsys_freeze_late,
.freeze_noirq = acpi_subsys_freeze_noirq,
.thaw_noirq = acpi_subsys_thaw_noirq,
.poweroff = acpi_subsys_suspend, .poweroff = acpi_subsys_suspend,
.poweroff_late = acpi_lpss_suspend_late, .poweroff_late = acpi_lpss_suspend_late,
.poweroff_noirq = acpi_lpss_suspend_noirq, .poweroff_noirq = acpi_lpss_suspend_noirq,
.restore_noirq = acpi_lpss_resume_noirq, .restore_noirq = acpi_lpss_restore_noirq,
.restore_early = acpi_lpss_resume_early, .restore_early = acpi_lpss_restore_early,
#endif #endif
.runtime_suspend = acpi_lpss_runtime_suspend, .runtime_suspend = acpi_lpss_runtime_suspend,
.runtime_resume = acpi_lpss_runtime_resume, .runtime_resume = acpi_lpss_runtime_resume,
......
...@@ -1077,7 +1077,7 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq); ...@@ -1077,7 +1077,7 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq);
* acpi_subsys_resume_noirq - Run the device driver's "noirq" resume callback. * acpi_subsys_resume_noirq - Run the device driver's "noirq" resume callback.
* @dev: Device to handle. * @dev: Device to handle.
*/ */
int acpi_subsys_resume_noirq(struct device *dev) static int acpi_subsys_resume_noirq(struct device *dev)
{ {
if (dev_pm_may_skip_resume(dev)) if (dev_pm_may_skip_resume(dev))
return 0; return 0;
...@@ -1092,7 +1092,6 @@ int acpi_subsys_resume_noirq(struct device *dev) ...@@ -1092,7 +1092,6 @@ int acpi_subsys_resume_noirq(struct device *dev)
return pm_generic_resume_noirq(dev); return pm_generic_resume_noirq(dev);
} }
EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq);
/** /**
* acpi_subsys_resume_early - Resume device using ACPI. * acpi_subsys_resume_early - Resume device using ACPI.
...@@ -1102,12 +1101,11 @@ EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq); ...@@ -1102,12 +1101,11 @@ EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq);
* generic early resume procedure for it during system transition into the * generic early resume procedure for it during system transition into the
* working state. * working state.
*/ */
int acpi_subsys_resume_early(struct device *dev) static int acpi_subsys_resume_early(struct device *dev)
{ {
int ret = acpi_dev_resume(dev); int ret = acpi_dev_resume(dev);
return ret ? ret : pm_generic_resume_early(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. * acpi_subsys_freeze - Run the device driver's freeze callback.
...@@ -1130,52 +1128,15 @@ int acpi_subsys_freeze(struct device *dev) ...@@ -1130,52 +1128,15 @@ int acpi_subsys_freeze(struct device *dev)
EXPORT_SYMBOL_GPL(acpi_subsys_freeze); EXPORT_SYMBOL_GPL(acpi_subsys_freeze);
/** /**
* acpi_subsys_freeze_late - Run the device driver's "late" freeze callback. * acpi_subsys_restore_early - Restore device using ACPI.
* @dev: Device to handle. * @dev: Device to restore.
*/
int acpi_subsys_freeze_late(struct device *dev)
{
if (dev_pm_smart_suspend_and_suspended(dev))
return 0;
return pm_generic_freeze_late(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_freeze_late);
/**
* acpi_subsys_freeze_noirq - Run the device driver's "noirq" freeze callback.
* @dev: Device to handle.
*/
int acpi_subsys_freeze_noirq(struct device *dev)
{
if (dev_pm_smart_suspend_and_suspended(dev))
return 0;
return pm_generic_freeze_noirq(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_freeze_noirq);
/**
* acpi_subsys_thaw_noirq - Run the device driver's "noirq" thaw callback.
* @dev: Device to handle.
*/ */
int acpi_subsys_thaw_noirq(struct device *dev) int acpi_subsys_restore_early(struct device *dev)
{ {
/* int ret = acpi_dev_resume(dev);
* If the device is in runtime suspend, the "thaw" code may not work return ret ? ret : pm_generic_restore_early(dev);
* correctly with it, so skip the driver callback and make the PM core
* skip all of the subsequent "thaw" callbacks for the device.
*/
if (dev_pm_smart_suspend_and_suspended(dev)) {
dev_pm_skip_next_resume_phases(dev);
return 0;
}
return pm_generic_thaw_noirq(dev);
} }
EXPORT_SYMBOL_GPL(acpi_subsys_thaw_noirq); EXPORT_SYMBOL_GPL(acpi_subsys_restore_early);
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static struct dev_pm_domain acpi_general_pm_domain = { static struct dev_pm_domain acpi_general_pm_domain = {
...@@ -1191,14 +1152,10 @@ static struct dev_pm_domain acpi_general_pm_domain = { ...@@ -1191,14 +1152,10 @@ static struct dev_pm_domain acpi_general_pm_domain = {
.resume_noirq = acpi_subsys_resume_noirq, .resume_noirq = acpi_subsys_resume_noirq,
.resume_early = acpi_subsys_resume_early, .resume_early = acpi_subsys_resume_early,
.freeze = acpi_subsys_freeze, .freeze = acpi_subsys_freeze,
.freeze_late = acpi_subsys_freeze_late,
.freeze_noirq = acpi_subsys_freeze_noirq,
.thaw_noirq = acpi_subsys_thaw_noirq,
.poweroff = acpi_subsys_suspend, .poweroff = acpi_subsys_suspend,
.poweroff_late = acpi_subsys_suspend_late, .poweroff_late = acpi_subsys_suspend_late,
.poweroff_noirq = acpi_subsys_suspend_noirq, .poweroff_noirq = acpi_subsys_suspend_noirq,
.restore_noirq = acpi_subsys_resume_noirq, .restore_early = acpi_subsys_restore_early,
.restore_early = acpi_subsys_resume_early,
#endif #endif
}, },
}; };
......
...@@ -917,26 +917,16 @@ int acpi_subsys_prepare(struct device *dev); ...@@ -917,26 +917,16 @@ int acpi_subsys_prepare(struct device *dev);
void acpi_subsys_complete(struct device *dev); void acpi_subsys_complete(struct device *dev);
int acpi_subsys_suspend_late(struct device *dev); int acpi_subsys_suspend_late(struct device *dev);
int acpi_subsys_suspend_noirq(struct device *dev); int acpi_subsys_suspend_noirq(struct device *dev);
int acpi_subsys_resume_noirq(struct device *dev);
int acpi_subsys_resume_early(struct device *dev);
int acpi_subsys_suspend(struct device *dev); int acpi_subsys_suspend(struct device *dev);
int acpi_subsys_freeze(struct device *dev); int acpi_subsys_freeze(struct device *dev);
int acpi_subsys_freeze_late(struct device *dev);
int acpi_subsys_freeze_noirq(struct device *dev);
int acpi_subsys_thaw_noirq(struct device *dev);
#else #else
static inline int acpi_dev_resume_early(struct device *dev) { return 0; } static inline int acpi_dev_resume_early(struct device *dev) { return 0; }
static inline int acpi_subsys_prepare(struct device *dev) { return 0; } static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
static inline void acpi_subsys_complete(struct device *dev) {} static inline void acpi_subsys_complete(struct device *dev) {}
static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; } static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }
static inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; } static inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; }
static inline int acpi_subsys_resume_noirq(struct device *dev) { return 0; }
static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
static inline int acpi_subsys_suspend(struct device *dev) { return 0; } static inline int acpi_subsys_suspend(struct device *dev) { return 0; }
static inline int acpi_subsys_freeze(struct device *dev) { return 0; } static inline int acpi_subsys_freeze(struct device *dev) { return 0; }
static inline int acpi_subsys_freeze_late(struct device *dev) { return 0; }
static inline int acpi_subsys_freeze_noirq(struct device *dev) { return 0; }
static inline int acpi_subsys_thaw_noirq(struct device *dev) { return 0; }
#endif #endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment