aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r--drivers/base/power/main.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index aa632020774..06f09bf89cb 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -57,7 +57,8 @@ static int async_error;
57 */ 57 */
58void device_pm_init(struct device *dev) 58void device_pm_init(struct device *dev)
59{ 59{
60 dev->power.in_suspend = false; 60 dev->power.is_prepared = false;
61 dev->power.is_suspended = false;
61 init_completion(&dev->power.completion); 62 init_completion(&dev->power.completion);
62 complete_all(&dev->power.completion); 63 complete_all(&dev->power.completion);
63 dev->power.wakeup = NULL; 64 dev->power.wakeup = NULL;
@@ -91,7 +92,7 @@ void device_pm_add(struct device *dev)
91 pr_debug("PM: Adding info for %s:%s\n", 92 pr_debug("PM: Adding info for %s:%s\n",
92 dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); 93 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
93 mutex_lock(&dpm_list_mtx); 94 mutex_lock(&dpm_list_mtx);
94 if (dev->parent && dev->parent->power.in_suspend) 95 if (dev->parent && dev->parent->power.is_prepared)
95 dev_warn(dev, "parent %s should not be sleeping\n", 96 dev_warn(dev, "parent %s should not be sleeping\n",
96 dev_name(dev->parent)); 97 dev_name(dev->parent));
97 list_add_tail(&dev->power.entry, &dpm_list); 98 list_add_tail(&dev->power.entry, &dpm_list);
@@ -511,7 +512,14 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
511 dpm_wait(dev->parent, async); 512 dpm_wait(dev->parent, async);
512 device_lock(dev); 513 device_lock(dev);
513 514
514 dev->power.in_suspend = false; 515 /*
516 * This is a fib. But we'll allow new children to be added below
517 * a resumed device, even if the device hasn't been completed yet.
518 */
519 dev->power.is_prepared = false;
520
521 if (!dev->power.is_suspended)
522 goto Unlock;
515 523
516 if (dev->pwr_domain) { 524 if (dev->pwr_domain) {
517 pm_dev_dbg(dev, state, "power domain "); 525 pm_dev_dbg(dev, state, "power domain ");
@@ -548,6 +556,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
548 } 556 }
549 557
550 End: 558 End:
559 dev->power.is_suspended = false;
560
561 Unlock:
551 device_unlock(dev); 562 device_unlock(dev);
552 complete_all(&dev->power.completion); 563 complete_all(&dev->power.completion);
553 564
@@ -670,7 +681,7 @@ void dpm_complete(pm_message_t state)
670 struct device *dev = to_device(dpm_prepared_list.prev); 681 struct device *dev = to_device(dpm_prepared_list.prev);
671 682
672 get_device(dev); 683 get_device(dev);
673 dev->power.in_suspend = false; 684 dev->power.is_prepared = false;
674 list_move(&dev->power.entry, &list); 685 list_move(&dev->power.entry, &list);
675 mutex_unlock(&dpm_list_mtx); 686 mutex_unlock(&dpm_list_mtx);
676 687
@@ -835,11 +846,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
835 device_lock(dev); 846 device_lock(dev);
836 847
837 if (async_error) 848 if (async_error)
838 goto End; 849 goto Unlock;
839 850
840 if (pm_wakeup_pending()) { 851 if (pm_wakeup_pending()) {
841 async_error = -EBUSY; 852 async_error = -EBUSY;
842 goto End; 853 goto Unlock;
843 } 854 }
844 855
845 if (dev->pwr_domain) { 856 if (dev->pwr_domain) {
@@ -877,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
877 } 888 }
878 889
879 End: 890 End:
891 dev->power.is_suspended = !error;
892
893 Unlock:
880 device_unlock(dev); 894 device_unlock(dev);
881 complete_all(&dev->power.completion); 895 complete_all(&dev->power.completion);
882 896
@@ -1042,7 +1056,7 @@ int dpm_prepare(pm_message_t state)
1042 put_device(dev); 1056 put_device(dev);
1043 break; 1057 break;
1044 } 1058 }
1045 dev->power.in_suspend = true; 1059 dev->power.is_prepared = true;
1046 if (!list_empty(&dev->power.entry)) 1060 if (!list_empty(&dev->power.entry))
1047 list_move_tail(&dev->power.entry, &dpm_prepared_list); 1061 list_move_tail(&dev->power.entry, &dpm_prepared_list);
1048 put_device(dev); 1062 put_device(dev);