summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-10-16 21:34:36 (GMT)
committerRafael J. Wysocki <rjw@sisk.pl>2011-10-21 22:19:29 (GMT)
commit4ca46ff3e0d8c234cb40ebb6457653b59584426c (patch)
treeb929bbc30d5e08b1ba4be980c473f9d594a42b58 /drivers/base
parentcd0ea672f58d5cfdea271c45cec0c897f2b792aa (diff)
downloadlinux-4ca46ff3e0d8c234cb40ebb6457653b59584426c.tar.xz
PM / Sleep: Mark devices involved in wakeup signaling during suspend
The generic PM domains code in drivers/base/power/domain.c has to avoid powering off domains that provide power to wakeup devices during system suspend. Currently, however, this only works for wakeup devices directly belonging to the given domain and not for their children (or the children of their children and so on). Thus, if there's a wakeup device whose parent belongs to a power domain handled by the generic PM domains code, the domain will be powered off during system suspend preventing the device from signaling wakeup. To address this problem introduce a device flag, power.wakeup_path, that will be set during system suspend for all wakeup devices, their parents, the parents of their parents and so on. This way, all wakeup paths in the device hierarchy will be marked and the generic PM domains code will only need to avoid powering off domains containing devices whose power.wakeup_path is set. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/domain.c4
-rw-r--r--drivers/base/power/main.c8
2 files changed, 9 insertions, 3 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 22fe029..6790cf7 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -714,7 +714,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
if (ret)
return ret;
- if (device_may_wakeup(dev)
+ if (dev->power.wakeup_path
&& genpd->active_wakeup && genpd->active_wakeup(dev))
return 0;
@@ -938,7 +938,7 @@ static int pm_genpd_dev_poweroff_noirq(struct device *dev)
if (ret)
return ret;
- if (device_may_wakeup(dev)
+ if (dev->power.wakeup_path
&& genpd->active_wakeup && genpd->active_wakeup(dev))
return 0;
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index a854591..1e15732 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -902,7 +902,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
}
End:
- dev->power.is_suspended = !error;
+ if (!error) {
+ dev->power.is_suspended = true;
+ if (dev->power.wakeup_path && dev->parent)
+ dev->parent->power.wakeup_path = true;
+ }
device_unlock(dev);
complete_all(&dev->power.completion);
@@ -999,6 +1003,8 @@ static int device_prepare(struct device *dev, pm_message_t state)
device_lock(dev);
+ dev->power.wakeup_path = device_may_wakeup(dev);
+
if (dev->pm_domain) {
pm_dev_dbg(dev, state, "preparing power domain ");
if (dev->pm_domain->ops.prepare)