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

Commit 2f0bc4bc authored by Connor O'Brien's avatar Connor O'Brien
Browse files

ANDROID: cpufreq: times: record fast switch frequency transitions



cpufreq_times_record_transition() is not called when fast switch is
enabled, leading /proc/uid_time_in_state to attribute all time on a
cluster to a single frequency. To fix this, add a call to
cpufreq_times_record_transition() in the fast switch path.

Also revise cpufreq_times_record_transition() to simplify the new call
and more closely align with cpufreq_stats_record_transition().

Bug: 121287027
Test: /proc/uid_time_in_state shows times for more than one freq per
cluster
Signed-off-by: default avatarConnor O'Brien <connoro@google.com>
Change-Id: I071ee2fa90eaadaad26582a298b741c5294e18b7
parent 9cca4066
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -435,7 +435,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
			 (unsigned long)freqs->new, (unsigned long)freqs->cpu);
		trace_cpu_frequency(freqs->new, freqs->cpu);
		cpufreq_stats_record_transition(policy, freqs->new);
		cpufreq_times_record_transition(freqs);
		cpufreq_times_record_transition(policy, freqs->new);
		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
				CPUFREQ_POSTCHANGE, freqs);
		if (likely(policy) && likely(policy->cpu == freqs->cpu))
@@ -1928,9 +1928,14 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
					unsigned int target_freq)
{
	int ret;
	target_freq = clamp_val(target_freq, policy->min, policy->max);

	return cpufreq_driver->fast_switch(policy, target_freq);
        ret = cpufreq_driver->fast_switch(policy, target_freq);
	if (ret)
		cpufreq_times_record_transition(policy, ret);

	return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch);

+4 −11
Original line number Diff line number Diff line
@@ -556,24 +556,17 @@ void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end)
	spin_unlock_irqrestore(&uid_lock, flags);
}

void cpufreq_times_record_transition(struct cpufreq_freqs *freq)
void cpufreq_times_record_transition(struct cpufreq_policy *policy,
	unsigned int new_freq)
{
	int index;
	struct cpu_freqs *freqs = all_freqs[freq->cpu];
	struct cpufreq_policy *policy;

	struct cpu_freqs *freqs = all_freqs[policy->cpu];
	if (!freqs)
		return;

	policy = cpufreq_cpu_get(freq->cpu);
	if (!policy)
		return;

	index = cpufreq_frequency_table_get_index(policy, freq->new);
	index = cpufreq_frequency_table_get_index(policy, new_freq);
	if (index >= 0)
		WRITE_ONCE(freqs->last_index, index);

	cpufreq_cpu_put(policy);
}

static const struct seq_operations uid_time_in_state_seq_ops = {
+3 −2
Original line number Diff line number Diff line
@@ -28,7 +28,8 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
			    struct pid *pid, struct task_struct *p);
void cpufreq_acct_update_power(struct task_struct *p, cputime_t cputime);
void cpufreq_times_create_policy(struct cpufreq_policy *policy);
void cpufreq_times_record_transition(struct cpufreq_freqs *freq);
void cpufreq_times_record_transition(struct cpufreq_policy *policy,
                                     unsigned int new_freq);
void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end);
int single_uid_time_in_state_open(struct inode *inode, struct file *file);
#else
@@ -39,7 +40,7 @@ static inline void cpufreq_acct_update_power(struct task_struct *p,
					     u64 cputime) {}
static inline void cpufreq_times_create_policy(struct cpufreq_policy *policy) {}
static inline void cpufreq_times_record_transition(
	struct cpufreq_freqs *freq) {}
	struct cpufreq_policy *policy, unsigned int new_freq) {}
static inline void cpufreq_task_times_remove_uids(uid_t uid_start,
						  uid_t uid_end) {}
#endif /* CONFIG_CPU_FREQ_TIMES */