diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 17:07:06 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 17:07:06 -0400 |
| commit | 468f4d1a855f8039dabf441b8bf68cae264033ff (patch) | |
| tree | 303ac5bc1ac3f86f136a30f9356e84f20dcbf13f /drivers | |
| parent | eb2689e06b3526c7684b09beecf26070f05ee825 (diff) | |
| parent | 8714c8d74d313c3ba27bf9c2aaacb1ad71c644f8 (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.c | 176 | ||||
| -rw-r--r-- | drivers/base/power/domain_governor.c | 166 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 10 | ||||
| -rw-r--r-- | drivers/base/power/qos.c | 19 | ||||
| -rw-r--r-- | drivers/base/power/runtime.c | 103 | ||||
| -rw-r--r-- | drivers/base/power/sysfs.c | 54 | ||||
| -rw-r--r-- | drivers/base/power/wakeup.c | 174 | ||||
| -rw-r--r-- | drivers/devfreq/governor_performance.c | 7 | ||||
| -rw-r--r-- | drivers/devfreq/governor_powersave.c | 7 |
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 | ||
| 254 | static 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 | ||
| 654 | static inline int genpd_dev_pm_qos_notifier(struct notifier_block *nb, | ||
| 655 | unsigned long val, void *ptr) | ||
| 656 | { | ||
| 657 | return NOTIFY_DONE; | ||
| 658 | } | ||
| 659 | |||
| 616 | static inline void genpd_power_off_work_fn(struct work_struct *work) {} | 660 | static 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 | |
