diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index c5356ef7e54e..fa5d98ee5902 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -475,20 +475,33 @@ End: | |||
475 | */ | 475 | */ |
476 | void dpm_resume_noirq(pm_message_t state) | 476 | void 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 | */ |
790 | int dpm_suspend_noirq(pm_message_t state) | 803 | int 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)); |