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 /drivers/base/power/runtime.c | |
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
Diffstat (limited to 'drivers/base/power/runtime.c')
-rw-r--r-- | drivers/base/power/runtime.c | 54 |
1 files changed, 47 insertions, 7 deletions
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); | 458 | atomic_inc(&parent->power.child_count); |
420 | } | 459 | } |
@@ -848,7 +887,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status) | |||
848 | } | 887 | } |
849 | 888 | ||
850 | out_set: | 889 | out_set: |
851 | dev->power.runtime_status = status; | 890 | __update_runtime_status(dev, status); |
852 | dev->power.runtime_error = 0; | 891 | dev->power.runtime_error = 0; |
853 | out: | 892 | out: |
854 | spin_unlock_irqrestore(&dev->power.lock, flags); | 893 | spin_unlock_irqrestore(&dev->power.lock, flags); |
@@ -1077,6 +1116,7 @@ void pm_runtime_init(struct device *dev) | |||
1077 | dev->power.request_pending = false; | 1116 | dev->power.request_pending = false; |
1078 | dev->power.request = RPM_REQ_NONE; | 1117 | dev->power.request = RPM_REQ_NONE; |
1079 | dev->power.deferred_resume = false; | 1118 | dev->power.deferred_resume = false; |
1119 | dev->power.accounting_timestamp = jiffies; | ||
1080 | INIT_WORK(&dev->power.work, pm_runtime_work); | 1120 | INIT_WORK(&dev->power.work, pm_runtime_work); |
1081 | 1121 | ||
1082 | dev->power.timer_expires = 0; | 1122 | dev->power.timer_expires = 0; |