MT bulletproofing.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 31c38c4..5db67e3 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -33,6 +33,7 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/system.h>
 
 static int mips_cpu_irq_base;
@@ -76,7 +77,7 @@
 	return 0;
 }
 
-#define	mips_cpu_irq_shutdown	mips_cpu_irq_disable
+#define	mips_cpu_irq_shutdown		mips_cpu_irq_disable
 
 /*
  * While we ack the interrupt interrupts are disabled and thus we don't need
@@ -84,9 +85,6 @@
  */
 static void mips_cpu_irq_ack(unsigned int irq)
 {
-	/* Only necessary for soft interrupts */
-	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
-
 	mask_mips_irq(irq);
 }
 
@@ -97,15 +95,60 @@
 }
 
 static hw_irq_controller mips_cpu_irq_controller = {
-	.typename = "MIPS",
-	.startup = mips_cpu_irq_startup,
-	.shutdown = mips_cpu_irq_shutdown,
-	.enable = mips_cpu_irq_enable,
-	.disable = mips_cpu_irq_disable,
-	.ack = mips_cpu_irq_ack,
-	.end = mips_cpu_irq_end,
+	.typename	= "MIPS",
+	.startup	= mips_cpu_irq_startup,
+	.shutdown	= mips_cpu_irq_shutdown,
+	.enable		= mips_cpu_irq_enable,
+	.disable	= mips_cpu_irq_disable,
+	.ack		= mips_cpu_irq_ack,
+	.end		= mips_cpu_irq_end,
 };
 
+/*
+ * Basically the same as above but taking care of all the MT stuff
+ */
+
+#define unmask_mips_mt_irq	unmask_mips_irq
+#define mask_mips_mt_irq	mask_mips_irq
+#define mips_mt_cpu_irq_enable	mips_cpu_irq_enable
+#define mips_mt_cpu_irq_disable	mips_cpu_irq_disable
+
+static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
+{
+	unsigned int vpflags = dvpe();
+
+	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+	evpe(vpflags);
+	mips_mt_cpu_irq_enable(irq);
+
+	return 0;
+}
+
+#define	mips_mt_cpu_irq_shutdown	mips_mt_cpu_irq_disable
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for mips_cpu_irq_end.
+ */
+static void mips_mt_cpu_irq_ack(unsigned int irq)
+{
+	unsigned int vpflags = dvpe();
+	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+	evpe(vpflags);
+	mask_mips_mt_irq(irq);
+}
+
+#define mips_mt_cpu_irq_end mips_cpu_irq_end
+
+static hw_irq_controller mips_mt_cpu_irq_controller = {
+	.typename	= "MIPS",
+	.startup	= mips_mt_cpu_irq_startup,
+	.shutdown	= mips_mt_cpu_irq_shutdown,
+	.enable		= mips_mt_cpu_irq_enable,
+	.disable	= mips_mt_cpu_irq_disable,
+	.ack		= mips_mt_cpu_irq_ack,
+	.end		= mips_mt_cpu_irq_end,
+};
 
 void __init mips_cpu_irq_init(int irq_base)
 {
@@ -115,7 +158,19 @@
 	clear_c0_status(ST0_IM);
 	clear_c0_cause(CAUSEF_IP);
 
-	for (i = irq_base; i < irq_base + 8; i++) {
+	/*
+	 * Only MT is using the software interrupts currently, so we just
+	 * leave them uninitialized for other processors.
+	 */
+	if (cpu_has_mipsmt)
+		for (i = irq_base; i < irq_base + 2; i++) {
+			irq_desc[i].status = IRQ_DISABLED;
+			irq_desc[i].action = NULL;
+			irq_desc[i].depth = 1;
+			irq_desc[i].handler = &mips_mt_cpu_irq_controller;
+		}
+
+	for (i = irq_base + 2; i < irq_base + 8; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;