[PATCH] ppc32: Bump PMU interrupt priority
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 27 Jun 2005 21:36:32 +0000 (14:36 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 27 Jun 2005 22:11:42 +0000 (15:11 -0700)
The Power Management Unit on PowerMacs is very sensitive to timeouts during
async message exchanges.  It uses rather crude protocol based on a shift
register with an interrupt and is almost continuously exchanging messages with
the host CPU on laptops.

This patch adds a routine to the open_pic driver to be able to select a PMU
driver so that it bumps it's interrupt priority to above the normal level.

This will allow PMU interrupts to occur while another interrupt is pending,
and thus reduce the risk of machine beeing abruptly shutdown by the PMU due to
a timeout in PMU communication caused by excessive interrupt latency.  The
problem is very rare, and usually just doesn't happen, but it is still useful
to make things even more robust.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/ppc/syslib/open_pic.c
drivers/macintosh/via-pmu.c
include/asm-ppc/open_pic.h

index b45d8268bf93e84619b1d44382d19688d11aa204..ad39b86ca92ca545c879c951307a05c3f0404208 100644 (file)
@@ -370,8 +370,9 @@ void __init openpic_init(int offset)
        /* Initialize IPI interrupts */
        if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
        for (i = 0; i < OPENPIC_NUM_IPI; i++) {
-               /* Disabled, Priority 10..13 */
-               openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
+               /* Disabled, increased priorities 10..13 */
+               openpic_initipi(i, OPENPIC_PRIORITY_IPI_BASE+i,
+                               OPENPIC_VEC_IPI+i+offset);
                /* IPIs are per-CPU */
                irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
                irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
@@ -399,8 +400,9 @@ void __init openpic_init(int offset)
                if (sense & IRQ_SENSE_MASK)
                        irq_desc[i+offset].status = IRQ_LEVEL;
 
-               /* Enabled, Priority 8 */
-               openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
+               /* Enabled, Default priority */
+               openpic_initirq(i, OPENPIC_PRIORITY_DEFAULT, i+offset,
+                               (sense & IRQ_POLARITY_MASK),
                                (sense & IRQ_SENSE_MASK));
                /* Processor 0 */
                openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
@@ -655,6 +657,18 @@ static void __init openpic_maptimer(u_int timer, cpumask_t cpumask)
                      cpus_addr(phys)[0]);
 }
 
+/*
+ * Change the priority of an interrupt
+ */
+void __init
+openpic_set_irq_priority(u_int irq, u_int pri)
+{
+       check_arg_irq(irq);
+       openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
+                               OPENPIC_PRIORITY_MASK,
+                               pri << OPENPIC_PRIORITY_SHIFT);
+}
+
 /*
  * Initalize the interrupt source which will generate an NMI.
  * This raises the interrupt's priority from 8 to 9.
@@ -665,9 +679,7 @@ void __init
 openpic_init_nmi_irq(u_int irq)
 {
        check_arg_irq(irq);
-       openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
-                               OPENPIC_PRIORITY_MASK,
-                               9 << OPENPIC_PRIORITY_SHIFT);
+       openpic_set_irq_priority(irq, OPENPIC_PRIORITY_NMI);
 }
 
 /*
index b941ee220997adbc96b50b48862d0e47c687afda..5375df03c6f3132e516fd6af1febb49d5fda8cba 100644 (file)
 #include <asm/backlight.h>
 #endif
 
+#ifdef CONFIG_PPC32
+#include <asm/open_pic.h>
+#endif
+
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
@@ -407,6 +411,12 @@ static int __init via_pmu_start(void)
        batt_req.complete = 1;
 #endif
 
+#ifdef CONFIG_PPC32
+       if (pmu_kind == PMU_KEYLARGO_BASED)
+               openpic_set_irq_priority(vias->intrs[0].line,
+                                        OPENPIC_PRIORITY_DEFAULT + 1);
+#endif
+
        if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU",
                        (void *)0)) {
                printk(KERN_ERR "VIA-PMU: can't get irq %d\n",
index dbe853319741e9e96049b7c6c6c9f089284e6ff6..7848aa610c05676ee8bb4f769718bdc1a852ffb4 100644 (file)
 #define OPENPIC_VEC_IPI                118     /* and up */
 #define OPENPIC_VEC_SPURIOUS   255
 
+/* Priorities */
+#define OPENPIC_PRIORITY_IPI_BASE      10
+#define OPENPIC_PRIORITY_DEFAULT       4
+#define OPENPIC_PRIORITY_NMI           9
+
 /* OpenPIC IRQ controller structure */
 extern struct hw_interrupt_type open_pic;
 
@@ -42,6 +47,7 @@ extern int epic_serial_mode;
 extern void openpic_set_sources(int first_irq, int num_irqs, void __iomem *isr);
 extern void openpic_init(int linux_irq_offset);
 extern void openpic_init_nmi_irq(u_int irq);
+extern void openpic_set_irq_priority(u_int irq, u_int pri);
 extern void openpic_hookup_cascade(u_int irq, char *name,
                                   int (*cascade_fn)(struct pt_regs *));
 extern u_int openpic_irq(void);