diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-16 18:18:17 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-16 18:18:17 -0500 |
| commit | 1e8703b2e6aefba84dd9633d90a4093ff1200b93 (patch) | |
| tree | 648c6a9ebd0ecfae1d5ef9c44e9996300b7232cd | |
| parent | 45314915ed8089634144c975357bf5ba17f06ab9 (diff) | |
| parent | 00fafcda1773245a5292f953321ec3f0668c8c28 (diff) | |
Merge branch 'pm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'pm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
PM / PM QoS: Fix reversed min and max
PM / OPP: Hide OPP configuration when SoCs do not provide an implementation
PM: Allow devices to be removed during late suspend and early resume
| -rw-r--r-- | Documentation/power/opp.txt | 3 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 34 | ||||
| -rw-r--r-- | kernel/pm_qos_params.c | 4 | ||||
| -rw-r--r-- | kernel/power/Kconfig | 4 |
4 files changed, 39 insertions, 6 deletions
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index 44d87ad3cea..cd445582d1f 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt | |||
| @@ -37,6 +37,9 @@ Typical usage of the OPP library is as follows: | |||
| 37 | SoC framework -> modifies on required cases certain OPPs -> OPP layer | 37 | SoC framework -> modifies on required cases certain OPPs -> OPP layer |
| 38 | -> queries to search/retrieve information -> | 38 | -> queries to search/retrieve information -> |
| 39 | 39 | ||
| 40 | Architectures that provide a SoC framework for OPP should select ARCH_HAS_OPP | ||
| 41 | to make the OPP layer available. | ||
| 42 | |||
| 40 | OPP layer expects each domain to be represented by a unique device pointer. SoC | 43 | OPP layer expects each domain to be represented by a unique device pointer. SoC |
| 41 | framework registers a set of initial OPPs per device with the OPP layer. This | 44 | framework registers a set of initial OPPs per device with the OPP layer. This |
| 42 | list is expected to be an optimally small number typically around 5 per device. | 45 | list is expected to be an optimally small number typically around 5 per device. |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 31b526661ec..ead3e79d6fc 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)); |
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c index c7a8f453919..aeaa7f84682 100644 --- a/kernel/pm_qos_params.c +++ b/kernel/pm_qos_params.c | |||
| @@ -121,10 +121,10 @@ static inline int pm_qos_get_value(struct pm_qos_object *o) | |||
| 121 | 121 | ||
| 122 | switch (o->type) { | 122 | switch (o->type) { |
| 123 | case PM_QOS_MIN: | 123 | case PM_QOS_MIN: |
| 124 | return plist_last(&o->requests)->prio; | 124 | return plist_first(&o->requests)->prio; |
| 125 | 125 | ||
| 126 | case PM_QOS_MAX: | 126 | case PM_QOS_MAX: |
| 127 | return plist_first(&o->requests)->prio; | 127 | return plist_last(&o->requests)->prio; |
| 128 | 128 | ||
| 129 | default: | 129 | default: |
| 130 | /* runtime check for not using enum */ | 130 | /* runtime check for not using enum */ |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 29bff6117ab..a5aff3ebad3 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
| @@ -246,9 +246,13 @@ config PM_OPS | |||
| 246 | depends on PM_SLEEP || PM_RUNTIME | 246 | depends on PM_SLEEP || PM_RUNTIME |
| 247 | default y | 247 | default y |
| 248 | 248 | ||
| 249 | config ARCH_HAS_OPP | ||
| 250 | bool | ||
| 251 | |||
| 249 | config PM_OPP | 252 | config PM_OPP |
| 250 | bool "Operating Performance Point (OPP) Layer library" | 253 | bool "Operating Performance Point (OPP) Layer library" |
| 251 | depends on PM | 254 | depends on PM |
| 255 | depends on ARCH_HAS_OPP | ||
| 252 | ---help--- | 256 | ---help--- |
| 253 | SOCs have a standard set of tuples consisting of frequency and | 257 | SOCs have a standard set of tuples consisting of frequency and |
| 254 | voltage pairs that the device will support per voltage domain. This | 258 | voltage pairs that the device will support per voltage domain. This |
