Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / cpufreq / cpufreq_interactive.c
index 25dd5885d1a024d467b2c3f1b012afa33d4a7063..1cfbcb8ba75cff600f57be9217abf1fc3e271241 100644 (file)
@@ -489,6 +489,58 @@ static void cpufreq_interactive_idle_end(void)
        up_read(&pcpu->enable_sem);
 }
 
+static void cpufreq_interactive_get_policy_info(struct cpufreq_policy *policy,
+                                               unsigned int *pmax_freq,
+                                               u64 *phvt, u64 *pfvt)
+{
+       struct cpufreq_interactive_cpuinfo *pcpu;
+       unsigned int max_freq = 0;
+       u64 hvt = ~0ULL, fvt = 0;
+       unsigned int i;
+
+       for_each_cpu(i, policy->cpus) {
+               pcpu = &per_cpu(cpuinfo, i);
+
+               fvt = max(fvt, pcpu->loc_floor_val_time);
+               if (pcpu->target_freq > max_freq) {
+                       max_freq = pcpu->target_freq;
+                       hvt = pcpu->loc_hispeed_val_time;
+               } else if (pcpu->target_freq == max_freq) {
+                       hvt = min(hvt, pcpu->loc_hispeed_val_time);
+               }
+       }
+
+       *pmax_freq = max_freq;
+       *phvt = hvt;
+       *pfvt = fvt;
+}
+
+static void cpufreq_interactive_adjust_cpu(unsigned int cpu,
+                                          struct cpufreq_policy *policy)
+{
+       struct cpufreq_interactive_cpuinfo *pcpu;
+       u64 hvt, fvt;
+       unsigned int max_freq;
+       int i;
+
+       cpufreq_interactive_get_policy_info(policy, &max_freq, &hvt, &fvt);
+
+       for_each_cpu(i, policy->cpus) {
+               pcpu = &per_cpu(cpuinfo, i);
+               pcpu->pol_floor_val_time = fvt;
+       }
+
+       if (max_freq != policy->cur) {
+               __cpufreq_driver_target(policy, max_freq, CPUFREQ_RELATION_H);
+               for_each_cpu(i, policy->cpus) {
+                       pcpu = &per_cpu(cpuinfo, i);
+                       pcpu->pol_hispeed_val_time = hvt;
+               }
+       }
+
+       trace_cpufreq_interactive_setspeed(cpu, max_freq, policy->cur);
+}
+
 static int cpufreq_interactive_speedchange_task(void *data)
 {
        unsigned int cpu;
@@ -517,49 +569,18 @@ static int cpufreq_interactive_speedchange_task(void *data)
                spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
 
                for_each_cpu(cpu, &tmp_mask) {
-                       unsigned int j;
-                       unsigned int max_freq = 0;
-                       struct cpufreq_interactive_cpuinfo *pjcpu;
-                       u64 hvt = ~0ULL, fvt = 0;
-
                        pcpu = &per_cpu(cpuinfo, cpu);
-                       if (!down_read_trylock(&pcpu->enable_sem))
-                               continue;
-                       if (!pcpu->governor_enabled) {
-                               up_read(&pcpu->enable_sem);
-                               continue;
-                       }
-
-                       for_each_cpu(j, pcpu->policy->cpus) {
-                               pjcpu = &per_cpu(cpuinfo, j);
 
-                               fvt = max(fvt, pjcpu->loc_floor_val_time);
-                               if (pjcpu->target_freq > max_freq) {
-                                       max_freq = pjcpu->target_freq;
-                                       hvt = pjcpu->loc_hispeed_val_time;
-                               } else if (pjcpu->target_freq == max_freq) {
-                                       hvt = min(hvt, pjcpu->loc_hispeed_val_time);
-                               }
-                       }
-                       for_each_cpu(j, pcpu->policy->cpus) {
-                               pjcpu = &per_cpu(cpuinfo, j);
-                               pjcpu->pol_floor_val_time = fvt;
-                       }
+                       down_write(&pcpu->policy->rwsem);
 
-                       if (max_freq != pcpu->policy->cur) {
-                               __cpufreq_driver_target(pcpu->policy,
-                                                       max_freq,
-                                                       CPUFREQ_RELATION_H);
-                               for_each_cpu(j, pcpu->policy->cpus) {
-                                       pjcpu = &per_cpu(cpuinfo, j);
-                                       pjcpu->pol_hispeed_val_time = hvt;
-                               }
+                       if (likely(down_read_trylock(&pcpu->enable_sem))) {
+                               if (likely(pcpu->governor_enabled))
+                                       cpufreq_interactive_adjust_cpu(cpu,
+                                                       pcpu->policy);
+                               up_read(&pcpu->enable_sem);
                        }
-                       trace_cpufreq_interactive_setspeed(cpu,
-                                                    pcpu->target_freq,
-                                                    pcpu->policy->cur);
 
-                       up_read(&pcpu->enable_sem);
+                       up_write(&pcpu->policy->rwsem);
                }
        }
 
@@ -579,8 +600,19 @@ static void cpufreq_interactive_boost(struct cpufreq_interactive_tunables *tunab
 
        for_each_online_cpu(i) {
                pcpu = &per_cpu(cpuinfo, i);
-               if (tunables != pcpu->policy->governor_data)
+
+               if (!down_read_trylock(&pcpu->enable_sem))
+                       continue;
+
+               if (!pcpu->governor_enabled) {
+                       up_read(&pcpu->enable_sem);
+                       continue;
+               }
+
+               if (tunables != pcpu->policy->governor_data) {
+                       up_read(&pcpu->enable_sem);
                        continue;
+               }
 
                spin_lock_irqsave(&pcpu->target_freq_lock, flags[1]);
                if (pcpu->target_freq < tunables->hispeed_freq) {
@@ -591,6 +623,8 @@ static void cpufreq_interactive_boost(struct cpufreq_interactive_tunables *tunab
                        anyboost = 1;
                }
                spin_unlock_irqrestore(&pcpu->target_freq_lock, flags[1]);
+
+               up_read(&pcpu->enable_sem);
        }
 
        spin_unlock_irqrestore(&speedchange_cpumask_lock, flags[0]);