From 3bccf467727c82421e5f7b630c9bb864ebe8d2e6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 27 Jan 2012 17:49:16 +0900 Subject: [PATCH] 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 --- arch/sh/kernel/cpufreq.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index 0fffacea6ed9..8203865e16b7 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 #include /* set_cpus_allowed() */ #include +#include +#include -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; }