diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-01-27 17:49:16 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-27 17:49:16 +0900 |
commit | 3bccf467727c82421e5f7b630c9bb864ebe8d2e6 (patch) | |
tree | 66e692cc557dbbf87fbd11de651a5ee21e5016e0 | |
parent | 74ea15d909b31158f9b63190a95b52bc05586d4b (diff) | |
download | op-kernel-dev-3bccf467727c82421e5f7b630c9bb864ebe8d2e6.zip op-kernel-dev-3bccf467727c82421e5f7b630c9bb864ebe8d2e6.tar.gz |
sh: cpufreq: percpu struct clk accounting.
At the moment there is simply a global struct clk pointer for the CPU
frequency, which is fundamentally broken in the SMP case. This moves to
fix it up by switching to a percpu case.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/kernel/cpufreq.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index 0ffface..8203865 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c @@ -3,7 +3,7 @@ * * cpufreq driver for the SuperH processors. * - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2012 Paul Mundt * Copyright (C) 2002 M. R. Brown * * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c @@ -24,12 +24,14 @@ #include <linux/smp.h> #include <linux/sched.h> /* set_cpus_allowed() */ #include <linux/clk.h> +#include <linux/percpu.h> +#include <linux/sh_clk.h> -static struct clk *cpuclk; +static DEFINE_PER_CPU(struct clk, sh_cpuclk); static unsigned int sh_cpufreq_get(unsigned int cpu) { - return (clk_get_rate(cpuclk) + 500) / 1000; + return (clk_get_rate(&per_cpu(sh_cpuclk, cpu)) + 500) / 1000; } /* @@ -40,6 +42,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, unsigned int relation) { unsigned int cpu = policy->cpu; + struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); cpumask_t cpus_allowed; struct cpufreq_freqs freqs; long freq; @@ -77,13 +80,15 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) { - if (!cpu_online(policy->cpu)) + unsigned int cpu = policy->cpu; + struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); + + if (!cpu_online(cpu)) return -ENODEV; cpuclk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpuclk)) { - printk(KERN_ERR "cpufreq: couldn't get CPU#%d clk\n", - policy->cpu); + printk(KERN_ERR "cpufreq: couldn't get CPU#%d clk\n", cpu); return PTR_ERR(cpuclk); } @@ -92,7 +97,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = sh_cpufreq_get(policy->cpu); + policy->cur = sh_cpufreq_get(cpu); policy->min = policy->cpuinfo.min_freq; policy->max = policy->cpuinfo.max_freq; @@ -102,7 +107,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) */ if (unlikely(policy->min == policy->max)) { printk(KERN_ERR "cpufreq: clock framework rate rounding " - "not supported on CPU#%d.\n", policy->cpu); + "not supported on CPU#%d.\n", cpu); clk_put(cpuclk); return -EINVAL; @@ -110,7 +115,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) printk(KERN_INFO "cpufreq: CPU#%d Frequencies - Minimum %u.%03u MHz, " "Maximum %u.%03u MHz.\n", - policy->cpu, policy->min / 1000, policy->min % 1000, + cpu, policy->min / 1000, policy->min % 1000, policy->max / 1000, policy->max % 1000); return 0; @@ -125,6 +130,7 @@ static int sh_cpufreq_verify(struct cpufreq_policy *policy) static int sh_cpufreq_exit(struct cpufreq_policy *policy) { + struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu); clk_put(cpuclk); return 0; } |