blob: 5fb64c89f38ab84120c305779bd780e1745d8870 [file] [log] [blame]
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Connor O'Brien <connoro@google.com>
Date: Fri, 8 Feb 2019 12:30:41 -0800
Subject: 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
Bug: 127641090
Test: /proc/uid_time_in_state shows times for more than one freq per
cluster
Change-Id: Ib63d19006878fafb88475e401ef243bdd8b11979
Signed-off-by: Connor O'Brien <connoro@google.com>
---
drivers/cpufreq/cpufreq.c | 10 ++++++++--
drivers/cpufreq/cpufreq_times.c | 15 ++++-----------
include/linux/cpufreq_times.h | 5 +++--
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6b25ba922628..c8a5d669b10e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -380,7 +380,7 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
CPUFREQ_POSTCHANGE, freqs);
cpufreq_stats_record_transition(policy, freqs->new);
- cpufreq_times_record_transition(freqs);
+ cpufreq_times_record_transition(policy, freqs->new);
policy->cur = freqs->new;
}
}
@@ -2026,9 +2026,15 @@ 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);
diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c
index aaded60c9a21..42420c5e1e6f 100644
--- a/drivers/cpufreq/cpufreq_times.c
+++ b/drivers/cpufreq/cpufreq_times.c
@@ -550,24 +550,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 = {
diff --git a/include/linux/cpufreq_times.h b/include/linux/cpufreq_times.h
index 757bf0cb6070..0eb6dc9d0fe2 100644
--- a/include/linux/cpufreq_times.h
+++ b/include/linux/cpufreq_times.h
@@ -27,7 +27,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, u64 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
@@ -38,7 +39,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 */