summaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/sun4m_smp.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-05-02 00:08:53 +0000
committerDavid S. Miller <davem@davemloft.net>2011-05-16 13:07:44 -0700
commitecbc42b70acbc6327adefe9635db93fcf62bf59d (patch)
treed6a58bc7c9b615bb90f88ed5bbb7f6a5a38e3df5 /arch/sparc/kernel/sun4m_smp.c
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/kernel/sun4m_smp.c')
-rw-r--r--arch/sparc/kernel/sun4m_smp.c29
1 files changed, 29 insertions, 0 deletions
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 @@
#include "irq.h"
#include "kernel.h"
+#define IRQ_IPI_SINGLE 12
+#define IRQ_IPI_MASK 13
+#define IRQ_IPI_RESCHED 14
#define IRQ_CROSS_CALL 15
static inline unsigned long
@@ -26,6 +29,7 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
return val;
}
+static void smp4m_ipi_init(void);
static void smp_setup_percpu_timer(void);
void __cpuinit smp4m_callin(void)
@@ -81,6 +85,7 @@ void __cpuinit smp4m_callin(void)
*/
void __init smp4m_boot_cpus(void)
{
+ smp4m_ipi_init();
smp_setup_percpu_timer();
local_flush_cache_all();
}
@@ -148,6 +153,27 @@ void __init smp4m_smp_done(void)
/* Ok, they are spinning and ready to go. */
}
+
+/* Initialize IPIs on the SUN4M SMP machine */
+static void __init smp4m_ipi_init(void)
+{
+}
+
+static void smp4m_ipi_resched(int cpu)
+{
+ set_cpu_int(cpu, IRQ_IPI_RESCHED);
+}
+
+static void smp4m_ipi_single(int cpu)
+{
+ set_cpu_int(cpu, IRQ_IPI_SINGLE);
+}
+
+static void smp4m_ipi_mask_one(int cpu)
+{
+ set_cpu_int(cpu, IRQ_IPI_MASK);
+}
+
static struct smp_funcall {
smpfunc_t func;
unsigned long arg1;
@@ -290,4 +316,7 @@ void __init sun4m_init_smp(void)
BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
}