diff options
Diffstat (limited to 'arch/sparc/kernel/sun4d_smp.c')
-rw-r--r-- | arch/sparc/kernel/sun4d_smp.c | 93 |
1 files changed, 85 insertions, 8 deletions
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 475d50b96cd0..133387980b56 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c | |||
@@ -32,6 +32,7 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon | |||
32 | return val; | 32 | return val; |
33 | } | 33 | } |
34 | 34 | ||
35 | static void smp4d_ipi_init(void); | ||
35 | static void smp_setup_percpu_timer(void); | 36 | static void smp_setup_percpu_timer(void); |
36 | 37 | ||
37 | static unsigned char cpu_leds[32]; | 38 | static unsigned char cpu_leds[32]; |
@@ -80,8 +81,6 @@ void __cpuinit smp4d_callin(void) | |||
80 | local_flush_cache_all(); | 81 | local_flush_cache_all(); |
81 | local_flush_tlb_all(); | 82 | local_flush_tlb_all(); |
82 | 83 | ||
83 | cpu_probe(); | ||
84 | |||
85 | while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) | 84 | while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) |
86 | barrier(); | 85 | barrier(); |
87 | 86 | ||
@@ -105,7 +104,7 @@ void __cpuinit smp4d_callin(void) | |||
105 | 104 | ||
106 | local_irq_enable(); /* We don't allow PIL 14 yet */ | 105 | local_irq_enable(); /* We don't allow PIL 14 yet */ |
107 | 106 | ||
108 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 107 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
109 | barrier(); | 108 | barrier(); |
110 | 109 | ||
111 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 110 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
@@ -120,6 +119,7 @@ void __cpuinit smp4d_callin(void) | |||
120 | */ | 119 | */ |
121 | void __init smp4d_boot_cpus(void) | 120 | void __init smp4d_boot_cpus(void) |
122 | { | 121 | { |
122 | smp4d_ipi_init(); | ||
123 | if (boot_cpu_id) | 123 | if (boot_cpu_id) |
124 | current_set[0] = NULL; | 124 | current_set[0] = NULL; |
125 | smp_setup_percpu_timer(); | 125 | smp_setup_percpu_timer(); |
@@ -191,6 +191,80 @@ void __init smp4d_smp_done(void) | |||
191 | sun4d_distribute_irqs(); | 191 | sun4d_distribute_irqs(); |
192 | } | 192 | } |
193 | 193 | ||
194 | /* Memory structure giving interrupt handler information about IPI generated */ | ||
195 | struct sun4d_ipi_work { | ||
196 | int single; | ||
197 | int msk; | ||
198 | int resched; | ||
199 | }; | ||
200 | |||
201 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work); | ||
202 | |||
203 | /* Initialize IPIs on the SUN4D SMP machine */ | ||
204 | static void __init smp4d_ipi_init(void) | ||
205 | { | ||
206 | int cpu; | ||
207 | struct sun4d_ipi_work *work; | ||
208 | |||
209 | printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ); | ||
210 | |||
211 | for_each_possible_cpu(cpu) { | ||
212 | work = &per_cpu(sun4d_ipi_work, cpu); | ||
213 | work->single = work->msk = work->resched = 0; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | void sun4d_ipi_interrupt(void) | ||
218 | { | ||
219 | struct sun4d_ipi_work *work = &__get_cpu_var(sun4d_ipi_work); | ||
220 | |||
221 | if (work->single) { | ||
222 | work->single = 0; | ||
223 | smp_call_function_single_interrupt(); | ||
224 | } | ||
225 | if (work->msk) { | ||
226 | work->msk = 0; | ||
227 | smp_call_function_interrupt(); | ||
228 | } | ||
229 | if (work->resched) { | ||
230 | work->resched = 0; | ||
231 | smp_resched_interrupt(); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | static void smp4d_ipi_single(int cpu) | ||
236 | { | ||
237 | struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); | ||
238 | |||
239 | /* Mark work */ | ||
240 | work->single = 1; | ||
241 | |||
242 | /* Generate IRQ on the CPU */ | ||
243 | sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); | ||
244 | } | ||
245 | |||
246 | static void smp4d_ipi_mask_one(int cpu) | ||
247 | { | ||
248 | struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); | ||
249 | |||
250 | /* Mark work */ | ||
251 | work->msk = 1; | ||
252 | |||
253 | /* Generate IRQ on the CPU */ | ||
254 | sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); | ||
255 | } | ||
256 | |||
257 | static void smp4d_ipi_resched(int cpu) | ||
258 | { | ||
259 | struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); | ||
260 | |||
261 | /* Mark work */ | ||
262 | work->resched = 1; | ||
263 | |||
264 | /* Generate IRQ on the CPU (any IRQ will cause resched) */ | ||
265 | sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); | ||
266 | } | ||
267 | |||
194 | static struct smp_funcall { | 268 | static struct smp_funcall { |
195 | smpfunc_t func; | 269 | smpfunc_t func; |
196 | unsigned long arg1; | 270 | unsigned long arg1; |
@@ -239,10 +313,10 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
239 | { | 313 | { |
240 | register int i; | 314 | register int i; |
241 | 315 | ||
242 | cpu_clear(smp_processor_id(), mask); | 316 | cpumask_clear_cpu(smp_processor_id(), &mask); |
243 | cpus_and(mask, cpu_online_map, mask); | 317 | cpumask_and(&mask, cpu_online_mask, &mask); |
244 | for (i = 0; i <= high; i++) { | 318 | for (i = 0; i <= high; i++) { |
245 | if (cpu_isset(i, mask)) { | 319 | if (cpumask_test_cpu(i, &mask)) { |
246 | ccall_info.processors_in[i] = 0; | 320 | ccall_info.processors_in[i] = 0; |
247 | ccall_info.processors_out[i] = 0; | 321 | ccall_info.processors_out[i] = 0; |
248 | sun4d_send_ipi(i, IRQ_CROSS_CALL); | 322 | sun4d_send_ipi(i, IRQ_CROSS_CALL); |
@@ -255,7 +329,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
255 | 329 | ||
256 | i = 0; | 330 | i = 0; |
257 | do { | 331 | do { |
258 | if (!cpu_isset(i, mask)) | 332 | if (!cpumask_test_cpu(i, &mask)) |
259 | continue; | 333 | continue; |
260 | while (!ccall_info.processors_in[i]) | 334 | while (!ccall_info.processors_in[i]) |
261 | barrier(); | 335 | barrier(); |
@@ -263,7 +337,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
263 | 337 | ||
264 | i = 0; | 338 | i = 0; |
265 | do { | 339 | do { |
266 | if (!cpu_isset(i, mask)) | 340 | if (!cpumask_test_cpu(i, &mask)) |
267 | continue; | 341 | continue; |
268 | while (!ccall_info.processors_out[i]) | 342 | while (!ccall_info.processors_out[i]) |
269 | barrier(); | 343 | barrier(); |
@@ -356,6 +430,9 @@ void __init sun4d_init_smp(void) | |||
356 | BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); | 430 | BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); |
357 | BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); | 431 | BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); |
358 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); | 432 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); |
433 | BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM); | ||
434 | BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM); | ||
435 | BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM); | ||
359 | 436 | ||
360 | for (i = 0; i < NR_CPUS; i++) { | 437 | for (i = 0; i < NR_CPUS; i++) { |
361 | ccall_info.processors_in[i] = 1; | 438 | ccall_info.processors_in[i] = 1; |