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

Commit eadd1739 authored by Junjie Wu's avatar Junjie Wu
Browse files

cpufreq: interactive: Record hispeed_validated_time in timer function



Change 0cd554ae
(cpufreq: interactive: Exercise hispeed settings at a policy level)
introduced policy level hispeed settings. The change is correct in
general, but it sets hispeed_validate_time after actual frequency
change has completed. Waking up speedchange task and setting
frequency takes non-trival amount of time. This period is not accounted
for in above_hispeed_delay, resulting in additional delays when
ramping up frequency. Frequency switch latency varies a lot
depending on beginning and end frequency, and thus it cannot be easily
compensated by user setting above_hispeed_delay.

Record a local hispeed_validated_time in every CPU's timer function.
Cluster hispeed_validated_time is the local hispeed_validated_time of
CPUs voting for the highest frequency.

Change-Id: Id8ae547fe3a70f8710f60b6e2125954111b7a2b6
Signed-off-by: default avatarJunjie Wu <junjiew@codeaurora.org>
parent eec8e250
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -52,7 +52,8 @@ struct cpufreq_interactive_cpuinfo {
	unsigned int floor_freq;
	unsigned int max_freq;
	u64 floor_validate_time;
	u64 hispeed_validate_time;
	u64 hispeed_validate_time; /* cluster hispeed_validate_time */
	u64 local_hvtime; /* per-cpu hispeed_validate_time */
	u64 max_freq_idle_start_time;
	struct rw_semaphore enable_sem;
	int governor_enabled;
@@ -466,6 +467,8 @@ static void cpufreq_interactive_timer(unsigned long data)
		goto rearm;
	}

	pcpu->local_hvtime = now;

	if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table,
					   new_freq, CPUFREQ_RELATION_L,
					   &index)) {
@@ -653,6 +656,7 @@ static int cpufreq_interactive_speedchange_task(void *data)
			unsigned int j;
			unsigned int max_freq = 0;
			struct cpufreq_interactive_cpuinfo *pjcpu;
			u64 hvt;

			pcpu = &per_cpu(cpuinfo, cpu);
			if (!down_read_trylock(&pcpu->enable_sem))
@@ -665,19 +669,21 @@ static int cpufreq_interactive_speedchange_task(void *data)
			for_each_cpu(j, pcpu->policy->cpus) {
				pjcpu = &per_cpu(cpuinfo, j);

				if (pjcpu->target_freq > max_freq)
				if (pjcpu->target_freq > max_freq) {
					max_freq = pjcpu->target_freq;
					hvt = pjcpu->local_hvtime;
				} else if (pjcpu->target_freq == max_freq) {
					hvt = min(hvt, pjcpu->local_hvtime);
				}
			}

			if (max_freq != pcpu->policy->cur) {
				u64 now;
				__cpufreq_driver_target(pcpu->policy,
							max_freq,
							CPUFREQ_RELATION_H);
				now = ktime_to_us(ktime_get());
				for_each_cpu(j, pcpu->policy->cpus) {
					pjcpu = &per_cpu(cpuinfo, j);
					pjcpu->hispeed_validate_time = now;
					pjcpu->hispeed_validate_time = hvt;
				}
			}
			trace_cpufreq_interactive_setspeed(cpu,
@@ -1634,6 +1640,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
				ktime_to_us(ktime_get());
			pcpu->hispeed_validate_time =
				pcpu->floor_validate_time;
			pcpu->local_hvtime = pcpu->floor_validate_time;
			pcpu->max_freq = policy->max;
			down_write(&pcpu->enable_sem);
			del_timer_sync(&pcpu->cpu_timer);