diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 06f09bf89cb..a85459126bc 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -425,9 +425,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
425 | TRACE_DEVICE(dev); | 425 | TRACE_DEVICE(dev); |
426 | TRACE_RESUME(0); | 426 | TRACE_RESUME(0); |
427 | 427 | ||
428 | if (dev->pwr_domain) { | 428 | if (dev->pm_domain) { |
429 | pm_dev_dbg(dev, state, "EARLY power domain "); | 429 | pm_dev_dbg(dev, state, "EARLY power domain "); |
430 | error = pm_noirq_op(dev, &dev->pwr_domain->ops, state); | 430 | error = pm_noirq_op(dev, &dev->pm_domain->ops, state); |
431 | } else if (dev->type && dev->type->pm) { | 431 | } else if (dev->type && dev->type->pm) { |
432 | pm_dev_dbg(dev, state, "EARLY type "); | 432 | pm_dev_dbg(dev, state, "EARLY type "); |
433 | error = pm_noirq_op(dev, dev->type->pm, state); | 433 | error = pm_noirq_op(dev, dev->type->pm, state); |
@@ -505,6 +505,7 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev)) | |||
505 | static int device_resume(struct device *dev, pm_message_t state, bool async) | 505 | static int device_resume(struct device *dev, pm_message_t state, bool async) |
506 | { | 506 | { |
507 | int error = 0; | 507 | int error = 0; |
508 | bool put = false; | ||
508 | 509 | ||
509 | TRACE_DEVICE(dev); | 510 | TRACE_DEVICE(dev); |
510 | TRACE_RESUME(0); | 511 | TRACE_RESUME(0); |
@@ -521,9 +522,12 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
521 | if (!dev->power.is_suspended) | 522 | if (!dev->power.is_suspended) |
522 | goto Unlock; | 523 | goto Unlock; |
523 | 524 | ||
524 | if (dev->pwr_domain) { | 525 | pm_runtime_enable(dev); |
526 | put = true; | ||
527 | |||
528 | if (dev->pm_domain) { | ||
525 | pm_dev_dbg(dev, state, "power domain "); | 529 | pm_dev_dbg(dev, state, "power domain "); |
526 | error = pm_op(dev, &dev->pwr_domain->ops, state); | 530 | error = pm_op(dev, &dev->pm_domain->ops, state); |
527 | goto End; | 531 | goto End; |
528 | } | 532 | } |
529 | 533 | ||
@@ -563,6 +567,10 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
563 | complete_all(&dev->power.completion); | 567 | complete_all(&dev->power.completion); |
564 | 568 | ||
565 | TRACE_RESUME(error); | 569 | TRACE_RESUME(error); |
570 | |||
571 | if (put) | ||
572 | pm_runtime_put_sync(dev); | ||
573 | |||
566 | return error; | 574 | return error; |
567 | } | 575 | } |
568 | 576 | ||
@@ -641,10 +649,10 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
641 | { | 649 | { |
642 | device_lock(dev); | 650 | device_lock(dev); |
643 | 651 | ||
644 | if (dev->pwr_domain) { | 652 | if (dev->pm_domain) { |
645 | pm_dev_dbg(dev, state, "completing power domain "); | 653 | pm_dev_dbg(dev, state, "completing power domain "); |
646 | if (dev->pwr_domain->ops.complete) | 654 | if (dev->pm_domain->ops.complete) |
647 | dev->pwr_domain->ops.complete(dev); | 655 | dev->pm_domain->ops.complete(dev); |
648 | } else if (dev->type && dev->type->pm) { | 656 | } else if (dev->type && dev->type->pm) { |
649 | pm_dev_dbg(dev, state, "completing type "); | 657 | pm_dev_dbg(dev, state, "completing type "); |
650 | if (dev->type->pm->complete) | 658 | if (dev->type->pm->complete) |
@@ -744,9 +752,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) | |||
744 | { | 752 | { |
745 | int error; | 753 | int error; |
746 | 754 | ||
747 | if (dev->pwr_domain) { | 755 | if (dev->pm_domain) { |
748 | pm_dev_dbg(dev, state, "LATE power domain "); | 756 | pm_dev_dbg(dev, state, "LATE power domain "); |
749 | error = pm_noirq_op(dev, &dev->pwr_domain->ops, state); | 757 | error = pm_noirq_op(dev, &dev->pm_domain->ops, state); |
750 | if (error) | 758 | if (error) |
751 | return error; | 759 | return error; |
752 | } else if (dev->type && dev->type->pm) { | 760 | } else if (dev->type && dev->type->pm) { |
@@ -843,19 +851,25 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
843 | int error = 0; | 851 | int error = 0; |
844 | 852 | ||
845 | dpm_wait_for_children(dev, async); | 853 | dpm_wait_for_children(dev, async); |
846 | device_lock(dev); | ||
847 | 854 | ||
848 | if (async_error) | 855 | if (async_error) |
849 | goto Unlock; | 856 | return 0; |
857 | |||
858 | pm_runtime_get_noresume(dev); | ||
859 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) | ||
860 | pm_wakeup_event(dev, 0); | ||
850 | 861 | ||
851 | if (pm_wakeup_pending()) { | 862 | if (pm_wakeup_pending()) { |
863 | pm_runtime_put_sync(dev); | ||
852 | async_error = -EBUSY; | 864 | async_error = -EBUSY; |
853 | goto Unlock; | 865 | return 0; |
854 | } | 866 | } |
855 | 867 | ||
856 | if (dev->pwr_domain) { | 868 | device_lock(dev); |
869 | |||
870 | if (dev->pm_domain) { | ||
857 | pm_dev_dbg(dev, state, "power domain "); | 871 | pm_dev_dbg(dev, state, "power domain "); |
858 | error = pm_op(dev, &dev->pwr_domain->ops, state); | 872 | error = pm_op(dev, &dev->pm_domain->ops, state); |
859 | goto End; | 873 | goto End; |
860 | } | 874 | } |
861 | 875 | ||
@@ -890,12 +904,15 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
890 | End: | 904 | End: |
891 | dev->power.is_suspended = !error; | 905 | dev->power.is_suspended = !error; |
892 | 906 | ||
893 | Unlock: | ||
894 | device_unlock(dev); | 907 | device_unlock(dev); |
895 | complete_all(&dev->power.completion); | 908 | complete_all(&dev->power.completion); |
896 | 909 | ||
897 | if (error) | 910 | if (error) { |
911 | pm_runtime_put_sync(dev); | ||
898 | async_error = error; | 912 | async_error = error; |
913 | } else if (dev->power.is_suspended) { | ||
914 | __pm_runtime_disable(dev, false); | ||
915 | } | ||
899 | 916 | ||
900 | return error; | 917 | return error; |
901 | } | 918 | } |
@@ -982,11 +999,11 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
982 | 999 | ||
983 | device_lock(dev); | 1000 | device_lock(dev); |
984 | 1001 | ||
985 | if (dev->pwr_domain) { | 1002 | if (dev->pm_domain) { |
986 | pm_dev_dbg(dev, state, "preparing power domain "); | 1003 | pm_dev_dbg(dev, state, "preparing power domain "); |
987 | if (dev->pwr_domain->ops.prepare) | 1004 | if (dev->pm_domain->ops.prepare) |
988 | error = dev->pwr_domain->ops.prepare(dev); | 1005 | error = dev->pm_domain->ops.prepare(dev); |
989 | suspend_report_result(dev->pwr_domain->ops.prepare, error); | 1006 | suspend_report_result(dev->pm_domain->ops.prepare, error); |
990 | if (error) | 1007 | if (error) |
991 | goto End; | 1008 | goto End; |
992 | } else if (dev->type && dev->type->pm) { | 1009 | } else if (dev->type && dev->type->pm) { |
@@ -1035,13 +1052,7 @@ int dpm_prepare(pm_message_t state) | |||
1035 | get_device(dev); | 1052 | get_device(dev); |
1036 | mutex_unlock(&dpm_list_mtx); | 1053 | mutex_unlock(&dpm_list_mtx); |
1037 | 1054 | ||
1038 | pm_runtime_get_noresume(dev); | 1055 | error = device_prepare(dev, state); |
1039 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) | ||
1040 | pm_wakeup_event(dev, 0); | ||
1041 | |||
1042 | pm_runtime_put_sync(dev); | ||
1043 | error = pm_wakeup_pending() ? | ||
1044 | -EBUSY : device_prepare(dev, state); | ||
1045 | 1056 | ||
1046 | mutex_lock(&dpm_list_mtx); | 1057 | mutex_lock(&dpm_list_mtx); |
1047 | if (error) { | 1058 | if (error) { |