diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-04 14:14:36 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-04 14:14:36 -0400 |
| commit | f46e9913faeebcb6bd29edf795f12b60acbff171 (patch) | |
| tree | 1ed8871d0ebd638094d27317de1d8a53712ae15a | |
| parent | 8d91530c5fd7f0b1e8c4ddfea2905e55a178569b (diff) | |
| parent | 8d4b9d1bfef117862a2889dec4dac227068544c9 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
PM / Runtime: Add runtime PM statistics (v3)
PM / Runtime: Make runtime_status attribute not debug-only (v. 2)
PM: Do not use dynamically allocated objects in pm_wakeup_event()
PM / Suspend: Fix ordering of calls in suspend error paths
PM / Hibernate: Fix snapshot error code path
PM / Hibernate: Fix hibernation_platform_enter()
pm_qos: Get rid of the allocation in pm_qos_add_request()
pm_qos: Reimplement using plists
plist: Add plist_last
PM: Make it possible to avoid races between wakeup and system sleep
PNPACPI: Add support for remote wakeup
PM: describe kernel policy regarding wakeup defaults (v. 2)
PM / Hibernate: Fix typos in comments in kernel/power/swap.c
29 files changed, 734 insertions, 188 deletions
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power index d6a801f45b48..2875f1f74a07 100644 --- a/Documentation/ABI/testing/sysfs-power +++ b/Documentation/ABI/testing/sysfs-power | |||
| @@ -114,3 +114,18 @@ Description: | |||
| 114 | if this file contains "1", which is the default. It may be | 114 | if this file contains "1", which is the default. It may be |
| 115 | disabled by writing "0" to this file, in which case all devices | 115 | disabled by writing "0" to this file, in which case all devices |
| 116 | will be suspended and resumed synchronously. | 116 | will be suspended and resumed synchronously. |
| 117 | |||
| 118 | What: /sys/power/wakeup_count | ||
| 119 | Date: July 2010 | ||
| 120 | Contact: Rafael J. Wysocki <rjw@sisk.pl> | ||
| 121 | Description: | ||
| 122 | The /sys/power/wakeup_count file allows user space to put the | ||
| 123 | system into a sleep state while taking into account the | ||
| 124 | concurrent arrival of wakeup events. Reading from it returns | ||
| 125 | the current number of registered wakeup events and it blocks if | ||
| 126 | some wakeup events are being processed at the time the file is | ||
| 127 | read from. Writing to it will only succeed if the current | ||
| 128 | number of wakeup events is equal to the written value and, if | ||
| 129 | successful, will make the kernel abort a subsequent transition | ||
| 130 | to a sleep state if any wakeup events are reported after the | ||
| 131 | write has returned. | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 89de75325cea..cbccf9a3cee4 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | obj-$(CONFIG_PM) += sysfs.o | 1 | obj-$(CONFIG_PM) += sysfs.o |
| 2 | obj-$(CONFIG_PM_SLEEP) += main.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o |
| 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o | 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o |
| 4 | obj-$(CONFIG_PM_OPS) += generic_ops.o | 4 | obj-$(CONFIG_PM_OPS) += generic_ops.o |
| 5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o | 5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 941fcb87e52a..5419a49ff135 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -59,6 +59,7 @@ void device_pm_init(struct device *dev) | |||
| 59 | { | 59 | { |
| 60 | dev->power.status = DPM_ON; | 60 | dev->power.status = DPM_ON; |
| 61 | init_completion(&dev->power.completion); | 61 | init_completion(&dev->power.completion); |
| 62 | dev->power.wakeup_count = 0; | ||
| 62 | pm_runtime_init(dev); | 63 | pm_runtime_init(dev); |
| 63 | } | 64 | } |
| 64 | 65 | ||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index b0ec0e9f27e9..b78c401ffa73 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -123,6 +123,45 @@ int pm_runtime_idle(struct device *dev) | |||
| 123 | } | 123 | } |
| 124 | EXPORT_SYMBOL_GPL(pm_runtime_idle); | 124 | EXPORT_SYMBOL_GPL(pm_runtime_idle); |
| 125 | 125 | ||
| 126 | |||
| 127 | /** | ||
| 128 | * update_pm_runtime_accounting - Update the time accounting of power states | ||
| 129 | * @dev: Device to update the accounting for | ||
| 130 | * | ||
| 131 | * In order to be able to have time accounting of the various power states | ||
| 132 | * (as used by programs such as PowerTOP to show the effectiveness of runtime | ||
| 133 | * PM), we need to track the time spent in each state. | ||
| 134 | * update_pm_runtime_accounting must be called each time before the | ||
| 135 | * runtime_status field is updated, to account the time in the old state | ||
| 136 | * correctly. | ||
| 137 | */ | ||
| 138 | void update_pm_runtime_accounting(struct device *dev) | ||
| 139 | { | ||
| 140 | unsigned long now = jiffies; | ||
| 141 | int delta; | ||
| 142 | |||
| 143 | delta = now - dev->power.accounting_timestamp; | ||
| 144 | |||
| 145 | if (delta < 0) | ||
| 146 | delta = 0; | ||
| 147 | |||
| 148 | dev->power.accounting_timestamp = now; | ||
| 149 | |||
| 150 | if (dev->power.disable_depth > 0) | ||
| 151 | return; | ||
| 152 | |||
| 153 | if (dev->power.runtime_status == RPM_SUSPENDED) | ||
| 154 | dev->power.suspended_jiffies += delta; | ||
| 155 | else | ||
| 156 | dev->power.active_jiffies += delta; | ||
| 157 | } | ||
| 158 | |||
| 159 | static void __update_runtime_status(struct device *dev, enum rpm_status status) | ||
| 160 | { | ||
| 161 | update_pm_runtime_accounting(dev); | ||
| 162 | dev->power.runtime_status = status; | ||
| 163 | } | ||
| 164 | |||
| 126 | /** | 165 | /** |
| 127 | * __pm_runtime_suspend - Carry out run-time suspend of given device. | 166 | * __pm_runtime_suspend - Carry out run-time suspend of given device. |
| 128 | * @dev: Device to suspend. | 167 | * @dev: Device to suspend. |
| @@ -197,7 +236,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
| 197 | goto repeat; | 236 | goto repeat; |
| 198 | } | 237 | } |
| 199 | 238 | ||
| 200 | dev->power.runtime_status = RPM_SUSPENDING; | 239 | __update_runtime_status(dev, RPM_SUSPENDING); |
| 201 | dev->power.deferred_resume = false; | 240 | dev->power.deferred_resume = false; |
| 202 | 241 | ||
| 203 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { | 242 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { |
| @@ -228,7 +267,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
| 228 | } | 267 | } |
| 229 | 268 | ||
| 230 | if (retval) { | 269 | if (retval) { |
| 231 | dev->power.runtime_status = RPM_ACTIVE; | 270 | __update_runtime_status(dev, RPM_ACTIVE); |
| 232 | if (retval == -EAGAIN || retval == -EBUSY) { | 271 | if (retval == -EAGAIN || retval == -EBUSY) { |
| 233 | if (dev->power.timer_expires == 0) | 272 | if (dev->power.timer_expires == 0) |
| 234 | notify = true; | 273 | notify = true; |
| @@ -237,7 +276,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
| 237 | pm_runtime_cancel_pending(dev); | 276 | pm_runtime_cancel_pending(dev); |
| 238 | } | 277 | } |
| 239 | } else { | 278 | } else { |
| 240 | dev->power.runtime_status = RPM_SUSPENDED; | 279 | __update_runtime_status(dev, RPM_SUSPENDED); |
| 241 | pm_runtime_deactivate_timer(dev); | 280 | pm_runtime_deactivate_timer(dev); |
| 242 | 281 | ||
| 243 | if (dev->parent) { | 282 | if (dev->parent) { |
| @@ -381,7 +420,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
| 381 | goto repeat; | 420 | goto repeat; |
| 382 | } | 421 | } |
| 383 | 422 | ||
| 384 | dev->power.runtime_status = RPM_RESUMING; | 423 | __update_runtime_status(dev, RPM_RESUMING); |
| 385 | 424 | ||
| 386 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) { | 425 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) { |
| 387 | spin_unlock_irq(&dev->power.lock); | 426 | spin_unlock_irq(&dev->power.lock); |
| @@ -411,10 +450,10 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
| 411 | } | 450 | } |
| 412 | 451 | ||
| 413 | if (retval) { | 452 | if (retval) { |
| 414 | dev->power.runtime_status = RPM_SUSPENDED; | 453 | __update_runtime_status(dev, RPM_SUSPENDED); |
| 415 | pm_runtime_cancel_pending(dev); | 454 | pm_runtime_cancel_pending(dev); |
| 416 | } else { | 455 | } else { |
| 417 | dev->power.runtime_status = RPM_ACTIVE; | 456 | __update_runtime_status(dev, RPM_ACTIVE); |
| 418 | if (parent) | 457 | if (parent) |
| 419 | atomic_inc(&parent->power.child_count); | ||
