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.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 31b526661ec4..ead3e79d6fcf 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -475,20 +475,33 @@ End:
475 */ 475 */
476void dpm_resume_noirq(pm_message_t state) 476void dpm_resume_noirq(pm_message_t state)
477{ 477{
478 struct device *dev; 478 struct list_head list;
479 ktime_t starttime = ktime_get(); 479 ktime_t starttime = ktime_get();
480 480
481 INIT_LIST_HEAD(&list);
481 mutex_lock(&dpm_list_mtx); 482 mutex_lock(&dpm_list_mtx);
482 transition_started = false; 483 transition_started = false;
483 list_for_each_entry(dev, &dpm_list, power.entry) 484 while (!list_empty(&dpm_list)) {
485 struct device *dev = to_device(dpm_list.next);
486
487 get_device(dev);
484 if (dev->power.status > DPM_OFF) { 488 if (dev->power.status > DPM_OFF) {
485 int error; 489 int error;
486 490
487 dev->power.status = DPM_OFF; 491 dev->power.status = DPM_OFF;
492 mutex_unlock(&dpm_list_mtx);
493
488 error = device_resume_noirq(dev, state); 494 error = device_resume_noirq(dev, state);
495
496 mutex_lock(&dpm_list_mtx);
489 if (error) 497 if (error)
490 pm_dev_err(dev, state, " early", error); 498 pm_dev_err(dev, state, " early", error);
491 } 499 }
500 if (!list_empty(&dev->power.entry))
501 list_move_tail(&dev->power.entry, &list);
502 put_device(dev);
503 }
504 list_splice(&list, &dpm_list);
492 mutex_unlock(&dpm_list_mtx); 505 mutex_unlock(&dpm_list_mtx);
493 dpm_show_time(starttime, state, "early"); 506 dpm_show_time(starttime, state, "early");
494 resume_device_irqs(); 507 resume_device_irqs();
@@ -789,20 +802,33 @@ End:
789 */ 802 */
790int dpm_suspend_noirq(pm_message_t state) 803int dpm_suspend_noirq(pm_message_t state)
791{ 804{
792 struct device *dev; 805 struct list_head list;
793 ktime_t starttime = ktime_get(); 806 ktime_t starttime = ktime_get();
794 int error = 0; 807 int error = 0;
795 808
809 INIT_LIST_HEAD(&list);
796 suspend_device_irqs(); 810 suspend_device_irqs();
797 mutex_lock(&dpm_list_mtx); 811 mutex_lock(&dpm_list_mtx);
798 list_for_each_entry_reverse(dev, &dpm_list, power.entry) { 812 while (!list_empty(&dpm_list)) {
813 struct device *dev = to_device(dpm_list.prev);
814
815 get_device(dev);
816 mutex_unlock(&dpm_list_mtx);
817
799 error = device_suspend_noirq(dev, state); 818 error = device_suspend_noirq(dev, state);
819
820 mutex_lock(&dpm_list_mtx);
800 if (error) { 821 if (error) {
801 pm_dev_err(dev, state, " late", error); 822 pm_dev_err(dev, state, " late", error);
823 put_device(dev);
802 break; 824 break;
803 } 825 }
804 dev->power.status = DPM_OFF_IRQ; 826 dev->power.status = DPM_OFF_IRQ;
827 if (!list_empty(&dev->power.entry))
828 list_move(&dev->power.entry, &list);
829 put_device(dev);
805 } 830 }
831 list_splice_tail(&list, &dpm_list);
806 mutex_unlock(&dpm_list_mtx); 832 mutex_unlock(&dpm_list_mtx);
807 if (error) 833 if (error)
808 dpm_resume_noirq(resume_event(state)); 834 dpm_resume_noirq(resume_event(state));