summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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