Re: [PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-20 Thread Quentin Perret
On Tuesday 20 Nov 2018 at 16:25:14 (+0100), Peter Zijlstra wrote:
> On Tue, Nov 20, 2018 at 10:16:02AM +0530, Viresh Kumar wrote:
> > On 19-11-18, 14:18, Quentin Perret wrote:
> > > @@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct 
> > > sugov_cpu *sg_cpu)
> > 
> > > - if ((util + cpu_util_dl(rq)) >= max)
> > > - return max;
> > > + if (type == FREQUENCY_UTIL) {
> > > + /*
> > > +  * For frequency selection we do not make cpu_util_dl() a
> > > +  * permanent part of this sum because we want to use
> > > +  * cpu_bw_dl() later on, but we need to check if the
> > > +  * CFS+RT+DL sum is saturated (ie. no idle time) such
> > > +  * that we select f_max when there is no idle time.
> > > +  *
> > > +  * NOTE: numerical errors or stop class might cause us
> > > +  * to not quite hit saturation when we should --
> > > +  * something for later.
> > > +  */
> > > +
> > > + if ((util + cpu_util_dl(rq)) >= max)
> > > + return max;
> > > + } else {
> > > + /*
> > > +  * OTOH, for energy computation we need the estimated
> > > +  * running time, so include util_dl and ignore dl_bw.
> > > +  */
> > > + util += cpu_util_dl(rq);
> > > + if (util >= max)
> > > + return max;
> > > + }
> > 
> > Maybe write above as:
> > 
> > dl_util = cpu_util_dl(rq);
> > 
> > if ((util + dl_util) >= max)
> > return max;
> > 
> > if (type != FREQUENCY_UTIL)
> > util += dl_util;
> > 
> > 
> > as both the if/else parts were doing almost the same thing.
> 
> A little like so ?
> 
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -201,8 +201,8 @@ static unsigned int get_next_freq(struct
>  unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
> unsigned long max, enum schedutil_type type)
>  {
> + unsigned long dl_util, util, irq;
>   struct rq *rq = cpu_rq(cpu);
> - unsigned long util, irq;
>  
>   if (type == FREQUENCY_UTIL && rt_rq_is_runnable(>rt))
>   return max;
> @@ -225,30 +225,26 @@ unsigned long schedutil_freq_util(int cp
>   util = util_cfs;
>   util += cpu_util_rt(rq);
>  
> - if (type == FREQUENCY_UTIL) {
> - /*
> -  * For frequency selection we do not make cpu_util_dl() a
> -  * permanent part of this sum because we want to use
> -  * cpu_bw_dl() later on, but we need to check if the
> -  * CFS+RT+DL sum is saturated (ie. no idle time) such
> -  * that we select f_max when there is no idle time.
> -  *
> -  * NOTE: numerical errors or stop class might cause us
> -  * to not quite hit saturation when we should --
> -  * something for later.
> -  */
> -
> - if ((util + cpu_util_dl(rq)) >= max)
> - return max;
> - } else {
> - /*
> -  * OTOH, for energy computation we need the estimated
> -  * running time, so include util_dl and ignore dl_bw.
> -  */
> - util += cpu_util_dl(rq);
> - if (util >= max)
> - return max;
> - }
> + dl_util = cpu_util_dl(rq);
> +
> + /*
> +  * NOTE: numerical errors or stop class might cause us to not quite hit
> +  * saturation when we should -- something for later.
> +  */
> + if (util + dl_util > max)
> + return max;
> +
> + /*
> +  * For frequency selection we do not make cpu_util_dl() a permanent
> +  * part of this sum because we want to use cpu_bw_dl() later on, but we
> +  * need to check if the CFS+RT+DL sum is saturated (ie. no idle time)
> +  * such that we select f_max when there is no idle time.

We probably want move that paragraph to the comment above no ? Other
than that, the change LGTM.

> +  *
> +  * OTOH, for energy computation we need the estimated running time, so
> +  * do include util_dl and ignore dl_bw.
> +  */
> + if (type == ENERGY_UTIL)
> + util += dl_util;
>  
>   /*
>* There is still idle time; further improve the number by using the
> @@ -262,21 +258,18 @@ unsigned long schedutil_freq_util(int cp
>   util = scale_irq_capacity(util, irq, max);
>   util += irq;
>  
> - if (type == FREQUENCY_UTIL) {
> - /*
> -  * Bandwidth required by DEADLINE must always be granted
> -  * while, for FAIR and RT, we use blocked utilization of
> -  * IDLE CPUs as a mechanism to gracefully reduce the
> -  * frequency when no tasks show up for longer periods of
> -  * time.
> -  *
> -  * Ideally we would like to set bw_dl as min/guaranteed
> -  * freq and util 

Re: [PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-20 Thread Quentin Perret
On Tuesday 20 Nov 2018 at 16:25:14 (+0100), Peter Zijlstra wrote:
> On Tue, Nov 20, 2018 at 10:16:02AM +0530, Viresh Kumar wrote:
> > On 19-11-18, 14:18, Quentin Perret wrote:
> > > @@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct 
> > > sugov_cpu *sg_cpu)
> > 
> > > - if ((util + cpu_util_dl(rq)) >= max)
> > > - return max;
> > > + if (type == FREQUENCY_UTIL) {
> > > + /*
> > > +  * For frequency selection we do not make cpu_util_dl() a
> > > +  * permanent part of this sum because we want to use
> > > +  * cpu_bw_dl() later on, but we need to check if the
> > > +  * CFS+RT+DL sum is saturated (ie. no idle time) such
> > > +  * that we select f_max when there is no idle time.
> > > +  *
> > > +  * NOTE: numerical errors or stop class might cause us
> > > +  * to not quite hit saturation when we should --
> > > +  * something for later.
> > > +  */
> > > +
> > > + if ((util + cpu_util_dl(rq)) >= max)
> > > + return max;
> > > + } else {
> > > + /*
> > > +  * OTOH, for energy computation we need the estimated
> > > +  * running time, so include util_dl and ignore dl_bw.
> > > +  */
> > > + util += cpu_util_dl(rq);
> > > + if (util >= max)
> > > + return max;
> > > + }
> > 
> > Maybe write above as:
> > 
> > dl_util = cpu_util_dl(rq);
> > 
> > if ((util + dl_util) >= max)
> > return max;
> > 
> > if (type != FREQUENCY_UTIL)
> > util += dl_util;
> > 
> > 
> > as both the if/else parts were doing almost the same thing.
> 
> A little like so ?
> 
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -201,8 +201,8 @@ static unsigned int get_next_freq(struct
>  unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
> unsigned long max, enum schedutil_type type)
>  {
> + unsigned long dl_util, util, irq;
>   struct rq *rq = cpu_rq(cpu);
> - unsigned long util, irq;
>  
>   if (type == FREQUENCY_UTIL && rt_rq_is_runnable(>rt))
>   return max;
> @@ -225,30 +225,26 @@ unsigned long schedutil_freq_util(int cp
>   util = util_cfs;
>   util += cpu_util_rt(rq);
>  
> - if (type == FREQUENCY_UTIL) {
> - /*
> -  * For frequency selection we do not make cpu_util_dl() a
> -  * permanent part of this sum because we want to use
> -  * cpu_bw_dl() later on, but we need to check if the
> -  * CFS+RT+DL sum is saturated (ie. no idle time) such
> -  * that we select f_max when there is no idle time.
> -  *
> -  * NOTE: numerical errors or stop class might cause us
> -  * to not quite hit saturation when we should --
> -  * something for later.
> -  */
> -
> - if ((util + cpu_util_dl(rq)) >= max)
> - return max;
> - } else {
> - /*
> -  * OTOH, for energy computation we need the estimated
> -  * running time, so include util_dl and ignore dl_bw.
> -  */
> - util += cpu_util_dl(rq);
> - if (util >= max)
> - return max;
> - }
> + dl_util = cpu_util_dl(rq);
> +
> + /*
> +  * NOTE: numerical errors or stop class might cause us to not quite hit
> +  * saturation when we should -- something for later.
> +  */
> + if (util + dl_util > max)
> + return max;
> +
> + /*
> +  * For frequency selection we do not make cpu_util_dl() a permanent
> +  * part of this sum because we want to use cpu_bw_dl() later on, but we
> +  * need to check if the CFS+RT+DL sum is saturated (ie. no idle time)
> +  * such that we select f_max when there is no idle time.

We probably want move that paragraph to the comment above no ? Other
than that, the change LGTM.

> +  *
> +  * OTOH, for energy computation we need the estimated running time, so
> +  * do include util_dl and ignore dl_bw.
> +  */
> + if (type == ENERGY_UTIL)
> + util += dl_util;
>  
>   /*
>* There is still idle time; further improve the number by using the
> @@ -262,21 +258,18 @@ unsigned long schedutil_freq_util(int cp
>   util = scale_irq_capacity(util, irq, max);
>   util += irq;
>  
> - if (type == FREQUENCY_UTIL) {
> - /*
> -  * Bandwidth required by DEADLINE must always be granted
> -  * while, for FAIR and RT, we use blocked utilization of
> -  * IDLE CPUs as a mechanism to gracefully reduce the
> -  * frequency when no tasks show up for longer periods of
> -  * time.
> -  *
> -  * Ideally we would like to set bw_dl as min/guaranteed
> -  * freq and util 

Re: [PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-20 Thread Peter Zijlstra
On Tue, Nov 20, 2018 at 10:16:02AM +0530, Viresh Kumar wrote:
> On 19-11-18, 14:18, Quentin Perret wrote:
> > @@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct sugov_cpu 
> > *sg_cpu)
> 
> > -   if ((util + cpu_util_dl(rq)) >= max)
> > -   return max;
> > +   if (type == FREQUENCY_UTIL) {
> > +   /*
> > +* For frequency selection we do not make cpu_util_dl() a
> > +* permanent part of this sum because we want to use
> > +* cpu_bw_dl() later on, but we need to check if the
> > +* CFS+RT+DL sum is saturated (ie. no idle time) such
> > +* that we select f_max when there is no idle time.
> > +*
> > +* NOTE: numerical errors or stop class might cause us
> > +* to not quite hit saturation when we should --
> > +* something for later.
> > +*/
> > +
> > +   if ((util + cpu_util_dl(rq)) >= max)
> > +   return max;
> > +   } else {
> > +   /*
> > +* OTOH, for energy computation we need the estimated
> > +* running time, so include util_dl and ignore dl_bw.
> > +*/
> > +   util += cpu_util_dl(rq);
> > +   if (util >= max)
> > +   return max;
> > +   }
> 
> Maybe write above as:
> 
> dl_util = cpu_util_dl(rq);
> 
> if ((util + dl_util) >= max)
> return max;
> 
>   if (type != FREQUENCY_UTIL)
>   util += dl_util;
> 
> 
> as both the if/else parts were doing almost the same thing.

A little like so ?

--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -201,8 +201,8 @@ static unsigned int get_next_freq(struct
 unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
  unsigned long max, enum schedutil_type type)
 {
+   unsigned long dl_util, util, irq;
struct rq *rq = cpu_rq(cpu);
-   unsigned long util, irq;
 
if (type == FREQUENCY_UTIL && rt_rq_is_runnable(>rt))
return max;
@@ -225,30 +225,26 @@ unsigned long schedutil_freq_util(int cp
util = util_cfs;
util += cpu_util_rt(rq);
 
-   if (type == FREQUENCY_UTIL) {
-   /*
-* For frequency selection we do not make cpu_util_dl() a
-* permanent part of this sum because we want to use
-* cpu_bw_dl() later on, but we need to check if the
-* CFS+RT+DL sum is saturated (ie. no idle time) such
-* that we select f_max when there is no idle time.
-*
-* NOTE: numerical errors or stop class might cause us
-* to not quite hit saturation when we should --
-* something for later.
-*/
-
-   if ((util + cpu_util_dl(rq)) >= max)
-   return max;
-   } else {
-   /*
-* OTOH, for energy computation we need the estimated
-* running time, so include util_dl and ignore dl_bw.
-*/
-   util += cpu_util_dl(rq);
-   if (util >= max)
-   return max;
-   }
+   dl_util = cpu_util_dl(rq);
+
+   /*
+* NOTE: numerical errors or stop class might cause us to not quite hit
+* saturation when we should -- something for later.
+*/
+   if (util + dl_util > max)
+   return max;
+
+   /*
+* For frequency selection we do not make cpu_util_dl() a permanent
+* part of this sum because we want to use cpu_bw_dl() later on, but we
+* need to check if the CFS+RT+DL sum is saturated (ie. no idle time)
+* such that we select f_max when there is no idle time.
+*
+* OTOH, for energy computation we need the estimated running time, so
+* do include util_dl and ignore dl_bw.
+*/
+   if (type == ENERGY_UTIL)
+   util += dl_util;
 
/*
 * There is still idle time; further improve the number by using the
@@ -262,21 +258,18 @@ unsigned long schedutil_freq_util(int cp
util = scale_irq_capacity(util, irq, max);
util += irq;
 
-   if (type == FREQUENCY_UTIL) {
-   /*
-* Bandwidth required by DEADLINE must always be granted
-* while, for FAIR and RT, we use blocked utilization of
-* IDLE CPUs as a mechanism to gracefully reduce the
-* frequency when no tasks show up for longer periods of
-* time.
-*
-* Ideally we would like to set bw_dl as min/guaranteed
-* freq and util + bw_dl as requested freq. However,
-* cpufreq is not yet ready for such an interface. So,
-* we only do the latter for now.
-*/
+   /*
+* Bandwidth required by DEADLINE 

Re: [PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-20 Thread Peter Zijlstra
On Tue, Nov 20, 2018 at 10:16:02AM +0530, Viresh Kumar wrote:
> On 19-11-18, 14:18, Quentin Perret wrote:
> > @@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct sugov_cpu 
> > *sg_cpu)
> 
> > -   if ((util + cpu_util_dl(rq)) >= max)
> > -   return max;
> > +   if (type == FREQUENCY_UTIL) {
> > +   /*
> > +* For frequency selection we do not make cpu_util_dl() a
> > +* permanent part of this sum because we want to use
> > +* cpu_bw_dl() later on, but we need to check if the
> > +* CFS+RT+DL sum is saturated (ie. no idle time) such
> > +* that we select f_max when there is no idle time.
> > +*
> > +* NOTE: numerical errors or stop class might cause us
> > +* to not quite hit saturation when we should --
> > +* something for later.
> > +*/
> > +
> > +   if ((util + cpu_util_dl(rq)) >= max)
> > +   return max;
> > +   } else {
> > +   /*
> > +* OTOH, for energy computation we need the estimated
> > +* running time, so include util_dl and ignore dl_bw.
> > +*/
> > +   util += cpu_util_dl(rq);
> > +   if (util >= max)
> > +   return max;
> > +   }
> 
> Maybe write above as:
> 
> dl_util = cpu_util_dl(rq);
> 
> if ((util + dl_util) >= max)
> return max;
> 
>   if (type != FREQUENCY_UTIL)
>   util += dl_util;
> 
> 
> as both the if/else parts were doing almost the same thing.

A little like so ?

--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -201,8 +201,8 @@ static unsigned int get_next_freq(struct
 unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
  unsigned long max, enum schedutil_type type)
 {
+   unsigned long dl_util, util, irq;
struct rq *rq = cpu_rq(cpu);
-   unsigned long util, irq;
 
if (type == FREQUENCY_UTIL && rt_rq_is_runnable(>rt))
return max;
@@ -225,30 +225,26 @@ unsigned long schedutil_freq_util(int cp
util = util_cfs;
util += cpu_util_rt(rq);
 
-   if (type == FREQUENCY_UTIL) {
-   /*
-* For frequency selection we do not make cpu_util_dl() a
-* permanent part of this sum because we want to use
-* cpu_bw_dl() later on, but we need to check if the
-* CFS+RT+DL sum is saturated (ie. no idle time) such
-* that we select f_max when there is no idle time.
-*
-* NOTE: numerical errors or stop class might cause us
-* to not quite hit saturation when we should --
-* something for later.
-*/
-
-   if ((util + cpu_util_dl(rq)) >= max)
-   return max;
-   } else {
-   /*
-* OTOH, for energy computation we need the estimated
-* running time, so include util_dl and ignore dl_bw.
-*/
-   util += cpu_util_dl(rq);
-   if (util >= max)
-   return max;
-   }
+   dl_util = cpu_util_dl(rq);
+
+   /*
+* NOTE: numerical errors or stop class might cause us to not quite hit
+* saturation when we should -- something for later.
+*/
+   if (util + dl_util > max)
+   return max;
+
+   /*
+* For frequency selection we do not make cpu_util_dl() a permanent
+* part of this sum because we want to use cpu_bw_dl() later on, but we
+* need to check if the CFS+RT+DL sum is saturated (ie. no idle time)
+* such that we select f_max when there is no idle time.
+*
+* OTOH, for energy computation we need the estimated running time, so
+* do include util_dl and ignore dl_bw.
+*/
+   if (type == ENERGY_UTIL)
+   util += dl_util;
 
/*
 * There is still idle time; further improve the number by using the
@@ -262,21 +258,18 @@ unsigned long schedutil_freq_util(int cp
util = scale_irq_capacity(util, irq, max);
util += irq;
 
-   if (type == FREQUENCY_UTIL) {
-   /*
-* Bandwidth required by DEADLINE must always be granted
-* while, for FAIR and RT, we use blocked utilization of
-* IDLE CPUs as a mechanism to gracefully reduce the
-* frequency when no tasks show up for longer periods of
-* time.
-*
-* Ideally we would like to set bw_dl as min/guaranteed
-* freq and util + bw_dl as requested freq. However,
-* cpufreq is not yet ready for such an interface. So,
-* we only do the latter for now.
-*/
+   /*
+* Bandwidth required by DEADLINE 

Re: [PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-19 Thread Viresh Kumar
On 19-11-18, 14:18, Quentin Perret wrote:
> @@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct sugov_cpu 
> *sg_cpu)

> - if ((util + cpu_util_dl(rq)) >= max)
> - return max;
> + if (type == FREQUENCY_UTIL) {
> + /*
> +  * For frequency selection we do not make cpu_util_dl() a
> +  * permanent part of this sum because we want to use
> +  * cpu_bw_dl() later on, but we need to check if the
> +  * CFS+RT+DL sum is saturated (ie. no idle time) such
> +  * that we select f_max when there is no idle time.
> +  *
> +  * NOTE: numerical errors or stop class might cause us
> +  * to not quite hit saturation when we should --
> +  * something for later.
> +  */
> +
> + if ((util + cpu_util_dl(rq)) >= max)
> + return max;
> + } else {
> + /*
> +  * OTOH, for energy computation we need the estimated
> +  * running time, so include util_dl and ignore dl_bw.
> +  */
> + util += cpu_util_dl(rq);
> + if (util >= max)
> + return max;
> + }

Maybe write above as:

dl_util = cpu_util_dl(rq);

if ((util + dl_util) >= max)
return max;

if (type != FREQUENCY_UTIL)
util += dl_util;


as both the if/else parts were doing almost the same thing.

-- 
viresh


Re: [PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-19 Thread Viresh Kumar
On 19-11-18, 14:18, Quentin Perret wrote:
> @@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct sugov_cpu 
> *sg_cpu)

> - if ((util + cpu_util_dl(rq)) >= max)
> - return max;
> + if (type == FREQUENCY_UTIL) {
> + /*
> +  * For frequency selection we do not make cpu_util_dl() a
> +  * permanent part of this sum because we want to use
> +  * cpu_bw_dl() later on, but we need to check if the
> +  * CFS+RT+DL sum is saturated (ie. no idle time) such
> +  * that we select f_max when there is no idle time.
> +  *
> +  * NOTE: numerical errors or stop class might cause us
> +  * to not quite hit saturation when we should --
> +  * something for later.
> +  */
> +
> + if ((util + cpu_util_dl(rq)) >= max)
> + return max;
> + } else {
> + /*
> +  * OTOH, for energy computation we need the estimated
> +  * running time, so include util_dl and ignore dl_bw.
> +  */
> + util += cpu_util_dl(rq);
> + if (util >= max)
> + return max;
> + }

Maybe write above as:

dl_util = cpu_util_dl(rq);

if ((util + dl_util) >= max)
return max;

if (type != FREQUENCY_UTIL)
util += dl_util;


as both the if/else parts were doing almost the same thing.

-- 
viresh


[PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-19 Thread Quentin Perret
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.

In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.

As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.

Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Suggested-by: Peter Zijlstra 
Signed-off-by: Quentin Perret 
---
 include/linux/sched/cpufreq.h|  6 +++
 kernel/sched/cpufreq_schedutil.c | 92 +---
 kernel/sched/sched.h | 30 +++
 3 files changed, 97 insertions(+), 31 deletions(-)

diff --git a/include/linux/sched/cpufreq.h b/include/linux/sched/cpufreq.h
index 59667444669f..afa940cd50dc 100644
--- a/include/linux/sched/cpufreq.h
+++ b/include/linux/sched/cpufreq.h
@@ -20,6 +20,12 @@ void cpufreq_add_update_util_hook(int cpu, struct 
update_util_data *data,
void (*func)(struct update_util_data *data, u64 time,
unsigned int flags));
 void cpufreq_remove_update_util_hook(int cpu);
+
+static inline unsigned long map_util_freq(unsigned long util,
+   unsigned long freq, unsigned long cap)
+{
+   return (freq + (freq >> 2)) * util / cap;
+}
 #endif /* CONFIG_CPU_FREQ */
 
 #endif /* _LINUX_SCHED_CPUFREQ_H */
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 3fffad3bc8a8..105cf70fcb69 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -13,6 +13,7 @@
 
 #include "sched.h"
 
+#include 
 #include 
 
 struct sugov_tunables {
@@ -167,7 +168,7 @@ static unsigned int get_next_freq(struct sugov_policy 
*sg_policy,
unsigned int freq = arch_scale_freq_invariant() ?
policy->cpuinfo.max_freq : policy->cur;
 
-   freq = (freq + (freq >> 2)) * util / max;
+   freq = map_util_freq(util, freq, max);
 
if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
return sg_policy->next_freq;
@@ -197,15 +198,13 @@ static unsigned int get_next_freq(struct sugov_policy 
*sg_policy,
  * based on the task model parameters and gives the minimal utilization
  * required to meet deadlines.
  */
-static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu)
+unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
+ unsigned long max, enum schedutil_type type)
 {
-   struct rq *rq = cpu_rq(sg_cpu->cpu);
-   unsigned long util, irq, max;
-
-   sg_cpu->max = max = arch_scale_cpu_capacity(NULL, sg_cpu->cpu);
-   sg_cpu->bw_dl = cpu_bw_dl(rq);
+   struct rq *rq = cpu_rq(cpu);
+   unsigned long util, irq;
 
-   if (rt_rq_is_runnable(>rt))
+   if (type == FREQUENCY_UTIL && rt_rq_is_runnable(>rt))
return max;
 
/*
@@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct sugov_cpu 
*sg_cpu)
 * utilization (PELT windows are synchronized) we can directly add them
 * to obtain the CPU's actual utilization.
 */
-   util = cpu_util_cfs(rq);
+   util = util_cfs;
util += cpu_util_rt(rq);
 
-   /*
-* We do not make cpu_util_dl() a permanent part of this sum because we
-* want to use cpu_bw_dl() later on, but we need to check if the
-* CFS+RT+DL sum is saturated (ie. no idle time) such that we select
-* f_max when there is no idle time.
-*
-* NOTE: numerical errors or stop class might cause us to not quite hit
-* saturation when we should -- something for later.
-*/
-   if ((util + cpu_util_dl(rq)) >= max)
-   return max;
+   if (type == FREQUENCY_UTIL) {
+   /*
+* For frequency selection we do not make cpu_util_dl() a
+* permanent part of this sum because we want to use
+* cpu_bw_dl() later on, but we need to check if the
+* CFS+RT+DL sum is saturated (ie. no idle time) such
+* that we select f_max when there is no idle time.
+*
+

[PATCH v9 02/15] sched/cpufreq: Prepare schedutil for Energy Aware Scheduling

2018-11-19 Thread Quentin Perret
Schedutil requests frequency by aggregating utilization signals from
the scheduler (CFS, RT, DL, IRQ) and applying a 25% margin on top of
them. Since Energy Aware Scheduling (EAS) needs to be able to predict
the frequency requests, it needs to forecast the decisions made by the
governor.

In order to prepare the introduction of EAS, introduce
schedutil_freq_util() to centralize the aforementioned signal
aggregation and make it available to both schedutil and EAS. Since
frequency selection and energy estimation still need to deal with RT and
DL signals slightly differently, schedutil_freq_util() is called with a
different 'type' parameter in those two contexts, and returns an
aggregated utilization signal accordingly. While at it, introduce the
map_util_freq() function which is designed to make schedutil's 25%
margin usable easily for both sugov and EAS.

As EAS will be able to predict schedutil's frequency requests more
accurately than any other governor by design, it'd be sensible to make
sure EAS cannot be used without schedutil. This will be done later, once
EAS has actually been introduced.

Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Suggested-by: Peter Zijlstra 
Signed-off-by: Quentin Perret 
---
 include/linux/sched/cpufreq.h|  6 +++
 kernel/sched/cpufreq_schedutil.c | 92 +---
 kernel/sched/sched.h | 30 +++
 3 files changed, 97 insertions(+), 31 deletions(-)

diff --git a/include/linux/sched/cpufreq.h b/include/linux/sched/cpufreq.h
index 59667444669f..afa940cd50dc 100644
--- a/include/linux/sched/cpufreq.h
+++ b/include/linux/sched/cpufreq.h
@@ -20,6 +20,12 @@ void cpufreq_add_update_util_hook(int cpu, struct 
update_util_data *data,
void (*func)(struct update_util_data *data, u64 time,
unsigned int flags));
 void cpufreq_remove_update_util_hook(int cpu);
+
+static inline unsigned long map_util_freq(unsigned long util,
+   unsigned long freq, unsigned long cap)
+{
+   return (freq + (freq >> 2)) * util / cap;
+}
 #endif /* CONFIG_CPU_FREQ */
 
 #endif /* _LINUX_SCHED_CPUFREQ_H */
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 3fffad3bc8a8..105cf70fcb69 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -13,6 +13,7 @@
 
 #include "sched.h"
 
+#include 
 #include 
 
 struct sugov_tunables {
@@ -167,7 +168,7 @@ static unsigned int get_next_freq(struct sugov_policy 
*sg_policy,
unsigned int freq = arch_scale_freq_invariant() ?
policy->cpuinfo.max_freq : policy->cur;
 
-   freq = (freq + (freq >> 2)) * util / max;
+   freq = map_util_freq(util, freq, max);
 
if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
return sg_policy->next_freq;
@@ -197,15 +198,13 @@ static unsigned int get_next_freq(struct sugov_policy 
*sg_policy,
  * based on the task model parameters and gives the minimal utilization
  * required to meet deadlines.
  */
-static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu)
+unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
+ unsigned long max, enum schedutil_type type)
 {
-   struct rq *rq = cpu_rq(sg_cpu->cpu);
-   unsigned long util, irq, max;
-
-   sg_cpu->max = max = arch_scale_cpu_capacity(NULL, sg_cpu->cpu);
-   sg_cpu->bw_dl = cpu_bw_dl(rq);
+   struct rq *rq = cpu_rq(cpu);
+   unsigned long util, irq;
 
-   if (rt_rq_is_runnable(>rt))
+   if (type == FREQUENCY_UTIL && rt_rq_is_runnable(>rt))
return max;
 
/*
@@ -223,20 +222,33 @@ static unsigned long sugov_get_util(struct sugov_cpu 
*sg_cpu)
 * utilization (PELT windows are synchronized) we can directly add them
 * to obtain the CPU's actual utilization.
 */
-   util = cpu_util_cfs(rq);
+   util = util_cfs;
util += cpu_util_rt(rq);
 
-   /*
-* We do not make cpu_util_dl() a permanent part of this sum because we
-* want to use cpu_bw_dl() later on, but we need to check if the
-* CFS+RT+DL sum is saturated (ie. no idle time) such that we select
-* f_max when there is no idle time.
-*
-* NOTE: numerical errors or stop class might cause us to not quite hit
-* saturation when we should -- something for later.
-*/
-   if ((util + cpu_util_dl(rq)) >= max)
-   return max;
+   if (type == FREQUENCY_UTIL) {
+   /*
+* For frequency selection we do not make cpu_util_dl() a
+* permanent part of this sum because we want to use
+* cpu_bw_dl() later on, but we need to check if the
+* CFS+RT+DL sum is saturated (ie. no idle time) such
+* that we select f_max when there is no idle time.
+*
+