summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-08-08 15:26:26 +0100
committerJon Medhurst <tixy@linaro.org>2013-08-20 10:34:45 +0100
commit692ca4a307ee56809c86c55334a87909ce5e9fc9 (patch)
treee4f41bb70fc01c55a4c6b9d6b69078e89c1c4fb4
parent04d3b3bc2eba63f819d6242c678aa34b1b3cc98f (diff)
cpufreq: arm-big-little: don't use cpu_last_req_freq for MPtracking-iks-cpufreq-llct-20130829.0tracking-iks-cpufreq-llct-20130820.0
While getting support for In-Kernel-Switcher in big LITTLE cpufreq driver we introduced cpu_last_req_freq per-cpu variable that stores the last frequency requested for a cpu. It was important for IKS as CPUs in the same cluster can have separate struct cpufreq_policy associated with them and so cpufreq core may try to set different frequencies on both CPUs of same cluster. But for non-IKS solution or MP we don't need to cache last requested frequency. Currently there is a bug in code where if cpufreq_driver->get() is called for any cpu other than policy->cpu, we are returning 0, because we set cpu_last_req_freq only for policy->cpu and not for others. This problem could have been fixed by setting cpu_last_req_freq for all CPUs in policy->cpus, but that wouldn't be the best solution. Purpose of cpufreq_driver->get() is to get exact frequency from the hardware instead of returning cached frequency that was last requested as that is already present with the core. Hence, this patch forces only IKS to use cpu_last_req_freq and not MP. We will get the frequency from hardware when ->get() is called for MP. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r--drivers/cpufreq/arm_big_little.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index f589b6c7e9c2..54979aed6fbf 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -91,9 +91,14 @@ static unsigned int clk_get_cpu_rate(unsigned int cpu)
static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
{
- pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq, cpu));
+ if (is_bL_switching_enabled()) {
+ pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq,
+ cpu));
- return per_cpu(cpu_last_req_freq, cpu);
+ return per_cpu(cpu_last_req_freq, cpu);
+ } else {
+ return clk_get_cpu_rate(cpu);
+ }
}
static unsigned int
@@ -101,14 +106,15 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
{
u32 new_rate, prev_rate;
int ret;
+ bool bLs = is_bL_switching_enabled();
mutex_lock(&cluster_lock[new_cluster]);
- prev_rate = per_cpu(cpu_last_req_freq, cpu);
- per_cpu(cpu_last_req_freq, cpu) = rate;
- per_cpu(physical_cluster, cpu) = new_cluster;
+ if (bLs) {
+ prev_rate = per_cpu(cpu_last_req_freq, cpu);
+ per_cpu(cpu_last_req_freq, cpu) = rate;
+ per_cpu(physical_cluster, cpu) = new_cluster;
- if (is_bL_switching_enabled()) {
new_rate = find_cluster_maxfreq(new_cluster);
new_rate = ACTUAL_FREQ(new_cluster, new_rate);
} else {
@@ -122,8 +128,10 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
if (WARN_ON(ret)) {
pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
new_cluster);
- per_cpu(cpu_last_req_freq, cpu) = prev_rate;
- per_cpu(physical_cluster, cpu) = old_cluster;
+ if (bLs) {
+ per_cpu(cpu_last_req_freq, cpu) = prev_rate;
+ per_cpu(physical_cluster, cpu) = old_cluster;
+ }
mutex_unlock(&cluster_lock[new_cluster]);
@@ -461,7 +469,9 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = clk_get_cpu_rate(policy->cpu);
- per_cpu(cpu_last_req_freq, policy->cpu) = policy->cur;
+
+ if (is_bL_switching_enabled())
+ per_cpu(cpu_last_req_freq, policy->cpu) = policy->cur;
dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
return 0;