aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-10-16 17:34:36 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-10-21 18:19:29 -0400
commit4ca46ff3e0d8c234cb40ebb6457653b59584426c (patch)
treeb929bbc30d5e08b1ba4be980c473f9d594a42b58 /drivers/base/power
parentcd0ea672f58d5cfdea271c45cec0c897f2b792aa (diff)
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/power')
-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 22fe029ca212..6790cf7eba5a 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)
714 if (ret) 714 if (ret)
715 return ret; 715 return ret;
716 716
717 if (device_may_wakeup(dev) 717 if (dev->power.wakeup_path
718 && genpd->active_wakeup && genpd->active_wakeup(dev)) 718 && genpd->active_wakeup && genpd->active_wakeup(dev))
719 return 0; 719 return 0;
720 720
@@ -938,7 +938,7 @@ static int pm_genpd_dev_poweroff_noirq(struct device *dev)
938 if (ret) 938 if (ret)
939 return ret; 939 return ret;
940 940
941 if (device_may_wakeup(dev) 941 if (dev->power.wakeup_path
942 && genpd->active_wakeup && genpd->active_wakeup(dev)) 942 && genpd->active_wakeup && genpd->active_wakeup(dev))
943 return 0; 943 return 0;
944 944
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index a85459126bc6..1e15732c12c4 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)
902 } 902 }
903 903
904 End: 904 End:
905 dev->power.is_suspended = !error; 905 if (!error) {
906 dev->power.is_suspended = true;
907 if (dev->power.wakeup_path && dev->parent)
908 dev->parent->power.wakeup_path = true;
909 }
906 910
907 device_unlock(dev); 911 device_unlock(dev);
908 complete_all(&dev->power.completion); 912 complete_all(&dev->power.completion);
@@ -999,6 +1003,8 @@ static int device_prepare(struct device *dev, pm_message_t state)
999 1003
1000 device_lock(dev); 1004 device_lock(dev);
1001 1005
1006 dev->power.wakeup_path = device_may_wakeup(dev);
1007
1002 if (dev->pm_domain) { 1008 if (dev->pm_domain) {
1003 pm_dev_dbg(dev, state, "preparing power domain "); 1009 pm_dev_dbg(dev, state, "preparing power domain ");
1004 if (dev->pm_domain->ops.prepare) 1010 if (dev->pm_domain->ops.prepare)