aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/base/power/main.c29
-rw-r--r--drivers/pci/pci-driver.c17
2 files changed, 18 insertions, 28 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);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 185be3703343..51cd90bcdd4c 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -624,21 +624,6 @@ static int pci_pm_prepare(struct device *dev)
624 int error = 0; 624 int error = 0;
625 625
626 /* 626 /*
627 * If a PCI device configured to wake up the system from sleep states
628 * has been suspended at run time and there's a resume request pending
629 * for it, this is equivalent to the device signaling wakeup, so the
630 * system suspend operation should be aborted.
631 */
632 pm_runtime_get_noresume(dev);
633 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
634 pm_wakeup_event(dev, 0);
635
636 if (pm_wakeup_pending()) {
637 pm_runtime_put_sync(dev);
638 return -EBUSY;
639 }
640
641 /*
642 * PCI devices suspended at run time need to be resumed at this 627 * PCI devices suspended at run time need to be resumed at this
643 * point, because in general it is necessary to reconfigure them for 628 * point, because in general it is necessary to reconfigure them for
644 * system suspend. Namely, if the device is supposed to wake up the 629 * system suspend. Namely, if the device is supposed to wake up the
@@ -661,8 +646,6 @@ static void pci_pm_complete(struct device *dev)
661 646
662 if (drv && drv->pm && drv->pm->complete) 647 if (drv && drv->pm && drv->pm->complete)
663 drv->pm->complete(dev); 648 drv->pm->complete(dev);
664
665 pm_runtime_put_sync(dev);
666} 649}
667 650
668#else /* !CONFIG_PM_SLEEP */ 651#else /* !CONFIG_PM_SLEEP */