Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5ca0d81 authored by Jonathan Avila's avatar Jonathan Avila
Browse files

cpufreq: schedutil: Add consistent cycle tracking



Currently, cycle tracking is not consistently applied in all cases in the
schedutil governor, which can lead to errors in the calculation of average
capacity. Fix this.

Change-Id: Idbdc6d1516abd20466c78f79c6524b3348b922f9
Signed-off-by: default avatarJonathan Avila <avilaj@codeaurora.org>
parent 714e43c8
Loading
Loading
Loading
Loading
+46 −45
Original line number Original line Diff line number Diff line
@@ -165,6 +165,51 @@ static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time,
	return true;
	return true;
}
}


static unsigned long freq_to_util(struct sugov_policy *sg_policy,
				  unsigned int freq)
{
	return mult_frac(sg_policy->max, freq,
			 sg_policy->policy->cpuinfo.max_freq);
}

#define KHZ 1000
static void sugov_track_cycles(struct sugov_policy *sg_policy,
				unsigned int prev_freq,
				u64 upto)
{
	u64 delta_ns, cycles;
	/* Track cycles in current window */
	delta_ns = upto - sg_policy->last_cyc_update_time;
	cycles = (prev_freq * delta_ns) / (NSEC_PER_SEC / KHZ);
	sg_policy->curr_cycles += cycles;
	sg_policy->last_cyc_update_time = upto;
}

static void sugov_calc_avg_cap(struct sugov_policy *sg_policy, u64 curr_ws,
				unsigned int prev_freq)
{
	u64 last_ws = sg_policy->last_ws;
	unsigned int avg_freq;

	WARN_ON(curr_ws < last_ws);
	if (curr_ws <= last_ws)
		return;

	/* If we skipped some windows */
	if (curr_ws > (last_ws + sched_ravg_window)) {
		avg_freq = prev_freq;
		/* Reset tracking history */
		sg_policy->last_cyc_update_time = curr_ws;
	} else {
		sugov_track_cycles(sg_policy, prev_freq, curr_ws);
		avg_freq = sg_policy->curr_cycles;
		avg_freq /= sched_ravg_window / (NSEC_PER_SEC / KHZ);
	}
	sg_policy->avg_cap = freq_to_util(sg_policy, avg_freq);
	sg_policy->curr_cycles = 0;
	sg_policy->last_ws = curr_ws;
}

static void sugov_fast_switch(struct sugov_policy *sg_policy, u64 time,
static void sugov_fast_switch(struct sugov_policy *sg_policy, u64 time,
			      unsigned int next_freq)
			      unsigned int next_freq)
{
{
@@ -174,6 +219,7 @@ static void sugov_fast_switch(struct sugov_policy *sg_policy, u64 time,
	if (!sugov_update_next_freq(sg_policy, time, next_freq))
	if (!sugov_update_next_freq(sg_policy, time, next_freq))
		return;
		return;


	sugov_track_cycles(sg_policy, sg_policy->policy->cur, time);
	next_freq = cpufreq_driver_fast_switch(policy, next_freq);
	next_freq = cpufreq_driver_fast_switch(policy, next_freq);
	if (!next_freq)
	if (!next_freq)
		return;
		return;
@@ -504,51 +550,6 @@ static bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu)
static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
#endif /* CONFIG_NO_HZ_COMMON */
#endif /* CONFIG_NO_HZ_COMMON */


static unsigned long freq_to_util(struct sugov_policy *sg_policy,
				  unsigned int freq)
{
	return mult_frac(sg_policy->max, freq,
			 sg_policy->policy->cpuinfo.max_freq);
}

#define KHZ 1000
static void sugov_track_cycles(struct sugov_policy *sg_policy,
				unsigned int prev_freq,
				u64 upto)
{
	u64 delta_ns, cycles;
	/* Track cycles in current window */
	delta_ns = upto - sg_policy->last_cyc_update_time;
	cycles = (prev_freq * delta_ns) / (NSEC_PER_SEC / KHZ);
	sg_policy->curr_cycles += cycles;
	sg_policy->last_cyc_update_time = upto;
}

static void sugov_calc_avg_cap(struct sugov_policy *sg_policy, u64 curr_ws,
				unsigned int prev_freq)
{
	u64 last_ws = sg_policy->last_ws;
	unsigned int avg_freq;

	WARN_ON(curr_ws < last_ws);
	if (curr_ws <= last_ws)
		return;

	/* If we skipped some windows */
	if (curr_ws > (last_ws + sched_ravg_window)) {
		avg_freq = prev_freq;
		/* Reset tracking history */
		sg_policy->last_cyc_update_time = curr_ws;
	} else {
		sugov_track_cycles(sg_policy, prev_freq, curr_ws);
		avg_freq = sg_policy->curr_cycles;
		avg_freq /= sched_ravg_window / (NSEC_PER_SEC / KHZ);
	}
	sg_policy->avg_cap = freq_to_util(sg_policy, avg_freq);
	sg_policy->curr_cycles = 0;
	sg_policy->last_ws = curr_ws;
}

#define NL_RATIO 75
#define NL_RATIO 75
#define DEFAULT_HISPEED_LOAD 90
#define DEFAULT_HISPEED_LOAD 90
static void sugov_walt_adjust(struct sugov_cpu *sg_cpu, unsigned long *util,
static void sugov_walt_adjust(struct sugov_cpu *sg_cpu, unsigned long *util,