linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] cpufreq / sched: iowait boost in intel_pstate and schedutil
@ 2016-09-09 21:57 Rafael J. Wysocki
  2016-09-09 21:59 ` [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition Rafael J. Wysocki
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2016-09-09 21:57 UTC (permalink / raw)
  To: Linux PM list
  Cc: Linux Kernel Mailing List, Srinivas Pandruvada, Peter Zijlstra,
	Viresh Kumar, Ingo Molnar, Vincent Guittot, Morten Rasmussen,
	Juri Lelli, Dietmar Eggemann, Steve Muckle, Doug Smythies

Hi Everyone,

This is a new iteration of the "iowait boost" series.

The first two patches (adding the SCHED_CPUFREQ_IOWAIT flag and changing
schedutil to use it) don't seem to be controversial, so they go unchanged
(not RFC any more though) and the only difference is the intel_pstate
part.

Since we still get some unconclusive results with the new algorithm
for Core processors, patch [3/3] in this series modifies the Atom
algorithm to use SCHED_CPUFREQ_IOWAIT instead of the get_cpu_iowait_time_us()
interface (which isn't particularly reliable) as the first step.

Going forward we would like to modify intel_pstate to select P-states
proportional to utilization (with IOwait boosting and possibly some other
tweaks) on all processors, but there still are some factors to determine
in that area, so let's make this simple change to start with.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition
  2016-09-09 21:57 [PATCH 0/3] cpufreq / sched: iowait boost in intel_pstate and schedutil Rafael J. Wysocki
@ 2016-09-09 21:59 ` Rafael J. Wysocki
  2016-09-13  7:34   ` Peter Zijlstra
  2016-09-09 22:00 ` [Resend][PATCH 2/3] cpufreq: schedutil: Add iowait boosting Rafael J. Wysocki
  2016-09-09 22:02 ` [PATCH 3/3] cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm Rafael J. Wysocki
  2 siblings, 1 reply; 7+ messages in thread
From: Rafael J. Wysocki @ 2016-09-09 21:59 UTC (permalink / raw)
  To: Linux PM list
  Cc: Linux Kernel Mailing List, Srinivas Pandruvada, Peter Zijlstra,
	Viresh Kumar, Ingo Molnar, Vincent Guittot, Morten Rasmussen,
	Juri Lelli, Dietmar Eggemann, Steve Muckle, Doug Smythies

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Testing indicates that it is possible to improve performace
significantly without increasing energy consumption too much by
teaching cpufreq governors to bump up the CPU performance level if
the in_iowait flag is set for the task in enqueue_task_fair().

For this purpose, define a new cpufreq_update_util() flag
SCHED_CPUFREQ_IOWAIT and modify enqueue_task_fair() to pass that
flag to cpufreq_update_util() in the in_iowait case.  That generally
requires cpufreq_update_util() to be called directly from there,
because update_load_avg() may not be invoked in that case.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Looks-good-to: Steve Muckle <smuckle@linaro.org>
---
 include/linux/sched.h |    1 +
 kernel/sched/fair.c   |    8 ++++++++
 2 files changed, 9 insertions(+)

Index: linux-pm/kernel/sched/fair.c
===================================================================
--- linux-pm.orig/kernel/sched/fair.c
+++ linux-pm/kernel/sched/fair.c
@@ -4500,6 +4500,14 @@ enqueue_task_fair(struct rq *rq, struct
 	struct cfs_rq *cfs_rq;
 	struct sched_entity *se = &p->se;
 
+	/*
+	 * If in_iowait is set, the code below may not trigger any cpufreq
+	 * utilization updates, so do it here explicitly with the IOWAIT flag
+	 * passed.
+	 */
+	if (p->in_iowait)
+		cpufreq_update_this_cpu(rq, SCHED_CPUFREQ_IOWAIT);
+
 	for_each_sched_entity(se) {
 		if (se->on_rq)
 			break;
Index: linux-pm/include/linux/sched.h
===================================================================
--- linux-pm.orig/include/linux/sched.h
+++ linux-pm/include/linux/sched.h
@@ -3471,6 +3471,7 @@ static inline unsigned long rlimit_max(u
 
 #define SCHED_CPUFREQ_RT	(1U << 0)
 #define SCHED_CPUFREQ_DL	(1U << 1)
+#define SCHED_CPUFREQ_IOWAIT	(1U << 2)
 
 #define SCHED_CPUFREQ_RT_DL	(SCHED_CPUFREQ_RT | SCHED_CPUFREQ_DL)
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Resend][PATCH 2/3] cpufreq: schedutil: Add iowait boosting
  2016-09-09 21:57 [PATCH 0/3] cpufreq / sched: iowait boost in intel_pstate and schedutil Rafael J. Wysocki
  2016-09-09 21:59 ` [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition Rafael J. Wysocki
@ 2016-09-09 22:00 ` Rafael J. Wysocki
  2016-09-13  7:44   ` Peter Zijlstra
  2016-09-09 22:02 ` [PATCH 3/3] cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm Rafael J. Wysocki
  2 siblings, 1 reply; 7+ messages in thread
From: Rafael J. Wysocki @ 2016-09-09 22:00 UTC (permalink / raw)
  To: Linux PM list
  Cc: Linux Kernel Mailing List, Srinivas Pandruvada, Peter Zijlstra,
	Viresh Kumar, Ingo Molnar, Vincent Guittot, Morten Rasmussen,
	Juri Lelli, Dietmar Eggemann, Steve Muckle, Doug Smythies

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Modify the schedutil cpufreq governor to boost the CPU
frequency if the SCHED_CPUFREQ_IOWAIT flag is passed to
it via cpufreq_update_util().

If that happens, the frequency is set to the maximum during
the first update after receiving the SCHED_CPUFREQ_IOWAIT flag
and then the boost is reduced by half during each following update.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Looks-good-to: Steve Muckle <smuckle@linaro.org>
---
 kernel/sched/cpufreq_schedutil.c |   53 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 4 deletions(-)

Index: linux-pm/kernel/sched/cpufreq_schedutil.c
===================================================================
--- linux-pm.orig/kernel/sched/cpufreq_schedutil.c
+++ linux-pm/kernel/sched/cpufreq_schedutil.c
@@ -47,11 +47,13 @@ struct sugov_cpu {
 	struct sugov_policy *sg_policy;
 
 	unsigned int cached_raw_freq;
+	unsigned long iowait_boost;
+	unsigned long iowait_boost_max;
+	u64 last_update;
 
 	/* The fields below are only needed when sharing a policy. */
 	unsigned long util;
 	unsigned long max;
-	u64 last_update;
 	unsigned int flags;
 };
 
@@ -153,6 +155,36 @@ static void sugov_get_util(unsigned long
 	*max = cfs_max;
 }
 
+static void sugov_set_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
+				   unsigned int flags)
+{
+	if (flags & SCHED_CPUFREQ_IOWAIT) {
+		sg_cpu->iowait_boost = sg_cpu->iowait_boost_max;
+	} else if (sg_cpu->iowait_boost) {
+		s64 delta_ns = time - sg_cpu->last_update;
+
+		/* Clear iowait_boost if the CPU apprears to have been idle. */
+		if (delta_ns > TICK_NSEC)
+			sg_cpu->iowait_boost = 0;
+	}
+}
+
+static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, unsigned long *util,
+			       unsigned long *max)
+{
+	unsigned long boost_util = sg_cpu->iowait_boost;
+	unsigned long boost_max = sg_cpu->iowait_boost_max;
+
+	if (!boost_util)
+		return;
+
+	if (*util * boost_max < *max * boost_util) {
+		*util = boost_util;
+		*max = boost_max;
+	}
+	sg_cpu->iowait_boost >>= 1;
+}
+
 static void sugov_update_single(struct update_util_data *hook, u64 time,
 				unsigned int flags)
 {
@@ -162,6 +194,9 @@ static void sugov_update_single(struct u
 	unsigned long util, max;
 	unsigned int next_f;
 
+	sugov_set_iowait_boost(sg_cpu, time, flags);
+	sg_cpu->last_update = time;
+
 	if (!sugov_should_update_freq(sg_policy, time))
 		return;
 
@@ -169,6 +204,7 @@ static void sugov_update_single(struct u
 		next_f = policy->cpuinfo.max_freq;
 	} else {
 		sugov_get_util(&util, &max);
+		sugov_iowait_boost(sg_cpu, &util, &max);
 		next_f = get_next_freq(sg_cpu, util, max);
 	}
 	sugov_update_commit(sg_policy, time, next_f);
@@ -187,6 +223,8 @@ static unsigned int sugov_next_freq_shar
 	if (flags & SCHED_CPUFREQ_RT_DL)
 		return max_f;
 
+	sugov_iowait_boost(sg_cpu, &util, &max);
+
 	for_each_cpu(j, policy->cpus) {
 		struct sugov_cpu *j_sg_cpu;
 		unsigned long j_util, j_max;
@@ -201,12 +239,13 @@ static unsigned int sugov_next_freq_shar
 		 * frequency update and the time elapsed between the last update
 		 * of the CPU utilization and the last frequency update is long
 		 * enough, don't take the CPU into account as it probably is
-		 * idle now.
+		 * idle now (and clear iowait_boost for it).
 		 */
 		delta_ns = last_freq_update_time - j_sg_cpu->last_update;
-		if (delta_ns > TICK_NSEC)
+		if (delta_ns > TICK_NSEC) {
+			j_sg_cpu->iowait_boost = 0;
 			continue;
-
+		}
 		if (j_sg_cpu->flags & SCHED_CPUFREQ_RT_DL)
 			return max_f;
 
@@ -216,6 +255,8 @@ static unsigned int sugov_next_freq_shar
 			util = j_util;
 			max = j_max;
 		}
+
+		sugov_iowait_boost(j_sg_cpu, &util, &max);
 	}
 
 	return get_next_freq(sg_cpu, util, max);
@@ -236,6 +277,8 @@ static void sugov_update_shared(struct u
 	sg_cpu->util = util;
 	sg_cpu->max = max;
 	sg_cpu->flags = flags;
+
+	sugov_set_iowait_boost(sg_cpu, time, flags);
 	sg_cpu->last_update = time;
 
 	if (sugov_should_update_freq(sg_policy, time)) {
@@ -468,6 +511,8 @@ static int sugov_start(struct cpufreq_po
 			sg_cpu->flags = SCHED_CPUFREQ_RT;
 			sg_cpu->last_update = 0;
 			sg_cpu->cached_raw_freq = 0;
+			sg_cpu->iowait_boost = 0;
+			sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
 			cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
 						     sugov_update_shared);
 		} else {

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/3] cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm
  2016-09-09 21:57 [PATCH 0/3] cpufreq / sched: iowait boost in intel_pstate and schedutil Rafael J. Wysocki
  2016-09-09 21:59 ` [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition Rafael J. Wysocki
  2016-09-09 22:00 ` [Resend][PATCH 2/3] cpufreq: schedutil: Add iowait boosting Rafael J. Wysocki
@ 2016-09-09 22:02 ` Rafael J. Wysocki
  2016-09-13 23:59   ` [Update][PATCH " Rafael J. Wysocki
  2 siblings, 1 reply; 7+ messages in thread
From: Rafael J. Wysocki @ 2016-09-09 22:02 UTC (permalink / raw)
  To: Linux PM list
  Cc: Linux Kernel Mailing List, Srinivas Pandruvada, Peter Zijlstra,
	Viresh Kumar, Ingo Molnar, Vincent Guittot, Morten Rasmussen,
	Juri Lelli, Dietmar Eggemann, Steve Muckle, Doug Smythies

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Modify the P-state selection algorithm for Atom processors to use
the new SCHED_CPUFREQ_IOWAIT flag instead of the questionable
get_cpu_iowait_time_us() function.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/cpufreq/intel_pstate.c |   58 +++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 27 deletions(-)

Index: linux-pm/drivers/cpufreq/intel_pstate.c
===================================================================
--- linux-pm.orig/drivers/cpufreq/intel_pstate.c
+++ linux-pm/drivers/cpufreq/intel_pstate.c
@@ -181,6 +181,8 @@ struct _pid {
  * @cpu:		CPU number for this instance data
  * @update_util:	CPUFreq utility callback information
  * @update_util_set:	CPUFreq utility callback is set
+ * @iowait_boost:	iowait-related boost fraction
+ * @last_update:	Time of the last update.
  * @pstate:		Stores P state limits for this CPU
  * @vid:		Stores VID limits for this CPU
  * @pid:		Stores PID parameters for this CPU
@@ -206,6 +208,7 @@ struct cpudata {
 	struct vid_data vid;
 	struct _pid pid;
 
+	u64	last_update;
 	u64	last_sample_time;
 	u64	prev_aperf;
 	u64	prev_mperf;
@@ -216,6 +219,7 @@ struct cpudata {
 	struct acpi_processor_performance acpi_perf_data;
 	bool valid_pss_table;
 #endif
+	unsigned int iowait_boost;
 };
 
 static struct cpudata **all_cpu_data;
@@ -229,6 +233,7 @@ static struct cpudata **all_cpu_data;
  * @p_gain_pct:		PID proportional gain
  * @i_gain_pct:		PID integral gain
  * @d_gain_pct:		PID derivative gain
+ * @boost_iowait:	Whether or not to use iowait boosting.
  *
  * Stores per CPU model static PID configuration data.
  */
@@ -240,6 +245,7 @@ struct pstate_adjust_policy {
 	int p_gain_pct;
 	int d_gain_pct;
 	int i_gain_pct;
+	bool boost_iowait;
 };
 
 /**
@@ -1037,6 +1043,7 @@ static struct cpu_defaults silvermont_pa
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
+		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = atom_get_max_pstate,
@@ -1058,6 +1065,7 @@ static struct cpu_defaults airmont_param
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
+		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = atom_get_max_pstate,
@@ -1099,6 +1107,7 @@ static struct cpu_defaults bxt_params =
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
+		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = core_get_max_pstate,
@@ -1222,36 +1231,18 @@ static inline int32_t get_avg_pstate(str
 static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 {
 	struct sample *sample = &cpu->sample;
-	u64 cummulative_iowait, delta_iowait_us;
-	u64 delta_iowait_mperf;
-	u64 mperf, now;
-	int32_t cpu_load;
+	int32_t busy_frac, boost;
 
-	cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now);
+	busy_frac = div_fp(sample->mperf, sample->tsc);
 
-	/*
-	 * Convert iowait time into number of IO cycles spent at max_freq.
-	 * IO is considered as busy only for the cpu_load algorithm. For
-	 * performance this is not needed since we always try to reach the
-	 * maximum P-State, so we are already boosting the IOs.
-	 */
-	delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait;
-	delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling *
-		cpu->pstate.max_pstate, MSEC_PER_SEC);
+	boost = cpu->iowait_boost;
+	cpu->iowait_boost >>= 1;
 
-	mperf = cpu->sample.mperf + delta_iowait_mperf;
-	cpu->prev_cummulative_iowait = cummulative_iowait;
-
-	/*
-	 * The load can be estimated as the ratio of the mperf counter
-	 * running at a constant frequency during active periods
-	 * (C0) and the time stamp counter running at the same frequency
-	 * also during C-states.
-	 */
-	cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
-	cpu->sample.busy_scaled = cpu_load;
+	if (busy_frac < boost)
+		busy_frac = boost;
 
-	return get_avg_pstate(cpu) - pid_calc(&cpu->pid, cpu_load);
+	sample->busy_scaled = busy_frac * 100;
+	return get_avg_pstate(cpu) - pid_calc(&cpu->pid, busy_frac);
 }
 
 static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
@@ -1332,8 +1323,21 @@ static void intel_pstate_update_util(str
 				     unsigned int flags)
 {
 	struct cpudata *cpu = container_of(data, struct cpudata, update_util);
-	u64 delta_ns = time - cpu->sample.time;
+	u64 delta_ns;
+
+	if (pid_params.boost_iowait) {
+		if (flags & SCHED_CPUFREQ_IOWAIT) {
+			cpu->iowait_boost = int_tofp(1);
+		} else if (cpu->iowait_boost) {
+			/* Clear iowait_boost if the CPU may have been idle. */
+			delta_ns = time - cpu->last_update;
+			if (delta_ns > TICK_NSEC)
+				cpu->iowait_boost = 0;
+		}
+		cpu->last_update = time;
+	}
 
+	delta_ns = time - cpu->sample.time;
 	if ((s64)delta_ns >= pid_params.sample_rate_ns) {
 		bool sample_taken = intel_pstate_sample(cpu, time);
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition
  2016-09-09 21:59 ` [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition Rafael J. Wysocki
@ 2016-09-13  7:34   ` Peter Zijlstra
  0 siblings, 0 replies; 7+ messages in thread
From: Peter Zijlstra @ 2016-09-13  7:34 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux PM list, Linux Kernel Mailing List, Srinivas Pandruvada,
	Viresh Kumar, Ingo Molnar, Vincent Guittot, Morten Rasmussen,
	Juri Lelli, Dietmar Eggemann, Steve Muckle, Doug Smythies

On Fri, Sep 09, 2016 at 11:59:33PM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Testing indicates that it is possible to improve performace
> significantly without increasing energy consumption too much by
> teaching cpufreq governors to bump up the CPU performance level if
> the in_iowait flag is set for the task in enqueue_task_fair().
> 
> For this purpose, define a new cpufreq_update_util() flag
> SCHED_CPUFREQ_IOWAIT and modify enqueue_task_fair() to pass that
> flag to cpufreq_update_util() in the in_iowait case.  That generally
> requires cpufreq_update_util() to be called directly from there,
> because update_load_avg() may not be invoked in that case.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Looks-good-to: Steve Muckle <smuckle@linaro.org>

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Resend][PATCH 2/3] cpufreq: schedutil: Add iowait boosting
  2016-09-09 22:00 ` [Resend][PATCH 2/3] cpufreq: schedutil: Add iowait boosting Rafael J. Wysocki
@ 2016-09-13  7:44   ` Peter Zijlstra
  0 siblings, 0 replies; 7+ messages in thread
From: Peter Zijlstra @ 2016-09-13  7:44 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux PM list, Linux Kernel Mailing List, Srinivas Pandruvada,
	Viresh Kumar, Ingo Molnar, Vincent Guittot, Morten Rasmussen,
	Juri Lelli, Dietmar Eggemann, Steve Muckle, Doug Smythies

On Sat, Sep 10, 2016 at 12:00:31AM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Modify the schedutil cpufreq governor to boost the CPU
> frequency if the SCHED_CPUFREQ_IOWAIT flag is passed to
> it via cpufreq_update_util().
> 
> If that happens, the frequency is set to the maximum during
> the first update after receiving the SCHED_CPUFREQ_IOWAIT flag
> and then the boost is reduced by half during each following update.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Looks-good-to: Steve Muckle <smuckle@linaro.org>

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Update][PATCH 3/3] cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm
  2016-09-09 22:02 ` [PATCH 3/3] cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm Rafael J. Wysocki
@ 2016-09-13 23:59   ` Rafael J. Wysocki
  0 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2016-09-13 23:59 UTC (permalink / raw)
  To: Linux PM list, Srinivas Pandruvada
  Cc: Linux Kernel Mailing List, Peter Zijlstra, Viresh Kumar,
	Ingo Molnar, Vincent Guittot, Morten Rasmussen, Juri Lelli,
	Dietmar Eggemann, Steve Muckle, Doug Smythies

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Modify the P-state selection algorithm for Atom processors to use
the new SCHED_CPUFREQ_IOWAIT flag instead of the questionable
get_cpu_iowait_time_us() function.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---

The PID uses percents not fractions, so pass sample->busy_scaled instead of
busy_frac to it in get_target_pstate_use_cpu_load().

---
 drivers/cpufreq/intel_pstate.c |   58 +++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 27 deletions(-)

Index: linux-pm/drivers/cpufreq/intel_pstate.c
===================================================================
--- linux-pm.orig/drivers/cpufreq/intel_pstate.c
+++ linux-pm/drivers/cpufreq/intel_pstate.c
@@ -181,6 +181,8 @@ struct _pid {
  * @cpu:		CPU number for this instance data
  * @update_util:	CPUFreq utility callback information
  * @update_util_set:	CPUFreq utility callback is set
+ * @iowait_boost:	iowait-related boost fraction
+ * @last_update:	Time of the last update.
  * @pstate:		Stores P state limits for this CPU
  * @vid:		Stores VID limits for this CPU
  * @pid:		Stores PID parameters for this CPU
@@ -206,6 +208,7 @@ struct cpudata {
 	struct vid_data vid;
 	struct _pid pid;
 
+	u64	last_update;
 	u64	last_sample_time;
 	u64	prev_aperf;
 	u64	prev_mperf;
@@ -216,6 +219,7 @@ struct cpudata {
 	struct acpi_processor_performance acpi_perf_data;
 	bool valid_pss_table;
 #endif
+	unsigned int iowait_boost;
 };
 
 static struct cpudata **all_cpu_data;
@@ -229,6 +233,7 @@ static struct cpudata **all_cpu_data;
  * @p_gain_pct:		PID proportional gain
  * @i_gain_pct:		PID integral gain
  * @d_gain_pct:		PID derivative gain
+ * @boost_iowait:	Whether or not to use iowait boosting.
  *
  * Stores per CPU model static PID configuration data.
  */
@@ -240,6 +245,7 @@ struct pstate_adjust_policy {
 	int p_gain_pct;
 	int d_gain_pct;
 	int i_gain_pct;
+	bool boost_iowait;
 };
 
 /**
@@ -1037,6 +1043,7 @@ static struct cpu_defaults silvermont_pa
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
+		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = atom_get_max_pstate,
@@ -1058,6 +1065,7 @@ static struct cpu_defaults airmont_param
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
+		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = atom_get_max_pstate,
@@ -1099,6 +1107,7 @@ static struct cpu_defaults bxt_params =
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
+		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = core_get_max_pstate,
@@ -1222,36 +1231,18 @@ static inline int32_t get_avg_pstate(str
 static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 {
 	struct sample *sample = &cpu->sample;
-	u64 cummulative_iowait, delta_iowait_us;
-	u64 delta_iowait_mperf;
-	u64 mperf, now;
-	int32_t cpu_load;
+	int32_t busy_frac, boost;
 
-	cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now);
+	busy_frac = div_fp(sample->mperf, sample->tsc);
 
-	/*
-	 * Convert iowait time into number of IO cycles spent at max_freq.
-	 * IO is considered as busy only for the cpu_load algorithm. For
-	 * performance this is not needed since we always try to reach the
-	 * maximum P-State, so we are already boosting the IOs.
-	 */
-	delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait;
-	delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling *
-		cpu->pstate.max_pstate, MSEC_PER_SEC);
+	boost = cpu->iowait_boost;
+	cpu->iowait_boost >>= 1;
 
-	mperf = cpu->sample.mperf + delta_iowait_mperf;
-	cpu->prev_cummulative_iowait = cummulative_iowait;
-
-	/*
-	 * The load can be estimated as the ratio of the mperf counter
-	 * running at a constant frequency during active periods
-	 * (C0) and the time stamp counter running at the same frequency
-	 * also during C-states.
-	 */
-	cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
-	cpu->sample.busy_scaled = cpu_load;
+	if (busy_frac < boost)
+		busy_frac = boost;
 
-	return get_avg_pstate(cpu) - pid_calc(&cpu->pid, cpu_load);
+	sample->busy_scaled = busy_frac * 100;
+	return get_avg_pstate(cpu) - pid_calc(&cpu->pid, sample->busy_scaled);
 }
 
 static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
@@ -1332,8 +1323,21 @@ static void intel_pstate_update_util(str
 				     unsigned int flags)
 {
 	struct cpudata *cpu = container_of(data, struct cpudata, update_util);
-	u64 delta_ns = time - cpu->sample.time;
+	u64 delta_ns;
+
+	if (pid_params.boost_iowait) {
+		if (flags & SCHED_CPUFREQ_IOWAIT) {
+			cpu->iowait_boost = int_tofp(1);
+		} else if (cpu->iowait_boost) {
+			/* Clear iowait_boost if the CPU may have been idle. */
+			delta_ns = time - cpu->last_update;
+			if (delta_ns > TICK_NSEC)
+				cpu->iowait_boost = 0;
+		}
+		cpu->last_update = time;
+	}
 
+	delta_ns = time - cpu->sample.time;
 	if ((s64)delta_ns >= pid_params.sample_rate_ns) {
 		bool sample_taken = intel_pstate_sample(cpu, time);
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-09-13 23:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-09 21:57 [PATCH 0/3] cpufreq / sched: iowait boost in intel_pstate and schedutil Rafael J. Wysocki
2016-09-09 21:59 ` [Resend][PATCH 1/3] cpufreq / sched: SCHED_CPUFREQ_IOWAIT flag to indicate iowait condition Rafael J. Wysocki
2016-09-13  7:34   ` Peter Zijlstra
2016-09-09 22:00 ` [Resend][PATCH 2/3] cpufreq: schedutil: Add iowait boosting Rafael J. Wysocki
2016-09-13  7:44   ` Peter Zijlstra
2016-09-09 22:02 ` [PATCH 3/3] cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm Rafael J. Wysocki
2016-09-13 23:59   ` [Update][PATCH " Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).