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/base | |
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/base')
-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 |
7 files changed, 449 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 | gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL); |
1257 | if (!gpd_data) | ||
1258 | return -ENOMEM; | ||
1213 | 1259 | ||
1214 | if (genpd->status == GPD_STATE_POWER_OFF) { | 1260 | mutex_init(&gpd_data->lock); |
1215 | ret = -EINVAL; | 1261 | gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier; |
1216 | goto out; | 1262 | dev_pm_qos_add_notifier(dev, &gpd_data->nb); |
1217 | } | 1263 | |
1264 | genpd_acquire_lock(genpd); | ||
1218 | 1265 | ||
1219 | if (genpd->prepared_count > 0) { | 1266 | if (genpd->prepared_count > 0) { |
1220 | ret = -EAGAIN; | 1267 | ret = -EAGAIN; |
@@ -1227,26 +1274,35 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, | |||
1227 | goto out; | 1274 | goto out; |
1228 | } | 1275 | } |
1229 | 1276 | ||
1230 | gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL); | ||
1231 | if (!gpd_data) { | ||
1232 | ret = -ENOMEM; | ||
1233 | goto out; | ||
1234 | } | ||
1235 | |||
1236 | genpd->device_count++; | 1277 | genpd->device_count++; |
1278 | genpd->max_off_time_changed = true; | ||
1237 | 1279 | ||
1238 | dev->pm_domain = &genpd->domain; | ||
1239 | dev_pm_get_subsys_data(dev); | 1280 | dev_pm_get_subsys_data(dev); |
1281 | |||
1282 | mutex_lock(&gpd_data->lock); | ||
1283 | spin_lock_irq(&dev->power.lock); | ||
1284 | dev->pm_domain = &genpd->domain; | ||
1240 | dev->power.subsys_data->domain_data = &gpd_data->base; | 1285 | dev->power.subsys_data->domain_data = &gpd_data->base; |
1241 | gpd_data->base.dev = dev; | 1286 | gpd_data->base.dev = dev; |
1242 | gpd_data->need_restore = false; | ||
1243 | list_add_tail(&gpd_data->base.list_node, &genpd->dev_list); | 1287 | list_add_tail(&gpd_data->base.list_node, &genpd->dev_list); |
1288 | gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF; | ||
1244 | if (td) | 1289 | if (td) |
1245 | gpd_data->td = *td; | 1290 | gpd_data->td = *td; |
1246 | 1291 | ||
1292 | gpd_data->td.constraint_changed = true; | ||
1293 | gpd_data->td.effective_constraint_ns = -1; | ||
1294 | spin_unlock_irq(&dev->power.lock); | ||
1295 | mutex_unlock(&gpd_data->lock); | ||
1296 | |||
1297 | genpd_release_lock(genpd); | ||
1298 | |||
1299 | return 0; | ||
1300 | |||
1247 | out: | 1301 | out: |
1248 | genpd_release_lock(genpd); | 1302 | genpd_release_lock(genpd); |
1249 | 1303 | ||
1304 | dev_pm_qos_remove_notifier(dev, &gpd_data->nb); | ||
1305 | kfree(gpd_data); | ||
1250 | return ret; | 1306 | return ret; |
1251 | } | 1307 | } |
1252 | 1308 | ||
@@ -1290,12 +1346,15 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev, | |||
1290 | int pm_genpd_remove_device(struct generic_pm_domain *genpd, | 1346 | int pm_genpd_remove_device(struct generic_pm_domain *genpd, |
1291 | struct device *dev) | 1347 | struct device *dev) |
1292 | { | 1348 | { |
1349 | struct generic_pm_domain_data *gpd_data; | ||
1293 | struct pm_domain_data *pdd; | 1350 | struct pm_domain_data *pdd; |
1294 | int ret = -EINVAL; | 1351 | int ret = 0; |
1295 | 1352 | ||
1296 | dev_dbg(dev, "%s()\n", __func__); | 1353 | dev_dbg(dev, "%s()\n", __func__); |
1297 | 1354 | ||
1298 | if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)) | 1355 | if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev) |
1356 | || IS_ERR_OR_NULL(dev->pm_domain) | ||
1357 | || pd_to_genpd(dev->pm_domain) != genpd) | ||
1299 | return -EINVAL; | 1358 | return -EINVAL; |
1300 | 1359 | ||
1301 | genpd_acquire_lock(genpd); | 1360 | genpd_acquire_lock(genpd); |
@@ -1305,21 +1364,27 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, | |||
1305 | goto out; | 1364 | goto out; |
1306 | } | 1365 | } |
1307 | 1366 | ||
1308 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { | 1367 | genpd->device_count--; |
1309 | if (pdd->dev != dev) | 1368 | genpd->max_off_time_changed = true; |
1310 | continue; | ||
1311 | 1369 | ||
1312 | list_del_init(&pdd->list_node); | 1370 | spin_lock_irq(&dev->power.lock); |
1313 | pdd->dev = NULL; | 1371 | dev->pm_domain = NULL; |
1314 | dev_pm_put_subsys_data(dev); | 1372 | pdd = dev->power.subsys_data->domain_data; |
1315 | dev->pm_domain = NULL; | 1373 | list_del_init(&pdd->list_node); |
1316 | kfree(to_gpd_data(pdd)); | 1374 | dev->power.subsys_data->domain_data = NULL; |
1375 | spin_unlock_irq(&dev->power.lock); | ||
1317 | 1376 | ||
1318 | genpd->device_count--; | 1377 | gpd_data = to_gpd_data(pdd); |
1378 | mutex_lock(&gpd_data->lock); | ||
1379 | pdd->dev = NULL; | ||
1380 | mutex_unlock(&gpd_data->lock); | ||
1319 | 1381 | ||
1320 | ret = 0; | 1382 | genpd_release_lock(genpd); |
1321 | break; | 1383 | |
1322 | } | 1384 | dev_pm_qos_remove_notifier(dev, &gpd_data->nb); |
1385 | kfree(gpd_data); | ||
1386 | dev_pm_put_subsys_data(dev); | ||
1387 | return 0; | ||
1323 | 1388 | ||
1324 | out: | 1389 | out: |
1325 | genpd_release_lock(genpd); | 1390 | genpd_release_lock(genpd); |
@@ -1348,6 +1413,26 @@ void pm_genpd_dev_always_on(struct device *dev, bool val) | |||
1348 | EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on); | 1413 | EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on); |
1349 | 1414 | ||
1350 | /** | 1415 | /** |
1416 | * pm_genpd_dev_need_restore - Set/unset the device's "need restore" flag. | ||
1417 | * @dev: Device to set/unset the flag for. | ||
1418 | * @val: The new value of the device's "need restore" flag. | ||
1419 | */ | ||
1420 | void pm_genpd_dev_need_restore(struct device *dev, bool val) | ||
1421 | { | ||
1422 | struct pm_subsys_data *psd; | ||
1423 | unsigned long flags; | ||
1424 | |||
1425 | spin_lock_irqsave(&dev->power.lock, flags); | ||
1426 | |||
1427 | psd = dev_to_psd(dev); | ||
1428 | if (psd && psd->domain_data) | ||
1429 | to_gpd_data(psd->domain_data)->need_restore = val; | ||
1430 | |||
1431 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
1432 | } | ||
1433 | EXPORT_SYMBOL_GPL(pm_genpd_dev_need_restore); | ||
1434 | |||
1435 | /** | ||
1351 | * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. | 1436 | * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. |
1352 | * @genpd: Master PM domain to add the subdomain to. | 1437 | * @genpd: Master PM domain to add the subdomain to. |
1353 | * @subdomain: Subdomain to be added. | 1438 | * @subdomain: Subdomain to be added. |
@@ -1378,7 +1463,7 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, | |||
1378 | goto out; | 1463 | goto out; |
1379 | } | 1464 | } |
1380 | 1465 | ||
1381 | list_for_each_entry(link, &genpd->slave_links, slave_node) { | 1466 | list_for_each_entry(link, &genpd->master_links, master_node) { |
1382 | if (link->slave == subdomain && link->master == genpd) { | 1467 | if (link->slave == subdomain && link->master == genpd) { |
1383 | ret = -EINVAL; | 1468 | ret = -EINVAL; |
1384 | goto out; | 1469 | goto out; |
@@ -1690,6 +1775,7 @@ void pm_genpd_init(struct generic_pm_domain *genpd, | |||
1690 | genpd->resume_count = 0; | 1775 | genpd->resume_count = 0; |
1691 | genpd->device_count = 0; | 1776 | genpd->device_count = 0; |
1692 | genpd->max_off_time_ns = -1; | 1777 | genpd->max_off_time_ns = -1; |
1778 | genpd->max_off_time_changed = true; | ||
1693 | genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; | 1779 | genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; |
1694 | genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; | 1780 | genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; |
1695 | genpd->domain.ops.runtime_idle = pm_generic_runtime_idle; | 1781 | genpd->domain.ops.runtime_idle = pm_generic_runtime_idle; |
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 66a265bf5867..28dee3053f1f 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c | |||
@@ -14,6 +14,31 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_PM_RUNTIME | 15 | #ifdef CONFIG_PM_RUNTIME |
16 | 16 | ||
17 | static int dev_update_qos_constraint(struct device *dev, void *data) | ||
18 | { | ||
19 | s64 *constraint_ns_p = data; | ||
20 | s32 constraint_ns = -1; | ||
21 | |||
22 | if (dev->power.subsys_data && dev->power.subsys_data->domain_data) | ||
23 | constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns; | ||
24 | |||
25 | if (constraint_ns < 0) { | ||
26 | constraint_ns = dev_pm_qos_read_value(dev); | ||
27 | constraint_ns *= NSEC_PER_USEC; | ||
28 | } | ||
29 | if (constraint_ns == 0) | ||
30 | return 0; | ||
31 | |||
32 | /* | ||
33 | * constraint_ns cannot be negative here, because the device has been | ||
34 | * suspended. | ||
35 | */ | ||
36 | if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0) | ||
37 | *constraint_ns_p = constraint_ns; | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
17 | /** | 42 | /** |
18 | * default_stop_ok - Default PM domain governor routine for stopping devices. | 43 | * default_stop_ok - Default PM domain governor routine for stopping devices. |
19 | * @dev: Device to check. | 44 | * @dev: Device to check. |
@@ -21,14 +46,52 @@ | |||
21 | bool default_stop_ok(struct device *dev) | 46 | bool default_stop_ok(struct device *dev) |
22 | { | 47 | { |
23 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; | 48 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; |
49 | unsigned long flags; | ||
50 | s64 constraint_ns; | ||
24 | 51 | ||
25 | dev_dbg(dev, "%s()\n", __func__); | 52 | dev_dbg(dev, "%s()\n", __func__); |
26 | 53 | ||
27 | if (dev->power.max_time_suspended_ns < 0 || td->break_even_ns == 0) | 54 | spin_lock_irqsave(&dev->power.lock, flags); |
28 | return true; | 55 | |
56 | if (!td->constraint_changed) { | ||
57 | bool ret = td->cached_stop_ok; | ||
29 | 58 | ||
30 | return td->stop_latency_ns + td->start_latency_ns < td->break_even_ns | 59 | spin_unlock_irqrestore(&dev->power.lock, flags); |
31 | && td->break_even_ns < dev->power.max_time_suspended_ns; | 60 | return ret; |
61 | } | ||
62 | td->constraint_changed = false; | ||
63 | td->cached_stop_ok = false; | ||
64 | td->effective_constraint_ns = -1; | ||
65 | constraint_ns = __dev_pm_qos_read_value(dev); | ||
66 | |||
67 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
68 | |||
69 | if (constraint_ns < 0) | ||
70 | return false; | ||
71 | |||
72 | constraint_ns *= NSEC_PER_USEC; | ||
73 | /* | ||
74 | * We can walk the children without any additional locking, because | ||
75 | * they all have been suspended at this point and their | ||
76 | * effective_constraint_ns fields won't be modified in parallel with us. | ||
77 | */ | ||
78 | if (!dev->power.ignore_children) | ||
79 | device_for_each_child(dev, &constraint_ns, | ||
80 | dev_update_qos_constraint); | ||
81 | |||
82 | if (constraint_ns > 0) { | ||
83 | constraint_ns -= td->start_latency_ns; | ||
84 | if (constraint_ns == 0) | ||
85 | return false; | ||
86 | } | ||
87 | td->effective_constraint_ns = constraint_ns; | ||
88 | td->cached_stop_ok = constraint_ns > td->stop_latency_ns || | ||
89 | constraint_ns == 0; | ||
90 | /* | ||
91 | * The children have been suspended already, so we don't need to take | ||
92 | * their stop latencies into account here. | ||
93 | */ | ||
94 | return td->cached_stop_ok; | ||
32 | } | 95 | } |
33 | 96 | ||
34 | /** | 97 | /** |
@@ -42,9 +105,27 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
42 | struct generic_pm_domain *genpd = pd_to_genpd(pd); | 105 | struct generic_pm_domain *genpd = pd_to_genpd(pd); |
43 | struct gpd_link *link; | 106 | struct gpd_link *link; |
44 | struct pm_domain_data *pdd; | 107 | struct pm_domain_data *pdd; |
45 | s64 min_dev_off_time_ns; | 108 | s64 min_off_time_ns; |
46 | s64 off_on_time_ns; | 109 | s64 off_on_time_ns; |
47 | ktime_t time_now = ktime_get(); | 110 | |
111 | if (genpd->max_off_time_changed) { | ||
112 | struct gpd_link *link; | ||
113 | |||
114 | /* | ||
115 | * We have to invalidate the cached results for the masters, so | ||
116 | * use the observation that default_power_down_ok() is not | ||
117 | * going to be called for any master until this instance | ||
118 | * returns. | ||
119 | */ | ||
120 | list_for_each_entry(link, &genpd->slave_links, slave_node) | ||
121 | link->master->max_off_time_changed = true; | ||
122 | |||
123 | genpd->max_off_time_changed = false; | ||
124 | genpd->cached_power_down_ok = false; | ||
125 | genpd->max_off_time_ns = -1; | ||
126 | } else { | ||
127 | return genpd->cached_power_down_ok; | ||
128 | } | ||
48 | 129 | ||
49 | off_on_time_ns = genpd->power_off_latency_ns + | 130 | off_on_time_ns = genpd->power_off_latency_ns + |
50 | genpd->power_on_latency_ns; | 131 | genpd->power_on_latency_ns; |
@@ -61,6 +142,7 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
61 | to_gpd_data(pdd)->td.save_state_latency_ns; | 142 | to_gpd_data(pdd)->td.save_state_latency_ns; |
62 | } | 143 | } |
63 | 144 | ||
145 | min_off_time_ns = -1; | ||
64 | /* | 146 | /* |
65 | * Check if subdomains can be off for enough time. | 147 | * Check if subdomains can be off for enough time. |
66 | * | 148 | * |
@@ -73,8 +155,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
73 | if (sd_max_off_ns < 0) | 155 | if (sd_max_off_ns < 0) |
74 | continue; | 156 | continue; |
75 | 157 | ||
76 | sd_max_off_ns -= ktime_to_ns(ktime_sub(time_now, | ||
77 | sd->power_off_time)); | ||
78 | /* | 158 | /* |
79 | * Check if the subdomain is allowed to be off long enough for | 159 | * Check if the subdomain is allowed to be off long enough for |
80 | * the current domain to turn off and on (that's how much time | 160 | * the current domain to turn off and on (that's how much time |
@@ -82,60 +162,64 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
82 | */ | 162 | */ |
83 | if (sd_max_off_ns <= off_on_time_ns) | 163 | if (sd_max_off_ns <= off_on_time_ns) |
84 | return false; | 164 | return false; |
165 | |||
166 | if (min_off_time_ns > sd_max_off_ns || min_off_time_ns < 0) | ||
167 | min_off_time_ns = sd_max_off_ns; | ||
85 | } | 168 | } |
86 | 169 | ||
87 | /* | 170 | /* |
88 | * Check if the devices in the domain can be off enough time. | 171 | * Check if the devices in the domain can be off enough time. |
89 | */ | 172 | */ |
90 | min_dev_off_time_ns = -1; | ||
91 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { | 173 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { |
92 | struct gpd_timing_data *td; | 174 | struct gpd_timing_data *td; |
93 | struct device *dev = pdd->dev; | 175 | s64 constraint_ns; |
94 | s64 dev_off_time_ns; | ||
95 | 176 | ||
96 | if (!dev->driver || dev->power.max_time_suspended_ns < 0) | 177 | if (!pdd->dev->driver) |
97 | continue; | 178 | continue; |
98 | 179 | ||
180 | /* | ||
181 | * Check if the device is allowed to be off long enough for the | ||
182 | * domain to turn off and on (that's how much time it will | ||
183 | * have to wait worst case). | ||
184 | */ | ||
99 | td = &to_gpd_data(pdd)->td; | 185 | td = &to_gpd_data(pdd)->td; |
100 | dev_off_time_ns = dev->power.max_time_suspended_ns - | 186 | constraint_ns = td->effective_constraint_ns; |
101 | (td->start_latency_ns + td->restore_state_latency_ns + | 187 | /* default_stop_ok() need not be called before us. */ |
102 | ktime_to_ns(ktime_sub(time_now, | 188 | if (constraint_ns < 0) { |
103 | dev->power.suspend_time))); | 189 | constraint_ns = dev_pm_qos_read_value(pdd->dev); |
104 | if (dev_off_time_ns <= off_on_time_ns) | 190 | constraint_ns *= NSEC_PER_USEC; |
105 | return false; | 191 | } |
106 | 192 | if (constraint_ns == 0) | |
107 | if (min_dev_off_time_ns > dev_off_time_ns | 193 | continue; |
108 | || min_dev_off_time_ns < 0) | ||
109 | min_dev_off_time_ns = dev_off_time_ns; | ||
110 | } | ||
111 | 194 | ||
112 | if (min_dev_off_time_ns < 0) { | ||
113 | /* | 195 | /* |
114 | * There are no latency constraints, so the domain can spend | 196 | * constraint_ns cannot be negative here, because the device has |
115 | * arbitrary time in the "off" state. | 197 | * been suspended. |
116 | */ | 198 | */ |
117 | genpd->max_off_time_ns = -1; | 199 | constraint_ns -= td->restore_state_latency_ns; |
118 | return true; | 200 | if (constraint_ns <= off_on_time_ns) |
201 | return false; | ||
202 | |||
203 | if (min_off_time_ns > constraint_ns || min_off_time_ns < 0) | ||
204 | min_off_time_ns = constraint_ns; | ||
119 | } | 205 | } |
120 | 206 | ||
207 | genpd->cached_power_down_ok = true; | ||
208 | |||
121 | /* | 209 | /* |
122 | * The difference between the computed minimum delta and the time needed | 210 | * If the computed minimum device off time is negative, there are no |
123 | * to turn the domain on is the maximum theoretical time this domain can | 211 | * latency constraints, so the domain can spend arbitrary time in the |
124 | * spend in the "off" state. | 212 | * "off" state. |
125 | */ | 213 | */ |
126 | min_dev_off_time_ns -= genpd->power_on_latency_ns; | 214 | if (min_off_time_ns < 0) |
215 | return true; | ||
127 | 216 | ||
128 | /* | 217 | /* |
129 | * If the difference between the computed minimum delta and the time | 218 | * The difference between the computed minimum subdomain or device off |
130 | * needed to turn the domain off and back on on is smaller than the | 219 | * time and the time needed to turn the domain on is the maximum |
131 | * domain's power break even time, removing power from the domain is not | 220 | * theoretical time this domain can spend in the "off" state. |
132 | * worth it. | ||
133 | */ | 221 | */ |
134 | if (genpd->break_even_ns > | 222 | genpd->max_off_time_ns = min_off_time_ns - genpd->power_on_latency_ns; |
135 | min_dev_off_time_ns - genpd->power_off_latency_ns) | ||
136 | return false; | ||
137 | |||
138 | genpd->max_off_time_ns = min_dev_off_time_ns; | ||
139 | return true; | 223 | return true; |
140 | } | 224 | } |
141 | 225 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index b462c0e341cb..e0fb5b0435a3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -889,6 +889,11 @@ static int dpm_suspend_noirq(pm_message_t state) | |||
889 | if (!list_empty(&dev->power.entry)) | 889 | if (!list_empty(&dev->power.entry)) |
890 | list_move(&dev->power.entry, &dpm_noirq_list); | 890 | list_move(&dev->power.entry, &dpm_noirq_list); |
891 | put_device(dev); | 891 | put_device(dev); |
892 | |||
893 | if (pm_wakeup_pending()) { | ||
894 | error = -EBUSY; | ||
895 | break; | ||
896 | } | ||
892 | } | 897 | } |
893 | mutex_unlock(&dpm_list_mtx); | 898 | mutex_unlock(&dpm_list_mtx); |
894 | if (error) | 899 | if (error) |
@@ -962,6 +967,11 @@ static int dpm_suspend_late(pm_message_t state) | |||
962 | if (!list_empty(&dev->power.entry)) | 967 | if (!list_empty(&dev->power.entry)) |
963 | list_move(&dev->power.entry, &dpm_late_early_list); | 968 | list_move(&dev->power.entry, &dpm_late_early_list); |
964 | put_device(dev); | 969 | put_device(dev); |
970 | |||
971 | if (pm_wakeup_pending()) { | ||
972 | error = -EBUSY; | ||
973 | break; | ||
974 | } | ||
965 | } | 975 | } |
966 | mutex_unlock(&dpm_list_mtx); | 976 | mutex_unlock(&dpm_list_mtx); |
967 | if (error) | 977 | if (error) |
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 71855570922d..fd849a2c4fa8 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
@@ -352,21 +352,26 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request); | |||
352 | * | 352 | * |
353 | * Will register the notifier into a notification chain that gets called | 353 | * Will register the notifier into a notification chain that gets called |
354 | * upon changes to the target value for the device. | 354 | * upon changes to the target value for the device. |
355 | * | ||
356 | * If the device's constraints object doesn't exist when this routine is called, | ||
357 | * it will be created (or error code will be returned if that fails). | ||
355 | */ | 358 | */ |
356 | int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) | 359 | int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) |
357 | { | 360 | { |
358 | int retval = 0; | 361 | int ret = 0; |
359 | 362 | ||
360 | mutex_lock(&dev_pm_qos_mtx); | 363 | mutex_lock(&dev_pm_qos_mtx); |
361 | 364 | ||
362 | /* Silently return if the constraints object is not present. */ | 365 | if (!dev->power.constraints) |
363 | if (dev->power.constraints) | 366 | ret = dev->power.power_state.event != PM_EVENT_INVALID ? |
364 | retval = blocking_notifier_chain_register( | 367 | dev_pm_qos_constraints_allocate(dev) : -ENODEV; |
365 | dev->power.constraints->notifiers, | 368 | |
366 | notifier); | 369 | if (!ret) |
370 | ret = blocking_notifier_chain_register( | ||
371 | dev->power.constraints->notifiers, notifier); | ||
367 | 372 | ||
368 | mutex_unlock(&dev_pm_qos_mtx); | 373 | mutex_unlock(&dev_pm_qos_mtx); |
369 | return retval; | 374 | return ret; |
370 | } | 375 | } |
371 | EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier); | 376 | EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier); |
372 | 377 | ||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index bd0f3949bcf9..59894873a3b3 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -282,47 +282,6 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev) | |||
282 | return retval != -EACCES ? retval : -EIO; | 282 | return retval != -EACCES ? retval : -EIO; |
283 | } | 283 | } |
284 | 284 | ||
285 | struct rpm_qos_data { | ||
286 | ktime_t time_now; | ||
287 | s64 constraint_ns; | ||
288 | }; | ||
289 | |||
290 | /** | ||
291 | * rpm_update_qos_constraint - Update a given PM QoS constraint data. | ||
292 | * @dev: Device whose timing data to use. | ||
293 | * @data: PM QoS constraint data to update. | ||
294 | * | ||
295 | * Use the suspend timing data of @dev to update PM QoS constraint data pointed | ||
296 | * to by @data. | ||
297 | */ | ||
298 | static int rpm_update_qos_constraint(struct device *dev, void *data) | ||
299 | { | ||
300 | struct rpm_qos_data *qos = data; | ||
301 | unsigned long flags; | ||
302 | s64 delta_ns; | ||
303 | int ret = 0; | ||
304 | |||
305 | spin_lock_irqsave(&dev->power.lock, flags); | ||
306 | |||
307 | if (dev->power.max_time_suspended_ns < 0) | ||
308 | goto out; | ||
309 | |||
310 | delta_ns = dev->power.max_time_suspended_ns - | ||
311 | ktime_to_ns(ktime_sub(qos->time_now, dev->power.suspend_time)); | ||
312 | if (delta_ns <= 0) { | ||
313 | ret = -EBUSY; | ||
314 | goto out; | ||
315 | } | ||
316 | |||
317 | if (qos->constraint_ns > delta_ns || qos->constraint_ns == 0) | ||
318 | qos->constraint_ns = delta_ns; | ||
319 | |||
320 | out: | ||
321 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | /** | 285 | /** |
327 | * rpm_suspend - Carry out runtime suspend of given device. | 286 | * rpm_suspend - Carry out runtime suspend of given device. |
328 | * @dev: Device to suspend. | 287 | * @dev: Device to suspend. |
@@ -349,7 +308,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
349 | { | 308 | { |
350 | int (*callback)(struct device *); | 309 | int (*callback)(struct device *); |
351 | struct device *parent = NULL; | 310 | struct device *parent = NULL; |
352 | struct rpm_qos_data qos; | ||
353 | int retval; | 311 | int retval; |
354 | 312 | ||
355 | trace_rpm_suspend(dev, rpmflags); | 313 | trace_rpm_suspend(dev, rpmflags); |
@@ -445,38 +403,14 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
445 | goto out; | 403 | goto out; |
446 | } | 404 | } |
447 | 405 | ||
448 | qos.constraint_ns = __dev_pm_qos_read_value(dev); | 406 | if (__dev_pm_qos_read_value(dev) < 0) { |
449 | if (qos.constraint_ns < 0) { | 407 | /* Negative PM QoS constraint means "never suspend". */ |
450 | /* Negative constraint means "never suspend". */ | ||
451 | retval = -EPERM; | 408 | retval = -EPERM; |
452 | goto out; | 409 | goto out; |
453 | } | 410 | } |
454 | qos.constraint_ns *= NSEC_PER_USEC; | ||
455 | qos.time_now = ktime_get(); | ||
456 | 411 | ||
457 | __update_runtime_status(dev, RPM_SUSPENDING); | 412 | __update_runtime_status(dev, RPM_SUSPENDING); |
458 | 413 | ||
459 | if (!dev->power.ignore_children) { | ||
460 | if (dev->power.irq_safe) | ||
461 | spin_unlock(&dev->power.lock); | ||
462 | else | ||
463 | spin_unlock_irq(&dev->power.lock); | ||
464 | |||
465 | retval = device_for_each_child(dev, &qos, | ||
466 | rpm_update_qos_constraint); | ||
467 | |||
468 | if (dev->power.irq_safe) | ||
469 | spin_lock(&dev->power.lock); | ||
470 | else | ||
471 | spin_lock_irq(&dev->power.lock); | ||
472 | |||
473 | if (retval) | ||
474 | goto fail; | ||
475 | } | ||
476 | |||
477 | dev->power.suspend_time = qos.time_now; | ||
478 | dev->power.max_time_suspended_ns = qos.constraint_ns ? : -1; | ||
479 | |||
480 | if (dev->pm_domain) | 414 | if (dev->pm_domain) |
481 | callback = dev->pm_domain->ops.runtime_suspend; | 415 | callback = dev->pm_domain->ops.runtime_suspend; |
482 | else if (dev->type && dev->type->pm) | 416 | else if (dev->type && dev->type->pm) |
@@ -529,8 +463,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
529 | 463 | ||
530 | fail: | 464 | fail: |
531 | __update_runtime_status(dev, RPM_ACTIVE); | 465 | __update_runtime_status(dev, RPM_ACTIVE); |
532 | dev->power.suspend_time = ktime_set(0, 0); | ||
533 | dev->power.max_time_suspended_ns = -1; | ||
534 | dev->power.deferred_resume = false; | 466 | dev->power.deferred_resume = false; |
535 | wake_up_all(&dev->power.wait_queue); | 467 | wake_up_all(&dev->power.wait_queue); |
536 | 468 | ||
@@ -704,9 +636,6 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
704 | if (dev->power.no_callbacks) | 636 | if (dev->power.no_callbacks) |
705 | goto no_callback; /* Assume success. */ | 637 | goto no_callback; /* Assume success. */ |
706 | 638 | ||
707 | dev->power.suspend_time = ktime_set(0, 0); | ||
708 | dev->power.max_time_suspended_ns = -1; | ||
709 | |||
710 | __update_runtime_status(dev, RPM_RESUMING); | 639 | __update_runtime_status(dev, RPM_RESUMING); |
711 | 640 | ||
712 | if (dev->pm_domain) | 641 | if (dev->pm_domain) |
@@ -1369,9 +1298,6 @@ void pm_runtime_init(struct device *dev) | |||
1369 | setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn, | 1298 | setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn, |
1370 | (unsigned long)dev); | 1299 | (unsigned long)dev); |
1371 | 1300 | ||
1372 | dev->power.suspend_time = ktime_set(0, 0); | ||
1373 | dev->power.max_time_suspended_ns = -1; | ||
1374 | |||
1375 | init_waitqueue_head(&dev->power.wait_queue); | 1301 | init_waitqueue_head(&dev->power.wait_queue); |
1376 | } | 1302 | } |
1377 | 1303 | ||
@@ -1389,28 +1315,3 @@ void pm_runtime_remove(struct device *dev) | |||
1389 | if (dev->power.irq_safe && dev->parent) | 1315 | if (dev->power.irq_safe && dev->parent) |
1390 | pm_runtime_put_sync(dev->parent); | 1316 | pm_runtime_put_sync(dev->parent); |
1391 | } | 1317 | } |
1392 | |||
1393 | /** | ||
1394 | * pm_runtime_update_max_time_suspended - Update device's suspend time data. | ||
1395 | * @dev: Device to handle. | ||
1396 | * @delta_ns: Value to subtract from the device's max_time_suspended_ns field. | ||
1397 | * | ||
1398 | * Update the device's power.max_time_suspended_ns field by subtracting | ||
1399 | * @delta_ns from it. The resulting value of power.max_time_suspended_ns is | ||
1400 | * never negative. | ||
1401 | */ | ||
1402 | void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns) | ||
1403 | { | ||
1404 | unsigned long flags; | ||
1405 | |||
1406 | spin_lock_irqsave(&dev->power.lock, flags); | ||
1407 | |||
1408 | if (delta_ns > 0 && dev->power.max_time_suspended_ns > 0) { | ||
1409 | if (dev->power.max_time_suspended_ns > delta_ns) | ||
1410 | dev->power.max_time_suspended_ns -= delta_ns; | ||
1411 | else | ||
1412 | dev->power.max_time_suspended_ns = 0; | ||
1413 | } | ||
1414 | |||
1415 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
1416 | } | ||
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 95c12f6cb5b9..48be2ad4dd2c 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -314,22 +314,41 @@ static ssize_t wakeup_active_count_show(struct device *dev, | |||
314 | 314 | ||
315 | static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL); | 315 | static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL); |
316 | 316 | ||
317 | static ssize_t wakeup_hit_count_show(struct device *dev, | 317 | static ssize_t wakeup_abort_count_show(struct device *dev, |
318 | struct device_attribute *attr, char *buf) | 318 | struct device_attribute *attr, |
319 | char *buf) | ||
320 | { | ||
321 | unsigned long count = 0; | ||
322 | bool enabled = false; | ||
323 | |||
324 | spin_lock_irq(&dev->power.lock); | ||
325 | if (dev->power.wakeup) { | ||
326 | count = dev->power.wakeup->wakeup_count; | ||
327 | enabled = true; | ||
328 | } | ||
329 | spin_unlock_irq(&dev->power.lock); | ||
330 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
331 | } | ||
332 | |||
333 | static DEVICE_ATTR(wakeup_abort_count, 0444, wakeup_abort_count_show, NULL); | ||
334 | |||
335 | static ssize_t wakeup_expire_count_show(struct device *dev, | ||
336 | struct device_attribute *attr, | ||
337 | char *buf) | ||
319 | { | 338 | { |
320 | unsigned long count = 0; | 339 | unsigned long count = 0; |
321 | bool enabled = false; | 340 | bool enabled = false; |
322 | 341 | ||
323 | spin_lock_irq(&dev->power.lock); | 342 | spin_lock_irq(&dev->power.lock); |
324 | if (dev->power.wakeup) { | 343 | if (dev->power.wakeup) { |
325 | count = dev->power.wakeup->hit_count; | 344 | count = dev->power.wakeup->expire_count; |
326 | enabled = true; | 345 | enabled = true; |
327 | } | 346 | } |
328 | spin_unlock_irq(&dev->power.lock); | 347 | spin_unlock_irq(&dev->power.lock); |
329 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | 348 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); |
330 | } | 349 | } |
331 | 350 | ||
332 | static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL); | 351 | static DEVICE_ATTR(wakeup_expire_count, 0444, wakeup_expire_count_show, NULL); |
333 | 352 | ||
334 | static ssize_t wakeup_active_show(struct device *dev, | 353 | static ssize_t wakeup_active_show(struct device *dev, |
335 | struct device_attribute *attr, char *buf) | 354 | struct device_attribute *attr, char *buf) |
@@ -398,6 +417,27 @@ static ssize_t wakeup_last_time_show(struct device *dev, | |||
398 | } | 417 | } |
399 | 418 | ||
400 | static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL); | 419 | static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL); |
420 | |||
421 | #ifdef CONFIG_PM_AUTOSLEEP | ||
422 | static ssize_t wakeup_prevent_sleep_time_show(struct device *dev, | ||
423 | struct device_attribute *attr, | ||
424 | char *buf) | ||
425 | { | ||
426 | s64 msec = 0; | ||
427 | bool enabled = false; | ||
428 | |||
429 | spin_lock_irq(&dev->power.lock); | ||
430 | if (dev->power.wakeup) { | ||
431 | msec = ktime_to_ms(dev->power.wakeup->prevent_sleep_time); | ||
432 | enabled = true; | ||
433 | } | ||
434 | spin_unlock_irq(&dev->power.lock); | ||
435 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
436 | } | ||
437 | |||
438 | static DEVICE_ATTR(wakeup_prevent_sleep_time_ms, 0444, | ||
439 | wakeup_prevent_sleep_time_show, NULL); | ||
440 | #endif /* CONFIG_PM_AUTOSLEEP */ | ||
401 | #endif /* CONFIG_PM_SLEEP */ | 441 | #endif /* CONFIG_PM_SLEEP */ |
402 | 442 | ||
403 | #ifdef CONFIG_PM_ADVANCED_DEBUG | 443 | #ifdef CONFIG_PM_ADVANCED_DEBUG |
@@ -486,11 +526,15 @@ static struct attribute *wakeup_attrs[] = { | |||
486 | &dev_attr_wakeup.attr, | 526 | &dev_attr_wakeup.attr, |
487 | &dev_attr_wakeup_count.attr, | 527 | &dev_attr_wakeup_count.attr, |
488 | &dev_attr_wakeup_active_count.attr, | 528 | &dev_attr_wakeup_active_count.attr, |
489 | &dev_attr_wakeup_hit_count.attr, | 529 | &dev_attr_wakeup_abort_count.attr, |
530 | &dev_attr_wakeup_expire_count.attr, | ||
490 | &dev_attr_wakeup_active.attr, | 531 | &dev_attr_wakeup_active.attr, |
491 | &dev_attr_wakeup_total_time_ms.attr, | 532 | &dev_attr_wakeup_total_time_ms.attr, |
492 | &dev_attr_wakeup_max_time_ms.attr, | 533 | &dev_attr_wakeup_max_time_ms.attr, |
493 | &dev_attr_wakeup_last_time_ms.attr, | 534 | &dev_attr_wakeup_last_time_ms.attr, |
535 | #ifdef CONFIG_PM_AUTOSLEEP | ||
536 | &dev_attr_wakeup_prevent_sleep_time_ms.attr, | ||
537 | #endif | ||
494 | #endif | 538 | #endif |
495 | NULL, | 539 | NULL, |
496 | }; | 540 | }; |
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 2a3e581b8dcd..cbb463b3a750 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -14,16 +14,15 @@ | |||
14 | #include <linux/suspend.h> | 14 | #include <linux/suspend.h> |
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/debugfs.h> | 16 | #include <linux/debugfs.h> |
17 | #include <trace/events/power.h> | ||
17 | 18 | ||
18 | #include "power.h" | 19 | #include "power.h" |
19 | 20 | ||
20 | #define TIMEOUT 100 | ||
21 | |||
22 | /* | 21 | /* |
23 | * If set, the suspend/hibernate code will abort transitions to a sleep state | 22 | * If set, the suspend/hibernate code will abort transitions to a sleep state |
24 | * if wakeup events are registered during or immediately before the transition. | 23 | * if wakeup events are registered during or immediately before the transition. |
25 | */ | 24 | */ |
26 | bool events_check_enabled; | 25 | bool events_check_enabled __read_mostly; |
27 | 26 | ||
28 | /* | 27 | /* |
29 | * Combined counters of registered wakeup events and wakeup events in progress. | 28 | * Combined counters of registered wakeup events and wakeup events in progress. |
@@ -52,6 +51,8 @@ static void pm_wakeup_timer_fn(unsigned long data); | |||
52 | 51 | ||
53 | static LIST_HEAD(wakeup_sources); | 52 | static LIST_HEAD(wakeup_sources); |
54 | 53 | ||
54 | static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue); | ||
55 | |||
55 | /** | 56 | /** |
56 | * wakeup_source_prepare - Prepare a new wakeup source for initialization. | 57 | * wakeup_source_prepare - Prepare a new wakeup source for initialization. |
57 | * @ws: Wakeup source to prepare. | 58 | * @ws: Wakeup source to prepare. |
@@ -132,6 +133,7 @@ void wakeup_source_add(struct wakeup_source *ws) | |||
132 | spin_lock_init(&ws->lock); | 133 | spin_lock_init(&ws->lock); |
133 | setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws); | 134 | setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws); |
134 | ws->active = false; | 135 | ws->active = false; |
136 | ws->last_time = ktime_get(); | ||
135 | 137 | ||
136 | spin_lock_irq(&events_lock); | 138 | spin_lock_irq(&events_lock); |
137 | list_add_rcu(&ws->entry, &wakeup_sources); | 139 | list_add_rcu(&ws->entry, &wakeup_sources); |
@@ -374,12 +376,33 @@ EXPORT_SYMBOL_GPL(device_set_wakeup_enable); | |||
374 | */ | 376 | */ |
375 | static void wakeup_source_activate(struct wakeup_source *ws) | 377 | static void wakeup_source_activate(struct wakeup_source *ws) |
376 | { | 378 | { |
379 | unsigned int cec; | ||
380 | |||
377 | ws->active = true; | 381 | ws->active = true; |
378 | ws->active_count++; | 382 | ws->active_count++; |
379 | ws->last_time = ktime_get(); | 383 | ws->last_time = ktime_get(); |
384 | if (ws->autosleep_enabled) | ||
385 | ws->start_prevent_time = ws->last_time; | ||
380 | 386 | ||
381 | /* Increment the counter of events in progress. */ | 387 | /* Increment the counter of events in progress. */ |
382 | atomic_inc(&combined_event_count); | 388 | cec = atomic_inc_return(&combined_event_count); |
389 | |||
390 | trace_wakeup_source_activate(ws->name, cec); | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * wakeup_source_report_event - Report wakeup event using the given source. | ||
395 | * @ws: Wakeup source to report the event for. | ||
396 | */ | ||
397 | static void wakeup_source_report_event(struct wakeup_source *ws) | ||
398 | { | ||
399 | ws->event_count++; | ||
400 | /* This is racy, but the counter is approximate anyway. */ | ||
401 | if (events_check_enabled) | ||
402 | ws->wakeup_count++; | ||
403 | |||
404 | if (!ws->active) | ||
405 | wakeup_source_activate(ws); | ||
383 | } | 406 | } |
384 | 407 | ||
385 | /** | 408 | /** |
@@ -397,10 +420,7 @@ void __pm_stay_awake(struct wakeup_source *ws) | |||
397 | 420 | ||
398 | spin_lock_irqsave(&ws->lock, flags); | 421 | spin_lock_irqsave(&ws->lock, flags); |
399 | 422 | ||
400 | ws->event_count++; | 423 | wakeup_source_report_event(ws); |
401 | if (!ws->active) | ||
402 | wakeup_source_activate(ws); | ||
403 | |||
404 | del_timer(&ws->timer); | 424 | del_timer(&ws->timer); |
405 | ws->timer_expires = 0; | 425 | ws->timer_expires = 0; |
406 | 426 | ||
@@ -432,6 +452,17 @@ void pm_stay_awake(struct device *dev) | |||
432 | } | 452 | } |
433 | EXPORT_SYMBOL_GPL(pm_stay_awake); | 453 | EXPORT_SYMBOL_GPL(pm_stay_awake); |
434 | 454 | ||
455 | #ifdef CONFIG_PM_AUTOSLEEP | ||
456 | static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now) | ||
457 | { | ||
458 | ktime_t delta = ktime_sub(now, ws->start_prevent_time); | ||
459 | ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta); | ||
460 | } | ||
461 | #else | ||
462 | static inline void update_prevent_sleep_time(struct wakeup_source *ws, | ||
463 | ktime_t now) {} | ||
464 | #endif | ||
465 | |||
435 | /** | 466 | /** |
436 | * wakup_source_deactivate - Mark given wakeup source as inactive. | 467 | * wakup_source_deactivate - Mark given wakeup source as inactive. |
437 | * @ws: Wakeup source to handle. | 468 | * @ws: Wakeup source to handle. |
@@ -442,6 +473,7 @@ EXPORT_SYMBOL_GPL(pm_stay_awake); | |||
442 | */ | 473 | */ |
443 | static void wakeup_source_deactivate(struct wakeup_source *ws) | 474 | static void wakeup_source_deactivate(struct wakeup_source *ws) |
444 | { | 475 | { |
476 | unsigned int cnt, inpr, cec; | ||
445 | ktime_t duration; | 477 | ktime_t duration; |
446 | ktime_t now; | 478 | ktime_t now; |
447 | 479 | ||
@@ -468,14 +500,23 @@ static void wakeup_source_deactivate(struct wakeup_source *ws) | |||
468 | if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) | 500 | if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) |
469 | ws->max_time = duration; | 501 | ws->max_time = duration; |
470 | 502 | ||
503 | ws->last_time = now; | ||
471 | del_timer(&ws->timer); | 504 | del_timer(&ws->timer); |
472 | ws->timer_expires = 0; | 505 | ws->timer_expires = 0; |
473 | 506 | ||
507 | if (ws->autosleep_enabled) | ||
508 | update_prevent_sleep_time(ws, now); | ||
509 | |||
474 | /* | 510 | /* |
475 | * Increment the counter of registered wakeup events and decrement the | 511 | * Increment the counter of registered wakeup events and decrement the |
476 | * couter of wakeup events in progress simultaneously. | 512 | * couter of wakeup events in progress simultaneously. |
477 | */ | 513 | */ |
478 | atomic_add(MAX_IN_PROGRESS, &combined_event_count); | 514 | cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count); |
515 | trace_wakeup_source_deactivate(ws->name, cec); | ||
516 | |||
517 | split_counters(&cnt, &inpr); | ||
518 | if (!inpr && waitqueue_active(&wakeup_count_wait_queue)) | ||
519 | wake_up(&wakeup_count_wait_queue); | ||
479 | } | 520 | } |
480 | 521 | ||
481 | /** | 522 | /** |
@@ -536,8 +577,10 @@ static void pm_wakeup_timer_fn(unsigned long data) | |||
536 | spin_lock_irqsave(&ws->lock, flags); | 577 | spin_lock_irqsave(&ws->lock, flags); |
537 | 578 | ||
538 | if (ws->active && ws->timer_expires | 579 | if (ws->active && ws->timer_expires |
539 | && time_after_eq(jiffies, ws->timer_expires)) | 580 | && time_after_eq(jiffies, ws->timer_expires)) { |
540 | wakeup_source_deactivate(ws); | 581 | wakeup_source_deactivate(ws); |
582 | ws->expire_count++; | ||
583 | } | ||
541 | 584 | ||
542 | spin_unlock_irqrestore(&ws->lock, flags); | 585 | spin_unlock_irqrestore(&ws->lock, flags); |
543 | } | 586 | } |
@@ -564,9 +607,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) | |||
564 | 607 | ||
565 | spin_lock_irqsave(&ws->lock, flags); | 608 | spin_lock_irqsave(&ws->lock, flags); |
566 | 609 | ||
567 | ws->event_count++; | 610 | wakeup_source_report_event(ws); |
568 | if (!ws->active) | ||
569 | wakeup_source_activate(ws); | ||
570 | 611 | ||
571 | if (!msec) { | 612 | if (!msec) { |
572 | wakeup_source_deactivate(ws); | 613 | wakeup_source_deactivate(ws); |
@@ -609,24 +650,6 @@ void pm_wakeup_event(struct device *dev, unsigned int msec) | |||
609 | EXPORT_SYMBOL_GPL(pm_wakeup_event); | 650 | EXPORT_SYMBOL_GPL(pm_wakeup_event); |
610 | 651 | ||
611 | /** | 652 | /** |
612 | * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources. | ||
613 | */ | ||
614 | static void pm_wakeup_update_hit_counts(void) | ||
615 | { | ||
616 | unsigned long flags; | ||
617 | struct wakeup_source *ws; | ||
618 | |||
619 | rcu_read_lock(); | ||
620 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) { | ||
621 | spin_lock_irqsave(&ws->lock, flags); | ||
622 | if (ws->active) | ||
623 | ws->hit_count++; | ||
624 | spin_unlock_irqrestore(&ws->lock, flags); | ||
625 | } | ||
626 | rcu_read_unlock(); | ||
627 | } | ||
628 | |||
629 | /** | ||
630 | * pm_wakeup_pending - Check if power transition in progress should be aborted. | 653 | * pm_wakeup_pending - Check if power transition in progress should be aborted. |
631 | * | 654 | * |
632 | * Compare the current number of registered wakeup events with its preserved | 655 | * Compare the current number of registered wakeup events with its preserved |
@@ -648,32 +671,38 @@ bool pm_wakeup_pending(void) | |||
648 | events_check_enabled = !ret; | 671 | events_check_enabled = !ret; |
649 | } | 672 | } |
650 | spin_unlock_irqrestore(&events_lock, flags); | 673 | spin_unlock_irqrestore(&events_lock, flags); |
651 | if (ret) | ||
652 | pm_wakeup_update_hit_counts(); | ||
653 | return ret; | 674 | return ret; |
654 | } | 675 | } |
655 | 676 | ||
656 | /** | 677 | /** |
657 | * pm_get_wakeup_count - Read the number of registered wakeup events. | 678 | * pm_get_wakeup_count - Read the number of registered wakeup events. |
658 | * @count: Address to store the value at. | 679 | * @count: Address to store the value at. |
680 | * @block: Whether or not to block. | ||
659 | * | 681 | * |
660 | * Store the number of registered wakeup events at the address in @count. Block | 682 | * Store the number of registered wakeup events at the address in @count. If |
661 | * if the current number of wakeup events being processed is nonzero. | 683 | * @block is set, block until the current number of wakeup events being |
684 | * processed is zero. | ||
662 | * | 685 | * |
663 | * Return 'false' if the wait for the number of wakeup events being processed to | 686 | * Return 'false' if the current number of wakeup events being processed is |
664 | * drop down to zero has been interrupted by a signal (and the current number | 687 | * nonzero. Otherwise return 'true'. |
665 | * of wakeup events being processed is still nonzero). Otherwise return 'true'. | ||
666 | */ | 688 | */ |
667 | bool pm_get_wakeup_count(unsigned int *count) | 689 | bool pm_get_wakeup_count(unsigned int *count, bool block) |
668 | { | 690 | { |
669 | unsigned int cnt, inpr; | 691 | unsigned int cnt, inpr; |
670 | 692 | ||
671 | for (;;) { | 693 | if (block) { |
672 | split_counters(&cnt, &inpr); | 694 | DEFINE_WAIT(wait); |
673 | if (inpr == 0 || signal_pending(current)) | 695 | |
674 | break; | 696 | for (;;) { |
675 | pm_wakeup_update_hit_counts(); | 697 | prepare_to_wait(&wakeup_count_wait_queue, &wait, |
676 | schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT)); | 698 | TASK_INTERRUPTIBLE); |
699 | split_counters(&cnt, &inpr); | ||
700 | if (inpr == 0 || signal_pending(current)) | ||
701 | break; | ||
702 | |||
703 | schedule(); | ||
704 | } | ||
705 | finish_wait(&wakeup_count_wait_queue, &wait); | ||
677 | } | 706 | } |
678 | 707 | ||
679 | split_counters(&cnt, &inpr); | 708 | split_counters(&cnt, &inpr); |
@@ -703,11 +732,37 @@ bool pm_save_wakeup_count(unsigned int count) | |||
703 | events_check_enabled = true; | 732 | events_check_enabled = true; |
704 | } | 733 | } |
705 | spin_unlock_irq(&events_lock); | 734 | spin_unlock_irq(&events_lock); |
706 | if (!events_check_enabled) | ||
707 | pm_wakeup_update_hit_counts(); | ||
708 | return events_check_enabled; | 735 | return events_check_enabled; |
709 | } | 736 | } |
710 | 737 | ||
738 | #ifdef CONFIG_PM_AUTOSLEEP | ||
739 | /** | ||
740 | * pm_wakep_autosleep_enabled - Modify autosleep_enabled for all wakeup sources. | ||
741 | * @enabled: Whether to set or to clear the autosleep_enabled flags. | ||
742 | */ | ||
743 | void pm_wakep_autosleep_enabled(bool set) | ||
744 | { | ||
745 | struct wakeup_source *ws; | ||
746 | ktime_t now = ktime_get(); | ||
747 | |||
748 | rcu_read_lock(); | ||
749 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) { | ||
750 | spin_lock_irq(&ws->lock); | ||
751 | if (ws->autosleep_enabled != set) { | ||
752 | ws->autosleep_enabled = set; | ||
753 | if (ws->active) { | ||
754 | if (set) | ||
755 | ws->start_prevent_time = now; | ||
756 | else | ||
757 | update_prevent_sleep_time(ws, now); | ||
758 | } | ||
759 | } | ||
760 | spin_unlock_irq(&ws->lock); | ||
761 | } | ||
762 | rcu_read_unlock(); | ||
763 | } | ||
764 | #endif /* CONFIG_PM_AUTOSLEEP */ | ||
765 | |||
711 | static struct dentry *wakeup_sources_stats_dentry; | 766 | static struct dentry *wakeup_sources_stats_dentry; |
712 | 767 | ||
713 | /** | 768 | /** |
@@ -723,27 +778,37 @@ static int print_wakeup_source_stats(struct seq_file *m, | |||
723 | ktime_t max_time; | 778 | ktime_t max_time; |
724 | unsigned long active_count; | 779 | unsigned long active_count; |
725 | ktime_t active_time; | 780 | ktime_t active_time; |
781 | ktime_t prevent_sleep_time; | ||
726 | int ret; | 782 | int ret; |
727 | 783 | ||
728 | spin_lock_irqsave(&ws->lock, flags); | 784 | spin_lock_irqsave(&ws->lock, flags); |
729 | 785 | ||
730 | total_time = ws->total_time; | 786 | total_time = ws->total_time; |
731 | max_time = ws->max_time; | 787 | max_time = ws->max_time; |
788 | prevent_sleep_time = ws->prevent_sleep_time; | ||
732 | active_count = ws->active_count; | 789 | active_count = ws->active_count; |
733 | if (ws->active) { | 790 | if (ws->active) { |
734 | active_time = ktime_sub(ktime_get(), ws->last_time); | 791 | ktime_t now = ktime_get(); |
792 | |||
793 | active_time = ktime_sub(now, ws->last_time); | ||
735 | total_time = ktime_add(total_time, active_time); | 794 | total_time = ktime_add(total_time, active_time); |
736 | if (active_time.tv64 > max_time.tv64) | 795 | if (active_time.tv64 > max_time.tv64) |
737 | max_time = active_time; | 796 | max_time = active_time; |
797 | |||
798 | if (ws->autosleep_enabled) | ||
799 | prevent_sleep_time = ktime_add(prevent_sleep_time, | ||
800 | ktime_sub(now, ws->start_prevent_time)); | ||
738 | } else { | 801 | } else { |
739 | active_time = ktime_set(0, 0); | 802 | active_time = ktime_set(0, 0); |
740 | } | 803 | } |
741 | 804 | ||
742 | ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t" | 805 | ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t" |
743 | "%lld\t\t%lld\t\t%lld\t\t%lld\n", | 806 | "%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n", |
744 | ws->name, active_count, ws->event_count, ws->hit_count, | 807 | ws->name, active_count, ws->event_count, |
808 | ws->wakeup_count, ws->expire_count, | ||
745 | ktime_to_ms(active_time), ktime_to_ms(total_time), | 809 | ktime_to_ms(active_time), ktime_to_ms(total_time), |
746 | ktime_to_ms(max_time), ktime_to_ms(ws->last_time)); | 810 | ktime_to_ms(max_time), ktime_to_ms(ws->last_time), |
811 | ktime_to_ms(prevent_sleep_time)); | ||
747 | 812 | ||
748 | spin_unlock_irqrestore(&ws->lock, flags); | 813 | spin_unlock_irqrestore(&ws->lock, flags); |
749 | 814 | ||
@@ -758,8 +823,9 @@ static int wakeup_sources_stats_show(struct seq_file *m, void *unused) | |||
758 | { | 823 | { |
759 | struct wakeup_source *ws; | 824 | struct wakeup_source *ws; |
760 | 825 | ||
761 | seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t" | 826 | seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t" |
762 | "active_since\ttotal_time\tmax_time\tlast_change\n"); | 827 | "expire_count\tactive_since\ttotal_time\tmax_time\t" |
828 | "last_change\tprevent_suspend_time\n"); | ||
763 | 829 | ||
764 | rcu_read_lock(); | 830 | rcu_read_lock(); |
765 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) | 831 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) |