aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-06-16 12:42:50 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-06-26 02:55:25 -0400
commitc4007a2fbf5f82b7e694c22b5929c87e38415a56 (patch)
tree9f959ef72a62eea0638cd2b1ed85a6b2e7fb3a70 /arch/powerpc/platforms
parentf97bb36f705da0a86b3ea77bfeee3415fee0b025 (diff)
powerpc: Use one common impl. of RTAS timebase sync and use raw spinlock
Several platforms use their own copy of what is essentially the same code, using RTAS to synchronize the timebases when bringing up new CPUs. This moves it all into a single common implementation and additionally turns the spinlock into a raw spinlock since the former can rely on the timebase not being frozen when spinlock debugging is enabled, and finally masks interrupts while the timebase is disabled. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/cell/smp.c30
-rw-r--r--arch/powerpc/platforms/chrp/smp.c33
-rw-r--r--arch/powerpc/platforms/pseries/smp.c30
3 files changed, 6 insertions, 87 deletions
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index 9046803c8276..bc97fada48c6 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -36,7 +36,6 @@
36#include <asm/prom.h> 36#include <asm/prom.h>
37#include <asm/smp.h> 37#include <asm/smp.h>
38#include <asm/paca.h> 38#include <asm/paca.h>
39#include <asm/time.h>
40#include <asm/machdep.h> 39#include <asm/machdep.h>
41#include <asm/cputable.h> 40#include <asm/cputable.h>
42#include <asm/firmware.h> 41#include <asm/firmware.h>
@@ -140,31 +139,6 @@ static void __devinit smp_cell_setup_cpu(int cpu)
140 mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER); 139 mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
141} 140}
142 141
143static DEFINE_SPINLOCK(timebase_lock);
144static unsigned long timebase = 0;
145
146static void __devinit cell_give_timebase(void)
147{
148 spin_lock(&timebase_lock);
149 rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
150 timebase = get_tb();
151 spin_unlock(&timebase_lock);
152
153 while (timebase)
154 barrier();
155 rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
156}
157
158static void __devinit cell_take_timebase(void)
159{
160 while (!timebase)
161 barrier();
162 spin_lock(&timebase_lock);
163 set_tb(timebase >> 32, timebase & 0xffffffff);
164 timebase = 0;
165 spin_unlock(&timebase_lock);
166}
167
168static void __devinit smp_cell_kick_cpu(int nr) 142static void __devinit smp_cell_kick_cpu(int nr)
169{ 143{
170 BUG_ON(nr < 0 || nr >= NR_CPUS); 144 BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -224,8 +198,8 @@ void __init smp_init_cell(void)
224 198
225 /* Non-lpar has additional take/give timebase */ 199 /* Non-lpar has additional take/give timebase */
226 if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { 200 if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
227 smp_ops->give_timebase = cell_give_timebase; 201 smp_ops->give_timebase = rtas_give_timebase;
228 smp_ops->take_timebase = cell_take_timebase; 202 smp_ops->take_timebase = rtas_take_timebase;
229 } 203 }
230 204
231 DBG(" <- smp_init_cell()\n"); 205 DBG(" <- smp_init_cell()\n");
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
index 10a4a4d063b6..02cafecc90e3 100644
--- a/arch/powerpc/platforms/chrp/smp.c
+++ b/arch/powerpc/platforms/chrp/smp.c
@@ -26,7 +26,6 @@
26#include <asm/io.h> 26#include <asm/io.h>
27#include <asm/prom.h> 27#include <asm/prom.h>
28#include <asm/smp.h> 28#include <asm/smp.h>
29#include <asm/time.h>
30#include <asm/machdep.h> 29#include <asm/machdep.h>
31#include <asm/mpic.h> 30#include <asm/mpic.h>
32#include <asm/rtas.h> 31#include <asm/rtas.h>
@@ -42,40 +41,12 @@ static void __devinit smp_chrp_setup_cpu(int cpu_nr)
42 mpic_setup_this_cpu(); 41 mpic_setup_this_cpu();
43} 42}
44 43
45static DEFINE_SPINLOCK(timebase_lock);
46static unsigned int timebase_upper = 0, timebase_lower = 0;
47
48void __devinit smp_chrp_give_timebase(void)
49{
50 spin_lock(&timebase_lock);
51 rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
52 timebase_upper = get_tbu();
53 timebase_lower = get_tbl();
54 spin_unlock(&timebase_lock);
55
56 while (timebase_upper || timebase_lower)
57 barrier();
58 rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
59}
60
61void __devinit smp_chrp_take_timebase(void)
62{
63 while (!(timebase_upper || timebase_lower))
64 barrier();
65 spin_lock(&timebase_lock);
66 set_tb(timebase_upper, timebase_lower);
67 timebase_upper = 0;
68 timebase_lower = 0;
69 spin_unlock(&timebase_lock);
70 printk("CPU %i taken timebase\n", smp_processor_id());
71}
72
73/* CHRP with openpic */ 44/* CHRP with openpic */
74struct smp_ops_t chrp_smp_ops = { 45struct smp_ops_t chrp_smp_ops = {
75 .message_pass = smp_mpic_message_pass, 46 .message_pass = smp_mpic_message_pass,
76 .probe = smp_mpic_probe, 47 .probe = smp_mpic_probe,
77 .kick_cpu = smp_chrp_kick_cpu, 48 .kick_cpu = smp_chrp_kick_cpu,
78 .setup_cpu = smp_chrp_setup_cpu, 49 .setup_cpu = smp_chrp_setup_cpu,
79 .give_timebase = smp_chrp_give_timebase, 50 .give_timebase = rtas_give_timebase,
80 .take_timebase = smp_chrp_take_timebase, 51 .take_timebase = rtas_take_timebase,
81}; 52};
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 1a231c389ba0..1f8f6cfb94f7 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -35,7 +35,6 @@
35#include <asm/prom.h> 35#include <asm/prom.h>
36#include <asm/smp.h> 36#include <asm/smp.h>
37#include <asm/paca.h> 37#include <asm/paca.h>
38#include <asm/time.h>
39#include <asm/machdep.h> 38#include <asm/machdep.h>
40#include <asm/cputable.h> 39#include <asm/cputable.h>
41#include <asm/firmware.h> 40#include <asm/firmware.h>
@@ -118,31 +117,6 @@ static void __devinit smp_xics_setup_cpu(int cpu)
118} 117}
119#endif /* CONFIG_XICS */ 118#endif /* CONFIG_XICS */
120 119
121static DEFINE_SPINLOCK(timebase_lock);
122static unsigned long timebase = 0;
123
124static void __devinit pSeries_give_timebase(void)
125{
126 spin_lock(&timebase_lock);
127 rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
128 timebase = get_tb();
129 spin_unlock(&timebase_lock);
130
131 while (timebase)
132 barrier();
133 rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
134}
135
136static void __devinit pSeries_take_timebase(void)
137{
138 while (!timebase)
139 barrier();
140 spin_lock(&timebase_lock);
141 set_tb(timebase >> 32, timebase & 0xffffffff);
142 timebase = 0;
143 spin_unlock(&timebase_lock);
144}
145
146static void __devinit smp_pSeries_kick_cpu(int nr) 120static void __devinit smp_pSeries_kick_cpu(int nr)
147{ 121{
148 BUG_ON(nr < 0 || nr >= NR_CPUS); 122 BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -209,8 +183,8 @@ static void __init smp_init_pseries(void)
209 183
210 /* Non-lpar has additional take/give timebase */ 184 /* Non-lpar has additional take/give timebase */
211 if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { 185 if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
212 smp_ops->give_timebase = pSeries_give_timebase; 186 smp_ops->give_timebase = rtas_give_timebase;
213 smp_ops->take_timebase = pSeries_take_timebase; 187 smp_ops->take_timebase = rtas_take_timebase;
214 } 188 }
215 189
216 pr_debug(" <- smp_init_pSeries()\n"); 190 pr_debug(" <- smp_init_pSeries()\n");