diff options
| -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 31b526661ec4..ead3e79d6fcf 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)); |
