summaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sun4d_irq.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-05-02 00:08:54 +0000
committerDavid S. Miller <davem@davemloft.net>2011-05-16 13:07:44 -0700
commit55dd23eca666876e6028aa35d5e391cfced54871 (patch)
tree7f1006b68c8f04f4590c5442e5822b71d87e761d /arch/sparc/kernel/sun4d_irq.c
parentecbc42b70acbc6327adefe9635db93fcf62bf59d (diff)
downloadlinux-stable-55dd23eca666876e6028aa35d5e391cfced54871.tar.gz
linux-stable-55dd23eca666876e6028aa35d5e391cfced54871.tar.bz2
linux-stable-55dd23eca666876e6028aa35d5e391cfced54871.zip
sparc32, sun4d: Implemented SMP IPIs support for SUN4D machines
The sun4d does not seem to have a distingstion between soft and hard IRQs. When generating IPIs the generated IRQ looks like a hard IRQ, this patch adds a "IPI check" in the sun4d irq trap handler at a predefined IRQ number (SUN4D_IPI_IRQ). Before generating an IPI a per-cpu memory structure is modified for the "IPI check" to successfully detect a IPI request to a specific processor, the check clears the IPI work requested. All three IPIs (resched, single and cpu-mask) use the same IRQ number. The IPI IRQ should preferrably be on a separate IRQ and definitly not shared with IRQ handlers requesting IRQ with IRQF_SHARED. Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/sun4d_irq.c')
-rw-r--r--arch/sparc/kernel/sun4d_irq.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index b830914e32d3..a9ea60eb2c10 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -156,6 +156,15 @@ void sun4d_handler_irq(int pil, struct pt_regs *regs)
cc_set_iclr(1 << pil);
+#ifdef CONFIG_SMP
+ /*
+ * Check IPI data structures after IRQ has been cleared. Hard and Soft
+ * IRQ can happen at the same time, so both cases are always handled.
+ */
+ if (pil == SUN4D_IPI_IRQ)
+ sun4d_ipi_interrupt();
+#endif
+
old_regs = set_irq_regs(regs);
irq_enter();
if (sbusl == 0) {