Merge branch 'lsk-v4.4-android' of git://android.git.linaro.org/kernel/linaro-android...
[firefly-linux-kernel-4.4.55.git] / drivers / cpufreq / cpufreq_interactive.c
index a20ab2e635bf04a9a8d0f7a982f1df84492269c0..f2929e62882074b7ca8fd03b607d2018b5e3db8a 100644 (file)
@@ -365,7 +365,7 @@ static void cpufreq_interactive_timer(unsigned long data)
        spin_lock_irqsave(&pcpu->target_freq_lock, flags);
        do_div(cputime_speedadj, delta_time);
        loadadjfreq = (unsigned int)cputime_speedadj * 100;
-       cpu_load = loadadjfreq / pcpu->target_freq;
+       cpu_load = loadadjfreq / pcpu->policy->cur;
        tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime;
 
        if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) {
@@ -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);
+                       down_write(&pcpu->policy->rwsem);
 
-                               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;
-                       }
-
-                       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,9 +600,20 @@ 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) {
                        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]);
@@ -781,7 +815,7 @@ static ssize_t store_hispeed_freq(struct cpufreq_interactive_tunables *tunables,
        int ret;
        long unsigned int val;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret < 0)
                return ret;
        tunables->hispeed_freq = val;
@@ -800,7 +834,7 @@ static ssize_t store_go_hispeed_load(struct cpufreq_interactive_tunables
        int ret;
        unsigned long val;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret < 0)
                return ret;
        tunables->go_hispeed_load = val;
@@ -819,7 +853,7 @@ static ssize_t store_min_sample_time(struct cpufreq_interactive_tunables
        int ret;
        unsigned long val;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret < 0)
                return ret;
        tunables->min_sample_time = val;
@@ -838,7 +872,7 @@ static ssize_t store_timer_rate(struct cpufreq_interactive_tunables *tunables,
        int ret;
        unsigned long val, val_round;
 
-       ret = strict_strtoul(buf, 0, &val);
+       ret = kstrtoul(buf, 0, &val);
        if (ret < 0)
                return ret;
 
@@ -1150,7 +1184,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                policy->governor_data = tunables;
                if (!have_governor_per_policy()) {
                        common_tunables = tunables;
-                       WARN_ON(cpufreq_get_global_kobject());
                }
 
                rc = sysfs_create_group(get_governor_parent_kobj(policy),
@@ -1160,7 +1193,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                        policy->governor_data = NULL;
                        if (!have_governor_per_policy()) {
                                common_tunables = NULL;
-                               cpufreq_put_global_kobject();
                        }
                        return rc;
                }
@@ -1184,9 +1216,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                        sysfs_remove_group(get_governor_parent_kobj(policy),
                                        get_sysfs_attr());
 
-                       if (!have_governor_per_policy())
-                               cpufreq_put_global_kobject();
-
                        kfree(tunables);
                        common_tunables = NULL;
                }