aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2012-12-17 11:19:03 +0530
committerAndrey Konovalov <andrey.konovalov@linaro.org>2013-05-25 13:26:45 +0400
commit59cb463c6cf42c9ea62d119043aa79ac6d297af3 (patch)
treefa85502d5b6092302e5e3319a8290d134a039378
parent4ab8c79c504746b000abfdc12771423579281e44 (diff)
cpufreq: vexpress: Re-check freq of old_cluster on cpu migration
Consider following scenario: - current freq of CPU 0 & 1: 1 GHz, both on cluster A7 - request: CPU0 to 700 MHz (we don't change freq as max is 1 GHz) - request: CPU1 to 2 GHz, we migrate CPU1 to cluster A15. At this point we could have reduced frequency of cluster A7 to 700 MHz, as it is the max now. This patch does it. :) Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/cpufreq/arm_big_little.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 851deccd738..b8a6f17db93 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -110,27 +110,45 @@ static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
return per_cpu(cpu_last_req_freq, cpu);
}
-static unsigned int bL_cpufreq_set_rate(u32 cpu, u32 cluster, u32 rate)
+static unsigned int
+bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
{
u32 max_rate, actual_rate;
int ret;
if (is_bL_switching_enabled()) {
- max_rate = find_cluster_maxfreq(cpu, cluster, rate);
- actual_rate = ACTUAL_FREQ(cluster, max_rate);
+ max_rate = find_cluster_maxfreq(cpu, new_cluster, rate);
+ actual_rate = ACTUAL_FREQ(new_cluster, max_rate);
} else {
actual_rate = max_rate = rate;
}
- pr_debug("%s: cpu: %d, cluster: %d, freq: %d\n", __func__, cpu, cluster,
- actual_rate);
+ pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
+ __func__, cpu, old_cluster, new_cluster, actual_rate);
- ret = clk_set_rate(clk[cluster], actual_rate * 1000);
+ ret = clk_set_rate(clk[new_cluster], actual_rate * 1000);
if (ret) {
- pr_err("clk_set_rate failed: %d\n", ret);
+ pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
+ new_cluster);
return ret;
}
+ /* Recalc freq for old cluster when switching clusters */
+ if (old_cluster != new_cluster) {
+ max_rate = find_cluster_maxfreq(cpu, old_cluster, 0);
+ max_rate = ACTUAL_FREQ(old_cluster, max_rate);
+
+ /* Set freq of old cluster if there are cpus left on it */
+ if (max_rate) {
+ pr_debug("%s: Updating rate of old cluster: %d, to freq: %d\n",
+ __func__, old_cluster, max_rate);
+
+ if (clk_set_rate(clk[old_cluster], max_rate * 1000))
+ pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n",
+ __func__, ret, old_cluster);
+ }
+ }
+
per_cpu(cpu_last_req_freq, cpu) = rate;
return 0;
}
@@ -185,7 +203,7 @@ static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
for_each_cpu(freqs.cpu, policy->cpus)
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- ret = bL_cpufreq_set_rate(cpu, new_cluster, freqs.new);
+ ret = bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs.new);
if (ret)
return ret;