aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2015-10-15 11:02:19 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-10-27 23:33:04 -0400
commit2b1d88cda32f81685bae45c00bf517f77bcda3cd (patch)
tree6e61c6e8868866887fc14cb647b0c9d0636767c8
parent51cda844892fded75d3ad07d0233e73572eba2f3 (diff)
PM / Domains: Merge measurements for PM QoS device latencies
Measure latency does by itself contribute to an increased latency, thus we should avoid it when it isn't needed. By merging the latency measurements for the ->save_state() and the ->stop() callbacks, we get one measurement instead of two and we get one value to store instead of two. Let's also apply the likewise change for the ->start() and ->restore_state() callbacks. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Lina Iyer <lina.iyer@linaro.org> Acked-by: Kevin Hilman <khilman@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/base/power/domain.c99
-rw-r--r--drivers/base/power/domain_governor.c6
-rw-r--r--include/linux/pm_domain.h6
3 files changed, 55 insertions, 56 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index a1c3ec4cc4fb..a7dfdf9f15ba 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -34,22 +34,6 @@
34 __ret; \ 34 __ret; \
35}) 35})
36 36
37#define GENPD_DEV_TIMED_CALLBACK(genpd, type, callback, dev, field, name) \
38({ \
39 ktime_t __start = ktime_get(); \
40 type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev); \
41 s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start)); \
42 struct gpd_timing_data *__td = &dev_gpd_data(dev)->td; \
43 if (!__retval && __elapsed > __td->field) { \
44 __td->field = __elapsed; \
45 dev_dbg(dev, name " latency exceeded, new value %lld ns\n", \
46 __elapsed); \
47 genpd->max_off_time_changed = true; \
48 __td->constraint_changed = true; \
49 } \
50 __retval; \
51})
52
53static LIST_HEAD(gpd_list); 37static LIST_HEAD(gpd_list);
54static DEFINE_MUTEX(gpd_list_lock); 38static DEFINE_MUTEX(gpd_list_lock);
55 39
@@ -90,24 +74,14 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
90 return pd_to_genpd(dev->pm_domain); 74 return pd_to_genpd(dev->pm_domain);
91} 75}
92 76
93static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev, 77static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
94 bool timed)
95{ 78{
96 if (!timed) 79 return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
97 return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
98
99 return GENPD_DEV_TIMED_CALLBACK(genpd, int, stop, dev,
100 stop_latency_ns, "stop");
101} 80}
102 81
103static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev, 82static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
104 bool timed)
105{ 83{
106 if (!timed) 84 return GENPD_DEV_CALLBACK(genpd, int, start, dev);
107 return GENPD_DEV_CALLBACK(genpd, int, start, dev);
108
109 return GENPD_DEV_TIMED_CALLBACK(genpd, int, start, dev,
110 start_latency_ns, "start");
111} 85}
112 86
113static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) 87static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
@@ -263,19 +237,13 @@ static int genpd_poweron(struct generic_pm_domain *genpd)
263 237
264static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) 238static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
265{ 239{
266 return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev, 240 return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
267 save_state_latency_ns, "state save");
268} 241}
269 242
270static int genpd_restore_dev(struct generic_pm_domain *genpd, 243static int genpd_restore_dev(struct generic_pm_domain *genpd,
271 struct device *dev, bool timed) 244 struct device *dev)
272{ 245{
273 if (!timed) 246 return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
274 return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
275
276 return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
277 restore_state_latency_ns,
278 "state restore");
279} 247}
280 248
281static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, 249static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
@@ -422,6 +390,9 @@ static int pm_genpd_runtime_suspend(struct device *dev)
422{ 390{
423 struct generic_pm_domain *genpd; 391 struct generic_pm_domain *genpd;
424 bool (*stop_ok)(struct device *__dev); 392 bool (*stop_ok)(struct device *__dev);
393 struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
394 ktime_t time_start;
395 s64 elapsed_ns;
425 int ret; 396 int ret;
426 397
427 dev_dbg(dev, "%s()\n", __func__); 398 dev_dbg(dev, "%s()\n", __func__);
@@ -434,16 +405,29 @@ static int pm_genpd_runtime_suspend(struct device *dev)
434 if (stop_ok && !stop_ok(dev)) 405 if (stop_ok && !stop_ok(dev))
435 return -EBUSY; 406 return -EBUSY;
436 407
408 /* Measure suspend latency. */
409 time_start = ktime_get();
410
437 ret = genpd_save_dev(genpd, dev); 411 ret = genpd_save_dev(genpd, dev);
438 if (ret) 412 if (ret)
439 return ret; 413 return ret;
440 414
441 ret = genpd_stop_dev(genpd, dev, true); 415 ret = genpd_stop_dev(genpd, dev);
442 if (ret) { 416 if (ret) {
443 genpd_restore_dev(genpd, dev, true); 417 genpd_restore_dev(genpd, dev);
444 return ret; 418 return ret;
445 } 419 }
446 420
421 /* Update suspend latency value if the measured time exceeds it. */
422 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
423 if (elapsed_ns > td->suspend_latency_ns) {
424 td->suspend_latency_ns = elapsed_ns;
425 dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
426 elapsed_ns);
427 genpd->max_off_time_changed = true;
428 td->constraint_changed = true;
429 }
430
447 /* 431 /*
448 * If power.irq_safe is set, this routine will be run with interrupts 432 * If power.irq_safe is set, this routine will be run with interrupts
449 * off, so it can't use mutexes. 433 * off, so it can't use mutexes.
@@ -469,6 +453,9 @@ static int pm_genpd_runtime_suspend(struct device *dev)
469static int pm_genpd_runtime_resume(struct device *dev) 453static int pm_genpd_runtime_resume(struct device *dev)
470{ 454{
471 struct generic_pm_domain *genpd; 455 struct generic_pm_domain *genpd;
456 struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
457 ktime_t time_start;
458 s64 elapsed_ns;
472 int ret; 459 int ret;
473 bool timed = true; 460 bool timed = true;
474 461
@@ -492,8 +479,24 @@ static int pm_genpd_runtime_resume(struct device *dev)
492 return ret; 479 return ret;
493 480
494 out: 481 out:
495 genpd_start_dev(genpd, dev, timed); 482 /* Measure resume latency. */
496 genpd_restore_dev(genpd, dev, timed); 483 if (timed)
484 time_start = ktime_get();
485
486 genpd_start_dev(genpd, dev);
487 genpd_restore_dev(genpd, dev);
488
489 /* Update resume latency value if the measured time exceeds it. */
490 if (timed) {
491 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
492 if (elapsed_ns > td->resume_latency_ns) {
493 td->resume_latency_ns = elapsed_ns;
494 dev_dbg(dev, "resume latency exceeded, %lld ns\n",
495 elapsed_ns);
496 genpd->max_off_time_changed = true;
497 td->constraint_changed = true;
498 }
499 }
497 500
498 return 0; 501 return 0;
499} 502}
@@ -783,7 +786,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
783 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))) 786 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
784 return 0; 787 return 0;
785 788
786 genpd_stop_dev(genpd, dev, false); 789 genpd_stop_dev(genpd, dev);
787 790
788 /* 791 /*
789 * Since all of the "noirq" callbacks are executed sequentially, it is 792 * Since all of the "noirq" callbacks are executed sequentially, it is
@@ -824,7 +827,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
824 pm_genpd_sync_poweron(genpd, true); 827 pm_genpd_sync_poweron(genpd, true);
825 genpd->suspended_count--; 828 genpd->suspended_count--;
826 829
827 return genpd_start_dev(genpd, dev, false); 830 return genpd_start_dev(genpd, dev);
828} 831}
829 832
830/** 833/**
@@ -932,7 +935,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
932 if (IS_ERR(genpd)) 935 if (IS_ERR(genpd))
933 return -EINVAL; 936 return -EINVAL;
934 937
935 return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev, false); 938 return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev);
936} 939}
937 940
938/** 941/**
@@ -953,7 +956,7 @@ static int pm_genpd_thaw_noirq(struct device *dev)
953 return -EINVAL; 956 return -EINVAL;
954 957
955 return genpd->suspend_power_off ? 958 return genpd->suspend_power_off ?
956 0 : genpd_start_dev(genpd, dev, false); 959 0 : genpd_start_dev(genpd, dev);
957} 960}
958 961
959/** 962/**
@@ -1047,7 +1050,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
1047 1050
1048 pm_genpd_sync_poweron(genpd, true); 1051 pm_genpd_sync_poweron(genpd, true);
1049 1052
1050 return genpd_start_dev(genpd, dev, false); 1053 return genpd_start_dev(genpd, dev);
1051} 1054}
1052 1055
1053/** 1056/**
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 85e17bacc834..e60dd12e23aa 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -77,10 +77,8 @@ static bool default_stop_ok(struct device *dev)
77 dev_update_qos_constraint); 77 dev_update_qos_constraint);
78 78
79 if (constraint_ns > 0) { 79 if (constraint_ns > 0) {
80 constraint_ns -= td->save_state_latency_ns + 80 constraint_ns -= td->suspend_latency_ns +
81 td->stop_latency_ns + 81 td->resume_latency_ns;
82 td->start_latency_ns +
83 td->restore_state_latency_ns;
84 if (constraint_ns == 0) 82 if (constraint_ns == 0)
85 return false; 83 return false;
86 } 84 }
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index f4dd8105b024..ba4ced38efae 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -81,10 +81,8 @@ struct gpd_link {
81}; 81};
82 82
83struct gpd_timing_data { 83struct gpd_timing_data {
84 s64 stop_latency_ns; 84 s64 suspend_latency_ns;
85 s64 start_latency_ns; 85 s64 resume_latency_ns;
86 s64 save_state_latency_ns;
87 s64 restore_state_latency_ns;
88 s64 effective_constraint_ns; 86 s64 effective_constraint_ns;
89 bool constraint_changed; 87 bool constraint_changed;
90 bool cached_stop_ok; 88 bool cached_stop_ok;