summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-09-19 15:59:02 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-19 15:59:02 -0400
commit88d26136a256576e444db312179e17af6dd0ea87 (patch)
tree21bd82f6880a91708549512fdb42bc4c79b4ea98 /drivers/base
parent997a031107ec962967ce36db9bc500f1fad491c1 (diff)
PM: Prevent runtime suspend during system resume
This patch (as1591) moves the pm_runtime_get_noresume() and pm_runtime_put_sync() calls from __device_suspend() and device_resume() to device_prepare() and device_complete() in the PM core. The reason for doing this is to make sure that parent devices remain at full power (i.e., don't go into runtime suspend) while their children are being resumed from a system sleep. The PCI core already contained equivalent code to serve the same purpose. The patch removes the duplicated code, since it is no longer needed. One of the comments from the PCI core gets moved into the PM core, and a second comment is added to explain whe the _get_noresume and _put_sync calls are present. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 2700f2e4066f..077b9756fd8f 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -565,7 +565,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
565 pm_callback_t callback = NULL; 565 pm_callback_t callback = NULL;
566 char *info = NULL; 566 char *info = NULL;
567 int error = 0; 567 int error = 0;
568 bool put = false;
569 568
570 TRACE_DEVICE(dev); 569 TRACE_DEVICE(dev);
571 TRACE_RESUME(0); 570 TRACE_RESUME(0);
@@ -583,7 +582,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
583 goto Unlock; 582 goto Unlock;
584 583
585 pm_runtime_enable(dev); 584 pm_runtime_enable(dev);
586 put = true;
587 585
588 if (dev->pm_domain) { 586 if (dev->pm_domain) {
589 info = "power domain "; 587 info = "power domain ";
@@ -636,9 +634,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
636 634
637 TRACE_RESUME(error); 635 TRACE_RESUME(error);
638 636
639 if (put)
640 pm_runtime_put_sync(dev);
641
642 return error; 637 return error;
643} 638}
644 639
@@ -749,6 +744,8 @@ static void device_complete(struct device *dev, pm_message_t state)
749 } 744 }
750 745
751 device_unlock(dev); 746 device_unlock(dev);
747
748 pm_runtime_put_sync(dev);
752} 749}
753 750
754/** 751/**
@@ -1043,12 +1040,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
1043 if (async_error) 1040 if (async_error)
1044 goto Complete; 1041 goto Complete;
1045 1042
1046 pm_runtime_get_noresume(dev); 1043 /*
1044 * If a device configured to wake up the system from sleep states
1045 * has been suspended at run time and there's a resume request pending
1046 * for it, this is equivalent to the device signaling wakeup, so the
1047 * system suspend operation should be aborted.
1048 */
1047 if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) 1049 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1048 pm_wakeup_event(dev, 0); 1050 pm_wakeup_event(dev, 0);
1049 1051
1050 if (pm_wakeup_pending()) { 1052 if (pm_wakeup_pending()) {
1051 pm_runtime_put_sync(dev);
1052 async_error = -EBUSY; 1053 async_error = -EBUSY;
1053 goto Complete; 1054 goto Complete;
1054 } 1055 }
@@ -1111,12 +1112,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
1111 Complete: 1112 Complete:
1112 complete_all(&dev->power.completion); 1113 complete_all(&dev->power.completion);
1113 1114
1114 if (error) { 1115 if (error)
1115 pm_runtime_put_sync(dev);
1116 async_error = error; 1116 async_error = error;
1117 } else if (dev->power.is_suspended) { 1117 else if (dev->power.is_suspended)
1118 __pm_runtime_disable(dev, false); 1118 __pm_runtime_disable(dev, false);
1119 }
1120 1119
1121 return error; 1120 return error;
1122} 1121}
@@ -1209,6 +1208,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
1209 char *info = NULL; 1208 char *info = NULL;
1210 int error = 0; 1209 int error = 0;
1211 1210
1211 /*
1212 * If a device's parent goes into runtime suspend at the wrong time,
1213 * it won't be possible to resume the device. To prevent this we
1214 * block runtime suspend here, during the prepare phase, and allow
1215 * it again during the complete phase.
1216 */
1217 pm_runtime_get_noresume(dev);
1218
1212 device_lock(dev); 1219 device_lock(dev);
1213 1220
1214 dev->power.wakeup_path = device_may_wakeup(dev); 1221 dev->power.wakeup_path = device_may_wakeup(dev);