diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-01-27 03:49:16 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-27 03:49:16 -0500 |
commit | 3bccf467727c82421e5f7b630c9bb864ebe8d2e6 (patch) | |
tree | 66e692cc557dbbf87fbd11de651a5ee21e5016e0 /arch/sh/kernel/cpufreq.c | |
parent | 74ea15d909b31158f9b63190a95b52bc05586d4b (diff) |
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>
Diffstat (limited to 'arch/sh/kernel/cpufreq.c')
-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 0fffacea6ed9..8203865e16b7 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * cpufreq driver for the SuperH processors. | 4 | * cpufreq driver for the SuperH processors. |
5 | * | 5 | * |
6 | * Copyright (C) 2002 - 2007 Paul Mundt | 6 | * Copyright (C) 2002 - 2012 Paul Mundt |
7 | * Copyright (C) 2002 M. R. Brown | 7 | * Copyright (C) 2002 M. R. Brown |
8 | * | 8 | * |
9 | * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c | 9 | * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c |
@@ -24,12 +24,14 @@ | |||
24 | #include <linux/smp.h> | 24 | #include <linux/smp.h> |
25 | #include <linux/sched.h> /* set_cpus_allowed() */ | 25 | #include <linux/sched.h> /* set_cpus_allowed() */ |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/percpu.h> | ||
28 | #include <linux/sh_clk.h> | ||
27 | 29 | ||
28 | static struct clk *cpuclk; | 30 | static DEFINE_PER_CPU(struct clk, sh_cpuclk); |
29 | 31 | ||
30 | static unsigned int sh_cpufreq_get(unsigned int cpu) | 32 | static unsigned int sh_cpufreq_get(unsigned int cpu) |
31 | { | 33 | { |
32 | return (clk_get_rate(cpuclk) + 500) / 1000; | 34 | return (clk_get_rate(&per_cpu(sh_cpuclk, cpu)) + 500) / 1000; |
33 | } | 35 | } |
34 | 36 | ||
35 | /* | 37 | /* |
@@ -40,6 +42,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, | |||
40 | unsigned int relation) | 42 | unsigned int relation) |
41 | { | 43 | { |
42 | unsigned int cpu = policy->cpu; | 44 | unsigned int cpu = policy->cpu; |
45 | struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); | ||
43 | cpumask_t cpus_allowed; | 46 | cpumask_t cpus_allowed; |
44 | struct cpufreq_freqs freqs; | 47 | struct cpufreq_freqs freqs; |
45 | long freq; | 48 | long freq; |
@@ -77,13 +80,15 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, | |||
77 | 80 | ||
78 | static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) | 81 | static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) |
79 | { | 82 | { |
80 | if (!cpu_online(policy->cpu)) | 83 | unsigned int cpu = policy->cpu; |
84 | struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); | ||
85 | |||
86 | if (!cpu_online(cpu)) | ||
81 | return -ENODEV; | 87 | return -ENODEV; |
82 | 88 | ||
83 | cpuclk = clk_get(NULL, "cpu_clk"); | 89 | cpuclk = clk_get(NULL, "cpu_clk"); |
84 | if (IS_ERR(cpuclk)) { | 90 | if (IS_ERR(cpuclk)) { |
85 | printk(KERN_ERR "cpufreq: couldn't get CPU#%d clk\n", | 91 | printk(KERN_ERR "cpufreq: couldn't get CPU#%d clk\n", cpu); |
86 | policy->cpu); | ||
87 | return PTR_ERR(cpuclk); | 92 | return PTR_ERR(cpuclk); |
88 | } | 93 | } |
89 | 94 | ||
@@ -92,7 +97,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
92 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | 97 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; |
93 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 98 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
94 | 99 | ||
95 | policy->cur = sh_cpufreq_get(policy->cpu); | 100 | policy->cur = sh_cpufreq_get(cpu); |
96 | policy->min = policy->cpuinfo.min_freq; | 101 | policy->min = policy->cpuinfo.min_freq; |
97 | policy->max = policy->cpuinfo.max_freq; | 102 | policy->max = policy->cpuinfo.max_freq; |
98 | 103 | ||
@@ -102,7 +107,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
102 | */ | 107 | */ |
103 | if (unlikely(policy->min == policy->max)) { | 108 | if (unlikely(policy->min == policy->max)) { |
104 | printk(KERN_ERR "cpufreq: clock framework rate rounding " | 109 | printk(KERN_ERR "cpufreq: clock framework rate rounding " |
105 | "not supported on CPU#%d.\n", policy->cpu); | 110 | "not supported on CPU#%d.\n", cpu); |
106 | 111 | ||
107 | clk_put(cpuclk); | 112 | clk_put(cpuclk); |
108 | return -EINVAL; | 113 | return -EINVAL; |
@@ -110,7 +115,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
110 | 115 | ||
111 | printk(KERN_INFO "cpufreq: CPU#%d Frequencies - Minimum %u.%03u MHz, " | 116 | printk(KERN_INFO "cpufreq: CPU#%d Frequencies - Minimum %u.%03u MHz, " |
112 | "Maximum %u.%03u MHz.\n", | 117 | "Maximum %u.%03u MHz.\n", |
113 | policy->cpu, policy->min / 1000, policy->min % 1000, | 118 | cpu, policy->min / 1000, policy->min % 1000, |
114 | policy->max / 1000, policy->max % 1000); | 119 | policy->max / 1000, policy->max % 1000); |
115 | 120 | ||
116 | return 0; | 121 | return 0; |
@@ -125,6 +130,7 @@ static int sh_cpufreq_verify(struct cpufreq_policy *policy) | |||
125 | 130 | ||
126 | static int sh_cpufreq_exit(struct cpufreq_policy *policy) | 131 | static int sh_cpufreq_exit(struct cpufreq_policy *policy) |
127 | { | 132 | { |
133 | struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu); | ||
128 | clk_put(cpuclk); | 134 | clk_put(cpuclk); |
129 | return 0; | 135 | return 0; |
130 | } | 136 | } |