MT bulletproofing.
Ralf Baechle [Wed, 17 Aug 2005 13:44:26 +0000 (13:44 +0000)]
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

arch/mips/kernel/irq_cpu.c
arch/mips/kernel/traps.c

index 31c38c4..5db67e3 100644 (file)
@@ -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 @@ static unsigned int mips_cpu_irq_startup(unsigned int irq)
        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 unsigned int mips_cpu_irq_startup(unsigned int irq)
  */
 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 void mips_cpu_irq_end(unsigned int irq)
 }
 
 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 @@ void __init mips_cpu_irq_init(int irq_base)
        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;
index 519b8f1..876aff7 100644 (file)
@@ -1186,8 +1186,14 @@ void __init per_cpu_trap_init(void)
                /* Setting vector spacing enables EI/VI mode  */
                change_c0_intctl (0x3e0, VECTORSPACING);
        }
-       if (cpu_has_divec)
-               set_c0_cause(CAUSEF_IV);
+       if (cpu_has_divec) {
+               if (cpu_has_mipsmt) {
+                       unsigned int vpflags = dvpe();
+                       set_c0_cause(CAUSEF_IV);
+                       evpe(vpflags);
+               } else
+                       set_c0_cause(CAUSEF_IV);
+       }
 
        cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
        TLBMISS_HANDLER_SETUP();