aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-05-01 20:08:53 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-16 16:07:44 -0400
commitecbc42b70acbc6327adefe9635db93fcf62bf59d (patch)
treed6a58bc7c9b615bb90f88ed5bbb7f6a5a38e3df5 /arch/sparc
parent1ca0c808c60f171c1949b0e7f3a4c0516855f7a0 (diff)
sparc32, sun4m: Implemented SMP IPIs support for SUN4M machines
Implement the three IPIs (resched, single and cpu-mask) generation and interrupt handler catch. The sun4m has 15 soft-IRQs and three of them is used with this patch, the three IPIs was previously implemented with the cross-call IRQ15 which does not work with locking routines such as spinlocks because IRQ15 is NMI, it may cause deadlock. The IRQ trap handler code assumes (in the same spritit as the old it seems) that hard interrupts will be generated until handled (level), when a IRQ happens the IRQ pending register is checked for pending soft-IRQs. When both hard and soft IRQ happens at the same time only soft-IRQs are handled. The old code implemented a soft-IRQ traphandler at IRQ14 which called smp_reschedule_irq which in turn called set_need_resched. It seems to be an old relic and is replaced with the interrupt traphander exit code RESTORE_ALL, it calls schedule() when appropriate. Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/kernel/entry.S29
-rw-r--r--arch/sparc/kernel/smp_32.c5
-rw-r--r--arch/sparc/kernel/sun4m_smp.c29
3 files changed, 54 insertions, 9 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index d759cf31c8ee..8341963f4c84 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -269,19 +269,22 @@ smp4m_ticker:
269 /* Here is where we check for possible SMP IPI passed to us 269 /* Here is where we check for possible SMP IPI passed to us
270 * on some level other than 15 which is the NMI and only used 270 * on some level other than 15 which is the NMI and only used
271 * for cross calls. That has a separate entry point below. 271 * for cross calls. That has a separate entry point below.
272 *
273 * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*.
272 */ 274 */
273maybe_smp4m_msg: 275maybe_smp4m_msg:
274 GET_PROCESSOR4M_ID(o3) 276 GET_PROCESSOR4M_ID(o3)
275 sethi %hi(sun4m_irq_percpu), %l5 277 sethi %hi(sun4m_irq_percpu), %l5
276 sll %o3, 2, %o3 278 sll %o3, 2, %o3
277 or %l5, %lo(sun4m_irq_percpu), %o5 279 or %l5, %lo(sun4m_irq_percpu), %o5
278 sethi %hi(0x40000000), %o2 280 sethi %hi(0x70000000), %o2 ! Check all soft-IRQs
279 ld [%o5 + %o3], %o1 281 ld [%o5 + %o3], %o1
280 ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending 282 ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
281 andcc %o3, %o2, %g0 283 andcc %o3, %o2, %g0
282 be,a smp4m_ticker 284 be,a smp4m_ticker
283 cmp %l7, 14 285 cmp %l7, 14
284 st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 286 /* Soft-IRQ IPI */
287 st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x70000000
285 WRITE_PAUSE 288 WRITE_PAUSE
286 ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending 289 ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
287 WRITE_PAUSE 290 WRITE_PAUSE
@@ -290,9 +293,27 @@ maybe_smp4m_msg:
290 WRITE_PAUSE 293 WRITE_PAUSE
291 wr %l4, PSR_ET, %psr 294 wr %l4, PSR_ET, %psr
292 WRITE_PAUSE 295 WRITE_PAUSE
293 call smp_reschedule_irq 296 sll %o2, 28, %o2 ! shift for simpler checks below
297maybe_smp4m_msg_check_single:
298 andcc %o2, 0x1, %g0
299 beq,a maybe_smp4m_msg_check_mask
300 andcc %o2, 0x2, %g0
301 call smp_call_function_single_interrupt
294 nop 302 nop
295 303 andcc %o2, 0x2, %g0
304maybe_smp4m_msg_check_mask:
305 beq,a maybe_smp4m_msg_check_resched
306 andcc %o2, 0x4, %g0
307 call smp_call_function_interrupt
308 nop
309 andcc %o2, 0x4, %g0
310maybe_smp4m_msg_check_resched:
311 /* rescheduling is done in RESTORE_ALL regardless, but incr stats */
312 beq,a maybe_smp4m_msg_out
313 nop
314 call smp_resched_interrupt
315 nop
316maybe_smp4m_msg_out:
296 RESTORE_ALL 317 RESTORE_ALL
297 318
298 .align 4 319 .align 4
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 2710602281de..705a94e1b8a5 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -267,11 +267,6 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
267 } 267 }
268} 268}
269 269
270void smp_reschedule_irq(void)
271{
272 set_need_resched();
273}
274
275void smp_flush_page_to_ram(unsigned long page) 270void smp_flush_page_to_ram(unsigned long page)
276{ 271{
277 /* Current theory is that those who call this are the one's 272 /* Current theory is that those who call this are the one's
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 5545d10d50cd..e2e687312e2e 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -15,6 +15,9 @@
15#include "irq.h" 15#include "irq.h"
16#include "kernel.h" 16#include "kernel.h"
17 17
18#define IRQ_IPI_SINGLE 12
19#define IRQ_IPI_MASK 13
20#define IRQ_IPI_RESCHED 14
18#define IRQ_CROSS_CALL 15 21#define IRQ_CROSS_CALL 15
19 22
20static inline unsigned long 23static inline unsigned long
@@ -26,6 +29,7 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
26 return val; 29 return val;
27} 30}
28 31
32static void smp4m_ipi_init(void);
29static void smp_setup_percpu_timer(void); 33static void smp_setup_percpu_timer(void);
30 34
31void __cpuinit smp4m_callin(void) 35void __cpuinit smp4m_callin(void)
@@ -81,6 +85,7 @@ void __cpuinit smp4m_callin(void)
81 */ 85 */
82void __init smp4m_boot_cpus(void) 86void __init smp4m_boot_cpus(void)
83{ 87{
88 smp4m_ipi_init();
84 smp_setup_percpu_timer(); 89 smp_setup_percpu_timer();
85 local_flush_cache_all(); 90 local_flush_cache_all();
86} 91}
@@ -148,6 +153,27 @@ void __init smp4m_smp_done(void)
148 /* Ok, they are spinning and ready to go. */ 153 /* Ok, they are spinning and ready to go. */
149} 154}
150 155
156
157/* Initialize IPIs on the SUN4M SMP machine */
158static void __init smp4m_ipi_init(void)
159{
160}
161
162static void smp4m_ipi_resched(int cpu)
163{
164 set_cpu_int(cpu, IRQ_IPI_RESCHED);
165}
166
167static void smp4m_ipi_single(int cpu)
168{
169 set_cpu_int(cpu, IRQ_IPI_SINGLE);
170}
171
172static void smp4m_ipi_mask_one(int cpu)
173{
174 set_cpu_int(cpu, IRQ_IPI_MASK);
175}
176
151static struct smp_funcall { 177static struct smp_funcall {
152 smpfunc_t func; 178 smpfunc_t func;
153 unsigned long arg1; 179 unsigned long arg1;
@@ -290,4 +316,7 @@ void __init sun4m_init_smp(void)
290 BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); 316 BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
291 BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); 317 BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
292 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); 318 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
319 BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
320 BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
321 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
293} 322}