| From cac6f0b0d91888b756691c97ac1bb4deca217f24 Mon Sep 17 00:00:00 2001 |
| From: "Rafael J. Wysocki" <rjw@sisk.pl> |
| Date: Tue, 12 Jul 2011 00:39:57 +0200 |
| Subject: PM / Domains: Improve handling of wakeup devices during system |
| suspend |
| |
| Kevin points out that if there's a device that can wake up the system |
| from sleep states, but it doesn't generate wakeup signals by itself |
| (they are generated on its behalf by other parts of the system) and |
| it currently is not enabled to wake up the system (that is, |
| device_may_wakeup() returns "false" for it), we may need to change |
| its wakeup settings during system suspend (for example, the device |
| might have been configured to signal remote wakeup from the system's |
| working state, as needed by runtime PM). Therefore the generic PM |
| domains code should invoke the system suspend callbacks provided by |
| the device's driver, which it doesn't do if the PM domain is powered |
| off during the system suspend's "prepare" stage. This is a valid |
| point. Moreover, this code also should make sure that system wakeup |
| devices that are enabled to wake up the system from sleep states and |
| have to remain active for this purpose are not suspended while the |
| system is in a sleep state. |
| |
| To avoid the above issues, make the generic PM domains' .prepare() |
| routine, pm_genpd_prepare(), force runtime resume of devices whose |
| system wakeup settings may need to be changed during system suspend |
| or that should remain active while the system is in a sleep state to |
| be able to wake it up from that state. |
| |
| Reported-by: Kevin Hilman <khilman@ti.com> |
| Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> |
| (cherry picked from commit 4ecd6e651dd25ebbf0cc53c68162c0ab08641725) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| drivers/base/power/domain.c | 30 ++++++++++++++++++++++++++++++ |
| 1 file changed, 30 insertions(+) |
| |
| diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c |
| index 7b20801..b6e29ff 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) |
| -- |
| 1.7.10.1.362.g242cab3 |
| |