aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 17:07:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 17:07:06 -0400
commit468f4d1a855f8039dabf441b8bf68cae264033ff (patch)
tree303ac5bc1ac3f86f136a30f9356e84f20dcbf13f /drivers
parenteb2689e06b3526c7684b09beecf26070f05ee825 (diff)
parent8714c8d74d313c3ba27bf9c2aaacb1ad71c644f8 (diff)
Merge tag 'pm-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: - Implementation of opportunistic suspend (autosleep) and user space interface for manipulating wakeup sources. - Hibernate updates from Bojan Smojver and Minho Ban. - Updates of the runtime PM core and generic PM domains framework related to PM QoS. - Assorted fixes. * tag 'pm-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (25 commits) epoll: Fix user space breakage related to EPOLLWAKEUP PM / Domains: Make it possible to add devices to inactive domains PM / Hibernate: Use get_gendisk to verify partition if resume_file is integer format PM / Domains: Fix computation of maximum domain off time PM / Domains: Fix link checking when add subdomain PM / Sleep: User space wakeup sources garbage collector Kconfig option PM / Sleep: Make the limit of user space wakeup sources configurable PM / Documentation: suspend-and-cpuhotplug.txt: Fix typo PM / Domains: Cache device stop and domain power off governor results, v3 PM / Domains: Make device removal more straightforward PM / Sleep: Fix a mistake in a conditional in autosleep_store() epoll: Add a flag, EPOLLWAKEUP, to prevent suspend while epoll events are ready PM / QoS: Create device constraints objects on notifier registration PM / Runtime: Remove device fields related to suspend time, v2 PM / Domains: Rework default domain power off governor function, v2 PM / Domains: Rework default device stop governor function, v2 PM / Sleep: Add user space interface for manipulating wakeup sources, v3 PM / Sleep: Add "prevent autosleep time" statistics to wakeup sources PM / Sleep: Implement opportunistic sleep, v2 PM / Sleep: Add wakeup_source_activate and wakeup_source_deactivate tracepoints ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/power/domain.c176
-rw-r--r--drivers/base/power/domain_governor.c166
-rw-r--r--drivers/base/power/main.c10
-rw-r--r--drivers/base/power/qos.c19
-rw-r--r--drivers/base/power/runtime.c103
-rw-r--r--drivers/base/power/sysfs.c54
-rw-r--r--drivers/base/power/wakeup.c174
-rw-r--r--drivers/devfreq/governor_performance.c7
-rw-r--r--drivers/devfreq/governor_powersave.c7
9 files changed, 463 insertions, 253 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 73ce9fbe9839..83aa694a8efe 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -11,6 +11,7 @@
11#include <linux/io.h> 11#include <linux/io.h>
12#include <linux/pm_runtime.h> 12#include <linux/pm_runtime.h>
13#include <linux/pm_domain.h> 13#include <linux/pm_domain.h>
14#include <linux/pm_qos.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
15#include <linux/err.h> 16#include <linux/err.h>
16#include <linux/sched.h> 17#include <linux/sched.h>
@@ -38,11 +39,13 @@
38 ktime_t __start = ktime_get(); \ 39 ktime_t __start = ktime_get(); \
39 type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev); \ 40 type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev); \
40 s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start)); \ 41 s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start)); \
41 struct generic_pm_domain_data *__gpd_data = dev_gpd_data(dev); \ 42 struct gpd_timing_data *__td = &dev_gpd_data(dev)->td; \
42 if (__elapsed > __gpd_data->td.field) { \ 43 if (!__retval && __elapsed > __td->field) { \
43 __gpd_data->td.field = __elapsed; \ 44 __td->field = __elapsed; \
44 dev_warn(dev, name " latency exceeded, new value %lld ns\n", \ 45 dev_warn(dev, name " latency exceeded, new value %lld ns\n", \
45 __elapsed); \ 46 __elapsed); \
47 genpd->max_off_time_changed = true; \
48 __td->constraint_changed = true; \
46 } \ 49 } \
47 __retval; \ 50 __retval; \
48}) 51})
@@ -211,6 +214,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
211 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); 214 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
212 if (elapsed_ns > genpd->power_on_latency_ns) { 215 if (elapsed_ns > genpd->power_on_latency_ns) {
213 genpd->power_on_latency_ns = elapsed_ns; 216 genpd->power_on_latency_ns = elapsed_ns;
217 genpd->max_off_time_changed = true;
214 if (genpd->name) 218 if (genpd->name)
215 pr_warning("%s: Power-on latency exceeded, " 219 pr_warning("%s: Power-on latency exceeded, "
216 "new value %lld ns\n", genpd->name, 220 "new value %lld ns\n", genpd->name,
@@ -247,6 +251,53 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
247 251
248#ifdef CONFIG_PM_RUNTIME 252#ifdef CONFIG_PM_RUNTIME
249 253
254static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
255 unsigned long val, void *ptr)
256{
257 struct generic_pm_domain_data *gpd_data;
258 struct device *dev;
259
260 gpd_data = container_of(nb, struct generic_pm_domain_data, nb);
261
262 mutex_lock(&gpd_data->lock);
263 dev = gpd_data->base.dev;
264 if (!dev) {
265 mutex_unlock(&gpd_data->lock);
266 return NOTIFY_DONE;
267 }
268 mutex_unlock(&gpd_data->lock);
269
270 for (;;) {
271 struct generic_pm_domain *genpd;
272 struct pm_domain_data *pdd;
273
274 spin_lock_irq(&dev->power.lock);
275
276 pdd = dev->power.subsys_data ?
277 dev->power.subsys_data->domain_data : NULL;
278 if (pdd) {
279 to_gpd_data(pdd)->td.constraint_changed = true;
280 genpd = dev_to_genpd(dev);
281 } else {
282 genpd = ERR_PTR(-ENODATA);
283 }
284
285 spin_unlock_irq(&dev->power.lock);
286
287 if (!IS_ERR(genpd)) {
288 mutex_lock(&genpd->lock);
289 genpd->max_off_time_changed = true;
290 mutex_unlock(&genpd->lock);
291 }
292
293 dev = dev->parent;
294 if (!dev || dev->power.ignore_children)
295 break;
296 }
297
298 return NOTIFY_DONE;
299}
300
250/** 301/**
251 * __pm_genpd_save_device - Save the pre-suspend state of a device. 302 * __pm_genpd_save_device - Save the pre-suspend state of a device.
252 * @pdd: Domain data of the device to save the state of. 303 * @pdd: Domain data of the device to save the state of.
@@ -435,6 +486,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
435 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); 486 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
436 if (elapsed_ns > genpd->power_off_latency_ns) { 487 if (elapsed_ns > genpd->power_off_latency_ns) {
437 genpd->power_off_latency_ns = elapsed_ns; 488 genpd->power_off_latency_ns = elapsed_ns;
489 genpd->max_off_time_changed = true;
438 if (genpd->name) 490 if (genpd->name)
439 pr_warning("%s: Power-off latency exceeded, " 491 pr_warning("%s: Power-off latency exceeded, "
440 "new value %lld ns\n", genpd->name, 492 "new value %lld ns\n", genpd->name,
@@ -443,17 +495,6 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
443 } 495 }
444 496
445 genpd->status = GPD_STATE_POWER_OFF; 497 genpd->status = GPD_STATE_POWER_OFF;
446 genpd->power_off_time = ktime_get();
447
448 /* Update PM QoS information for devices in the domain. */
449 list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
450 struct gpd_timing_data *td = &to_gpd_data(pdd)->td;
451
452 pm_runtime_update_max_time_suspended(pdd->dev,
453 td->start_latency_ns +
454 td->restore_state_latency_ns +
455 genpd->power_on_latency_ns);
456 }
457 498
458 list_for_each_entry(link, &genpd->slave_links, slave_node) { 499 list_for_each_entry(link, &genpd->slave_links, slave_node) {
459 genpd_sd_counter_dec(link->master); 500 genpd_sd_counter_dec(link->master);
@@ -514,9 +555,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)
514 if (ret) 555 if (ret)
515 return ret; 556 return ret;
516 557
517 pm_runtime_update_max_time_suspended(dev,
518 dev_gpd_data(dev)->td.start_latency_ns);
519
520 /* 558 /*
521 * If power.irq_safe is set, this routine will be run with interrupts 559 * If power.irq_safe is set, this routine will be run with interrupts
522 * off, so it can't use mutexes. 560 * off, so it can't use mutexes.
@@ -613,6 +651,12 @@ void pm_genpd_poweroff_unused(void)
613 651
614#else 652#else
615 653
654static inline int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
655 unsigned long val, void *ptr)
656{
657 return NOTIFY_DONE;
658}
659
616static inline void genpd_power_off_work_fn(struct work_struct *work) {} 660static inline void genpd_power_off_work_fn(struct work_struct *work) {}
617 661
618#define pm_genpd_runtime_suspend NULL 662#define pm_genpd_runtime_suspend NULL
@@ -1209,12 +1253,15 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1209 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)) 1253 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
1210 return -EINVAL; 1254 return -EINVAL;
1211 1255
1212 genpd_acquire_lock(genpd); 1256