diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/power/domain.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7b20801d19d..b6e29ffbb70 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -482,6 +482,33 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) } /** + * resume_needed - Check whether to resume a device before system suspend. + * @dev: Device to check. + * @genpd: PM domain the device belongs to. + * + * There are two cases in which a device that can wake up the system from sleep + * states should be resumed by pm_genpd_prepare(): (1) if the device is enabled + * to wake up the system and it has to remain active for this purpose while the + * system is in the sleep state and (2) if the device is not enabled to wake up + * the system from sleep states and it generally doesn't generate wakeup signals + * by itself (those signals are generated on its behalf by other parts of the + * system). In the latter case it may be necessary to reconfigure the device's + * wakeup settings during system suspend, because it may have been set up to + * signal remote wakeup from the system's working state as needed by runtime PM. + * Return 'true' in either of the above cases. + */ +static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd) +{ + bool active_wakeup; + + if (!device_can_wakeup(dev)) + return false; + + active_wakeup = genpd->active_wakeup && genpd->active_wakeup(dev); + return device_may_wakeup(dev) ? active_wakeup : !active_wakeup; +} + +/** * pm_genpd_prepare - Start power transition of a device in a PM domain. * @dev: Device to start the transition of. * @@ -515,6 +542,9 @@ static int pm_genpd_prepare(struct device *dev) return -EBUSY; } + if (resume_needed(dev, genpd)) + pm_runtime_resume(dev); + genpd_acquire_lock(genpd); if (genpd->prepared_count++ == 0) |