ACPI: PM: Simplify and fix PM domain hibernation callbacks
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: 05087360fd
(ACPI / PM: Take SMART_SUSPEND driver flag into account)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
a78ae45a79
commit
3cd7957e85
|
@ -1094,16 +1094,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)
|
||||||
|
@ -1137,14 +1183,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,
|
||||||
|
|
|
@ -1073,7 +1073,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;
|
||||||
|
@ -1088,7 +1088,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.
|
||||||
|
@ -1098,12 +1097,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.
|
||||||
|
@ -1126,52 +1124,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)
|
int acpi_subsys_restore_early(struct device *dev)
|
||||||
{
|
{
|
||||||
|
int ret = acpi_dev_resume(dev);
|
||||||
if (dev_pm_smart_suspend_and_suspended(dev))
|
return ret ? ret : pm_generic_restore_early(dev);
|
||||||
return 0;
|
|
||||||
|
|
||||||
return pm_generic_freeze_late(dev);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(acpi_subsys_freeze_late);
|
EXPORT_SYMBOL_GPL(acpi_subsys_restore_early);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If the device is in runtime suspend, the "thaw" code may not work
|
|
||||||
* 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);
|
|
||||||
#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 = {
|
||||||
|
@ -1187,14 +1148,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
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -918,26 +918,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
|
||||||
|
|
Loading…
Reference in New Issue