aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-08-16 16:14:55 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-08-16 16:14:55 -0400
commit58919e83c85c3a3c5fb34025dc0e95ddd998c478 (patch)
tree04aff6a76eccc25de1f205973bf72aaa1570f581
parent694d0d0bb2030d2e36df73e2d23d5770511dbc8d (diff)
cpufreq / sched: Pass flags to cpufreq_update_util()
It is useful to know the reason why cpufreq_update_util() has just been called and that can be passed as flags to cpufreq_update_util() and to the ->func() callback in struct update_util_data. However, doing that in addition to passing the util and max arguments they already take would be clumsy, so avoid it. Instead, use the observation that the schedutil governor is part of the scheduler proper, so it can access scheduler data directly. This allows the util and max arguments of cpufreq_update_util() and the ->func() callback in struct update_util_data to be replaced with a flags one, but schedutil has to be modified to follow. Thus make the schedutil governor obtain the CFS utilization information from the scheduler and use the "RT" and "DL" flags instead of the special utilization value of ULONG_MAX to track updates from the RT and DL sched classes. Make it non-modular too to avoid having to export scheduler variables to modules at large. Next, update all of the other users of cpufreq_update_util() and the ->func() callback in struct update_util_data accordingly. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/cpufreq/Kconfig5
-rw-r--r--drivers/cpufreq/cpufreq_governor.c2
-rw-r--r--drivers/cpufreq/intel_pstate.c2
-rw-r--r--include/linux/sched.h12
-rw-r--r--kernel/sched/cpufreq.c2
-rw-r--r--kernel/sched/cpufreq_schedutil.c67
-rw-r--r--kernel/sched/deadline.c4
-rw-r--r--kernel/sched/fair.c12
-rw-r--r--kernel/sched/rt.c4
-rw-r--r--kernel/sched/sched.h31
10 files changed, 67 insertions, 74 deletions
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 74919aa81dcb..4dc95250cf4e 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -194,7 +194,7 @@ config CPU_FREQ_GOV_CONSERVATIVE
194 If in doubt, say N. 194 If in doubt, say N.
195 195
196config CPU_FREQ_GOV_SCHEDUTIL 196config CPU_FREQ_GOV_SCHEDUTIL
197 tristate "'schedutil' cpufreq policy governor" 197 bool "'schedutil' cpufreq policy governor"
198 depends on CPU_FREQ && SMP 198 depends on CPU_FREQ && SMP
199 select CPU_FREQ_GOV_ATTR_SET 199 select CPU_FREQ_GOV_ATTR_SET
200 select IRQ_WORK 200 select IRQ_WORK
@@ -208,9 +208,6 @@ config CPU_FREQ_GOV_SCHEDUTIL
208 frequency tipping point is at utilization/capacity equal to 80% in 208 frequency tipping point is at utilization/capacity equal to 80% in
209 both cases. 209 both cases.
210 210
211 To compile this driver as a module, choose M here: the module will
212 be called cpufreq_schedutil.
213
214 If in doubt, say N. 211 If in doubt, say N.
215 212
216comment "CPU frequency scaling drivers" 213comment "CPU frequency scaling drivers"
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index e415349ab31b..642dd0f183a8 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -260,7 +260,7 @@ static void dbs_irq_work(struct irq_work *irq_work)
260} 260}
261 261
262static void dbs_update_util_handler(struct update_util_data *data, u64 time, 262static void dbs_update_util_handler(struct update_util_data *data, u64 time,
263 unsigned long util, unsigned long max) 263 unsigned int flags)
264{ 264{
265 struct cpu_dbs_info *cdbs = container_of(data, struct cpu_dbs_info, update_util); 265 struct cpu_dbs_info *cdbs = container_of(data, struct cpu_dbs_info, update_util);
266 struct policy_dbs_info *policy_dbs = cdbs->policy_dbs; 266 struct policy_dbs_info *policy_dbs = cdbs->policy_dbs;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index be9eade147f2..bdbe9369146b 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1329,7 +1329,7 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
1329} 1329}
1330 1330
1331static void intel_pstate_update_util(struct update_util_data *data, u64 time, 1331static void intel_pstate_update_util(struct update_util_data *data, u64 time,
1332 unsigned long util, unsigned long max) 1332 unsigned int flags)
1333{ 1333{
1334 struct cpudata *cpu = container_of(data, struct cpudata, update_util); 1334 struct cpudata *cpu = container_of(data, struct cpudata, update_util);
1335 u64 delta_ns = time - cpu->sample.time; 1335 u64 delta_ns = time - cpu->sample.time;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 62c68e513e39..b0fa726b7f31 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -3469,15 +3469,19 @@ static inline unsigned long rlimit_max(unsigned int limit)
3469 return task_rlimit_max(current, limit); 3469 return task_rlimit_max(current, limit);
3470} 3470}
3471 3471
3472#define SCHED_CPUFREQ_RT (1U << 0)
3473#define SCHED_CPUFREQ_DL (1U << 1)
3474
3475#define SCHED_CPUFREQ_RT_DL (SCHED_CPUFREQ_RT | SCHED_CPUFREQ_DL)
3476
3472#ifdef CONFIG_CPU_FREQ 3477#ifdef CONFIG_CPU_FREQ
3473struct update_util_data { 3478struct update_util_data {
3474 void (*func)(struct update_util_data *data, 3479 void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
3475 u64 time, unsigned long util, unsigned long max);
3476}; 3480};
3477 3481
3478void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data, 3482void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
3479 void (*func)(struct update_util_data *data, u64 time, 3483 void (*func)(struct update_util_data *data, u64 time,
3480 unsigned long util, unsigned long max)); 3484 unsigned int flags));
3481void cpufreq_remove_update_util_hook(int cpu); 3485void cpufreq_remove_update_util_hook(int cpu);
3482#endif /* CONFIG_CPU_FREQ */ 3486#endif /* CONFIG_CPU_FREQ */
3483 3487
diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c
index 1141954e73b4..dbc51442ecbc 100644
--- a/kernel/sched/cpufreq.c
+++ b/kernel/sched/cpufreq.c
@@ -33,7 +33,7 @@ DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
33 */ 33 */
34void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data, 34void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
35 void (*func)(struct update_util_data *data, u64 time, 35 void (*func)(struct update_util_data *data, u64 time,
36 unsigned long util, unsigned long max)) 36 unsigned int flags))
37{ 37{
38 if (WARN_ON(!data || !func)) 38 if (WARN_ON(!data || !func))
39 return; 39 return;
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index a84641b222c1..60d985f4dc47 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -12,7 +12,6 @@
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 13
14#include <linux/cpufreq.h> 14#include <linux/cpufreq.h>
15#include <linux/module.h>
16#include <linux/slab.h> 15#include <linux/slab.h>
17#include <trace/events/power.h> 16#include <trace/events/power.h>
18 17
@@ -53,6 +52,7 @@ struct sugov_cpu {
53 unsigned long util; 52 unsigned long util;
54 unsigned long max; 53 unsigned long max;
55 u64 last_update; 54 u64 last_update;
55 unsigned int flags;
56}; 56};
57 57
58static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu); 58static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu);
@@ -144,24 +144,39 @@ static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util,
144 return cpufreq_driver_resolve_freq(policy, freq); 144 return cpufreq_driver_resolve_freq(policy, freq);
145} 145}
146 146
147static void sugov_get_util(unsigned long *util, unsigned long *max)
148{
149 struct rq *rq = this_rq();
150 unsigned long cfs_max = rq->cpu_capacity_orig;
151
152 *util = min(rq->cfs.avg.util_avg, cfs_max);
153 *max = cfs_max;
154}
155
147static void sugov_update_single(struct update_util_data *hook, u64 time, 156static void sugov_update_single(struct update_util_data *hook, u64 time,
148 unsigned long util, unsigned long max) 157 unsigned int flags)
149{ 158{
150 struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); 159 struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
151 struct sugov_policy *sg_policy = sg_cpu->sg_policy; 160 struct sugov_policy *sg_policy = sg_cpu->sg_policy;
152 struct cpufreq_policy *policy = sg_policy->policy; 161 struct cpufreq_policy *policy = sg_policy->policy;
162 unsigned long util, max;
153 unsigned int next_f; 163 unsigned int next_f;
154 164
155 if (!sugov_should_update_freq(sg_policy, time)) 165 if (!sugov_should_update_freq(sg_policy, time))
156 return; 166 return;
157 167
158 next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq : 168 if (flags & SCHED_CPUFREQ_RT_DL) {
159 get_next_freq(sg_cpu, util, max); 169 next_f = policy->cpuinfo.max_freq;
170 } else {
171 sugov_get_util(&util, &max);
172 next_f = get_next_freq(sg_cpu, util, max);
173 }
160 sugov_update_commit(sg_policy, time, next_f); 174 sugov_update_commit(sg_policy, time, next_f);
161} 175}
162 176
163static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, 177static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
164 unsigned long util, unsigned long max) 178 unsigned long util, unsigned long max,
179 unsigned int flags)
165{ 180{
166 struct sugov_policy *sg_policy = sg_cpu->sg_policy; 181 struct sugov_policy *sg_policy = sg_cpu->sg_policy;
167 struct cpufreq_policy *policy = sg_policy->policy; 182 struct cpufreq_policy *policy = sg_policy->policy;
@@ -169,7 +184,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
169 u64 last_freq_update_time = sg_policy->last_freq_update_time; 184 u64 last_freq_update_time = sg_policy->last_freq_update_time;
170 unsigned int j; 185 unsigned int j;
171 186
172 if (util == ULONG_MAX) 187 if (flags & SCHED_CPUFREQ_RT_DL)
173 return max_f; 188 return max_f;
174 189
175 for_each_cpu(j, policy->cpus) { 190 for_each_cpu(j, policy->cpus) {
@@ -192,10 +207,10 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
192 if (delta_ns > TICK_NSEC) 207 if (delta_ns > TICK_NSEC)
193 continue; 208 continue;
194 209
195 j_util = j_sg_cpu->util; 210 if (j_sg_cpu->flags & SCHED_CPUFREQ_RT_DL)
196 if (j_util == ULONG_MAX)
197 return max_f; 211 return max_f;
198 212
213 j_util = j_sg_cpu->util;
199 j_max = j_sg_cpu->max; 214 j_max = j_sg_cpu->max;
200 if (j_util * max > j_max * util) { 215 if (j_util * max > j_max * util) {
201 util = j_util; 216 util = j_util;
@@ -207,20 +222,24 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
207} 222}
208 223
209static void sugov_update_shared(struct update_util_data *hook, u64 time, 224static void sugov_update_shared(struct update_util_data *hook, u64 time,
210 unsigned long util, unsigned long max) 225 unsigned int flags)
211{ 226{
212 struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); 227 struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
213 struct sugov_policy *sg_policy = sg_cpu->sg_policy; 228 struct sugov_policy *sg_policy = sg_cpu->sg_policy;
229 unsigned long util, max;
214 unsigned int next_f; 230 unsigned int next_f;
215 231
232 sugov_get_util(&util, &max);
233
216 raw_spin_lock(&sg_policy->update_lock); 234 raw_spin_lock(&sg_policy->update_lock);
217 235
218 sg_cpu->util = util; 236 sg_cpu->util = util;
219 sg_cpu->max = max; 237 sg_cpu->max = max;
238 sg_cpu->flags = flags;
220 sg_cpu->last_update = time; 239 sg_cpu->last_update = time;
221 240
222 if (sugov_should_update_freq(sg_policy, time)) { 241 if (sugov_should_update_freq(sg_policy, time)) {
223 next_f = sugov_next_freq_shared(sg_cpu, util, max); 242 next_f = sugov_next_freq_shared(sg_cpu, util, max, flags);
224 sugov_update_commit(sg_policy, time, next_f); 243 sugov_update_commit(sg_policy, time, next_f);
225 } 244 }
226 245
@@ -444,8 +463,9 @@ static int sugov_start(struct cpufreq_policy *policy)
444 463
445 sg_cpu->sg_policy = sg_policy; 464 sg_cpu->sg_policy = sg_policy;
446 if (policy_is_shared(policy)) { 465 if (policy_is_shared(policy)) {
447 sg_cpu->util = ULONG_MAX; 466 sg_cpu->util = 0;
448 sg_cpu->max = 0; 467 sg_cpu->max = 0;
468 sg_cpu->flags = SCHED_CPUFREQ_RT;
449 sg_cpu->last_update = 0; 469 sg_cpu->last_update = 0;
450 sg_cpu->cached_raw_freq = 0; 470 sg_cpu->cached_raw_freq = 0;
451 cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, 471 cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
@@ -495,28 +515,15 @@ static struct cpufreq_governor schedutil_gov = {
495 .limits = sugov_limits, 515 .limits = sugov_limits,
496}; 516};
497 517
498static int __init sugov_module_init(void)
499{
500 return cpufreq_register_governor(&schedutil_gov);
501}
502
503static void __exit sugov_module_exit(void)
504{
505 cpufreq_unregister_governor(&schedutil_gov);
506}
507
508MODULE_AUTHOR("Rafael J. Wysocki <rafael.j.wysocki@intel.com>");
509MODULE_DESCRIPTION("Utilization-based CPU frequency selection");
510MODULE_LICENSE("GPL");
511
512#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL 518#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
513struct cpufreq_governor *cpufreq_default_governor(void) 519struct cpufreq_governor *cpufreq_default_governor(void)
514{ 520{
515 return &schedutil_gov; 521 return &schedutil_gov;
516} 522}
517
518fs_initcall(sugov_module_init);
519#else
520module_init(sugov_module_init);
521#endif 523#endif
522module_exit(sugov_module_exit); 524
525static int __init sugov_register(void)
526{
527 return cpufreq_register_governor(&schedutil_gov);
528}
529fs_initcall(sugov_register);
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 1ce8867283dc..4464cc3e4f3d 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -735,9 +735,9 @@ static void update_curr_dl(struct rq *rq)
735 return; 735 return;
736 } 736 }
737 737
738 /* kick cpufreq (see the comment in linux/cpufreq.h). */ 738 /* kick cpufreq (see the comment in kernel/sched/sched.h). */
739 if (cpu_of(rq) == smp_processor_id()) 739 if (cpu_of(rq) == smp_processor_id())
740 cpufreq_trigger_update(rq_clock(rq)); 740 cpufreq_update_util(rq_clock(rq), SCHED_CPUFREQ_DL);
741 741
742 schedstat_set(curr->se.statistics.exec_max, 742 schedstat_set(curr->se.statistics.exec_max,
743 max(curr->se.statistics.exec_max, delta_exec)); 743 max(curr->se.statistics.exec_max, delta_exec));
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 039de34f1521..f91fa5796e50 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2875,11 +2875,8 @@ static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force) {}
2875 2875
2876static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq) 2876static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq)
2877{ 2877{
2878 struct rq *rq = rq_of(cfs_rq); 2878 if (&this_rq()->cfs == cfs_rq) {
2879 int cpu = cpu_of(rq); 2879 struct rq *rq = rq_of(cfs_rq);
2880
2881 if (cpu == smp_processor_id() && &rq->cfs == cfs_rq) {
2882 unsigned long max = rq->cpu_capacity_orig;
2883 2880
2884 /* 2881 /*
2885 * There are a few boundary cases this might miss but it should 2882 * There are a few boundary cases this might miss but it should
@@ -2897,8 +2894,7 @@ static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq)
2897 * 2894 *
2898 * See cpu_util(). 2895 * See cpu_util().
2899 */ 2896 */
2900 cpufreq_update_util(rq_clock(rq), 2897 cpufreq_update_util(rq_clock(rq), 0);
2901 min(cfs_rq->avg.util_avg, max), max);
2902 } 2898 }
2903} 2899}
2904 2900
@@ -3162,7 +3158,7 @@ static inline void update_load_avg(struct sched_entity *se, int not_used)
3162 struct cfs_rq *cfs_rq = cfs_rq_of(se); 3158 struct cfs_rq *cfs_rq = cfs_rq_of(se);
3163 struct rq *rq = rq_of(cfs_rq); 3159 struct rq *rq = rq_of(cfs_rq);
3164 3160
3165 cpufreq_trigger_update(rq_clock(rq)); 3161 cpufreq_update_util(rq_clock(rq), 0);
3166} 3162}
3167 3163
3168static inline void 3164static inline void
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index d5690b722691..8a9cd9ba5153 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -957,9 +957,9 @@ static void update_curr_rt(struct rq *rq)
957 if (unlikely((s64)delta_exec <= 0)) 957 if (unlikely((s64)delta_exec <= 0))
958 return; 958 return;
959 959
960 /* Kick cpufreq (see the comment in linux/cpufreq.h). */ 960 /* Kick cpufreq (see the comment in kernel/sched/sched.h). */
961 if (cpu_of(rq) == smp_processor_id()) 961 if (cpu_of(rq) == smp_processor_id())
962 cpufreq_trigger_update(rq_clock(rq)); 962 cpufreq_update_util(rq_clock(rq), SCHED_CPUFREQ_RT);
963 963
964 schedstat_set(curr->se.statistics.exec_max, 964 schedstat_set(curr->se.statistics.exec_max,
965 max(curr->se.statistics.exec_max, delta_exec)); 965 max(curr->se.statistics.exec_max, delta_exec));
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c64fc5114004..82fc5542708c 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1764,26 +1764,12 @@ DECLARE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
1764/** 1764/**
1765 * cpufreq_update_util - Take a note about CPU utilization changes. 1765 * cpufreq_update_util - Take a note about CPU utilization changes.
1766 * @time: Current time. 1766 * @time: Current time.
1767 * @util: Current utilization. 1767 * @flags: Update reason flags.
1768 * @max: Utilization ceiling.
1769 * 1768 *
1770 * This function is called by the scheduler on every invocation of 1769 * This function is called by the scheduler on the CPU whose utilization is
1771 * update_load_avg() on the CPU whose utilization is being updated. 1770 * being updated.
1772 * 1771 *
1773 * It can only be called from RCU-sched read-side critical sections. 1772 * It can only be called from RCU-sched read-side critical sections.
1774 */
1775static inline void cpufreq_update_util(u64 time, unsigned long util, unsigned long max)
1776{
1777 struct update_util_data *data;
1778
1779 data = rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data));
1780 if (data)
1781 data->func(data, time, util, max);
1782}
1783
1784/**
1785 * cpufreq_trigger_update - Trigger CPU performance state evaluation if needed.
1786 * @time: Current time.
1787 * 1773 *
1788 * The way cpufreq is currently arranged requires it to evaluate the CPU 1774 * The way cpufreq is currently arranged requires it to evaluate the CPU
1789 * performance state (frequency/voltage) on a regular basis to prevent it from 1775 * performance state (frequency/voltage) on a regular basis to prevent it from
@@ -1797,13 +1783,16 @@ static inline void cpufreq_update_util(u64 time, unsigned long util, unsigned lo
1797 * but that really is a band-aid. Going forward it should be replaced with 1783 * but that really is a band-aid. Going forward it should be replaced with
1798 * solutions targeted more specifically at RT and DL tasks. 1784 * solutions targeted more specifically at RT and DL tasks.
1799 */ 1785 */
1800static inline void cpufreq_trigger_update(u64 time) 1786static inline void cpufreq_update_util(u64 time, unsigned int flags)
1801{ 1787{
1802 cpufreq_update_util(time, ULONG_MAX, 0); 1788 struct update_util_data *data;
1789
1790 data = rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data));
1791 if (data)
1792 data->func(data, time, flags);
1803} 1793}
1804#else 1794#else
1805static inline void cpufreq_update_util(u64 time, unsigned long util, unsigned long max) {} 1795static inline void cpufreq_update_util(u64 time, unsigned int flags) {}
1806static inline void cpufreq_trigger_update(u64 time) {}
1807#endif /* CONFIG_CPU_FREQ */ 1796#endif /* CONFIG_CPU_FREQ */
1808 1797
1809#ifdef arch_scale_freq_capacity 1798#ifdef arch_scale_freq_capacity