ANDROID: cpufreq: times: record fast switch frequency transitions
authorConnor O'Brien <connoro@google.com>
Fri, 8 Feb 2019 20:30:41 +0000 (12:30 -0800)
committerConnor O'Brien <connoro@google.com>
Tue, 19 Feb 2019 20:55:13 +0000 (20:55 +0000)
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
Change-Id: Ib63d19006878fafb88475e401ef243bdd8b11979
Signed-off-by: Connor O'Brien <connoro@google.com>
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_times.c
include/linux/cpufreq_times.h

index 927399454d625aa9465f87f1c44fa1bfd1221175..467b2738cc3a8a69b5427f3395fd2e748d045bbc 100644 (file)
@@ -340,7 +340,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))
@@ -1856,9 +1856,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);
 
index aaded60c9a21c38275652262019ce634eba02d9b..42420c5e1e6fc3369084b63c53941f282797471b 100644 (file)
@@ -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 = {
index 757bf0cb60704719c49f97467f4813cbe2bed14a..0eb6dc9d0fe29cb1db992783b90e634768d2ced3 100644 (file)
@@ -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 */