diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index aa6320207745..06f09bf89cb2 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -57,7 +57,8 @@ static int async_error; | |||
57 | */ | 57 | */ |
58 | void device_pm_init(struct device *dev) | 58 | void 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); |