MIPS: Oprofile: Fixup the loose ends in the plumbing.
[linux-2.6.git] / arch / mips / kernel / time.c
index 07e125c027b2eb81a56d060c49c90a2bef0110ec..7050b4ffffcd34a992c6c99293cdb18d59fea15e 100644 (file)
@@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
        return IRQ_HANDLED;
 }
 
+int null_perf_irq(struct pt_regs *regs)
+{
+       return 0;
+}
+
+int (*perf_irq)(struct pt_regs *regs) = null_perf_irq;
+
+EXPORT_SYMBOL(null_perf_irq);
+EXPORT_SYMBOL(perf_irq);
+
 asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
 {
 asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
 {
+       int r2 = cpu_has_mips_r2;
+
        irq_enter();
        kstat_this_cpu.irqs[irq]++;
 
        irq_enter();
        kstat_this_cpu.irqs[irq]++;
 
+       /*
+        * Suckage alert:
+        * Before R2 of the architecture there was no way to see if a
+        * performance counter interrupt was pending, so we have to run the
+        * performance counter interrupt handler anyway.
+        */
+       if (!r2 || (read_c0_cause() & (1 << 26)))
+               if (perf_irq(regs))
+                       goto out;
+
        /* we keep interrupt disabled all the time */
        /* we keep interrupt disabled all the time */
-       timer_interrupt(irq, NULL, regs);
+       if (!r2 || (read_c0_cause() & (1 << 30)))
+               timer_interrupt(irq, NULL, regs);
 
 
+out:
        irq_exit();
 }
 
        irq_exit();
 }