aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-06-27 17:36:32 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-27 18:11:42 -0400
commite4ee69c8c1e7ff9790fbce29c7be50db57323a6f (patch)
treeba6bfdc216de500f3b3c7c1613c50efb7d550dba
parentbb1657468152c5e5232c7bf35cf0e9c41b5d9910 (diff)
[PATCH] ppc32: Bump PMU interrupt priority
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>
-rw-r--r--arch/ppc/syslib/open_pic.c26
-rw-r--r--drivers/macintosh/via-pmu.c10
-rw-r--r--include/asm-ppc/open_pic.h6
3 files changed, 35 insertions, 7 deletions
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index b45d8268bf93..ad39b86ca92c 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -370,8 +370,9 @@ void __init openpic_init(int offset)
370 /* Initialize IPI interrupts */ 370 /* Initialize IPI interrupts */
371 if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb); 371 if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
372 for (i = 0; i < OPENPIC_NUM_IPI; i++) { 372 for (i = 0; i < OPENPIC_NUM_IPI; i++) {
373 /* Disabled, Priority 10..13 */ 373 /* Disabled, increased priorities 10..13 */
374 openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset); 374 openpic_initipi(i, OPENPIC_PRIORITY_IPI_BASE+i,
375 OPENPIC_VEC_IPI+i+offset);
375 /* IPIs are per-CPU */ 376 /* IPIs are per-CPU */
376 irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU; 377 irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
377 irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi; 378 irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
@@ -399,8 +400,9 @@ void __init openpic_init(int offset)
399 if (sense & IRQ_SENSE_MASK) 400 if (sense & IRQ_SENSE_MASK)
400 irq_desc[i+offset].status = IRQ_LEVEL; 401 irq_desc[i+offset].status = IRQ_LEVEL;
401 402
402 /* Enabled, Priority 8 */ 403 /* Enabled, Default priority */
403 openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK), 404 openpic_initirq(i, OPENPIC_PRIORITY_DEFAULT, i+offset,
405 (sense & IRQ_POLARITY_MASK),
404 (sense & IRQ_SENSE_MASK)); 406 (sense & IRQ_SENSE_MASK));
405 /* Processor 0 */ 407 /* Processor 0 */
406 openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE); 408 openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
@@ -656,6 +658,18 @@ static void __init openpic_maptimer(u_int timer, cpumask_t cpumask)
656} 658}
657 659
658/* 660/*
661 * Change the priority of an interrupt
662 */
663void __init
664openpic_set_irq_priority(u_int irq, u_int pri)
665{
666 check_arg_irq(irq);
667 openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
668 OPENPIC_PRIORITY_MASK,
669 pri << OPENPIC_PRIORITY_SHIFT);
670}
671
672/*
659 * Initalize the interrupt source which will generate an NMI. 673 * Initalize the interrupt source which will generate an NMI.
660 * This raises the interrupt's priority from 8 to 9. 674 * This raises the interrupt's priority from 8 to 9.
661 * 675 *
@@ -665,9 +679,7 @@ void __init
665openpic_init_nmi_irq(u_int irq) 679openpic_init_nmi_irq(u_int irq)
666{ 680{
667 check_arg_irq(irq); 681 check_arg_irq(irq);
668 openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority, 682 openpic_set_irq_priority(irq, OPENPIC_PRIORITY_NMI);
669 OPENPIC_PRIORITY_MASK,
670 9 << OPENPIC_PRIORITY_SHIFT);
671} 683}
672 684
673/* 685/*
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index b941ee220997..5375df03c6f3 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -63,6 +63,10 @@
63#include <asm/backlight.h> 63#include <asm/backlight.h>
64#endif 64#endif
65 65
66#ifdef CONFIG_PPC32
67#include <asm/open_pic.h>
68#endif
69
66/* Some compile options */ 70/* Some compile options */
67#undef SUSPEND_USES_PMU 71#undef SUSPEND_USES_PMU
68#define DEBUG_SLEEP 72#define DEBUG_SLEEP
@@ -407,6 +411,12 @@ static int __init via_pmu_start(void)
407 batt_req.complete = 1; 411 batt_req.complete = 1;
408#endif 412#endif
409 413
414#ifdef CONFIG_PPC32
415 if (pmu_kind == PMU_KEYLARGO_BASED)
416 openpic_set_irq_priority(vias->intrs[0].line,
417 OPENPIC_PRIORITY_DEFAULT + 1);
418#endif
419
410 if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", 420 if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU",
411 (void *)0)) { 421 (void *)0)) {
412 printk(KERN_ERR "VIA-PMU: can't get irq %d\n", 422 printk(KERN_ERR "VIA-PMU: can't get irq %d\n",
diff --git a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h
index dbe853319741..7848aa610c05 100644
--- a/include/asm-ppc/open_pic.h
+++ b/include/asm-ppc/open_pic.h
@@ -25,6 +25,11 @@
25#define OPENPIC_VEC_IPI 118 /* and up */ 25#define OPENPIC_VEC_IPI 118 /* and up */
26#define OPENPIC_VEC_SPURIOUS 255 26#define OPENPIC_VEC_SPURIOUS 255
27 27
28/* Priorities */
29#define OPENPIC_PRIORITY_IPI_BASE 10
30#define OPENPIC_PRIORITY_DEFAULT 4
31#define OPENPIC_PRIORITY_NMI 9
32
28/* OpenPIC IRQ controller structure */ 33/* OpenPIC IRQ controller structure */
29extern struct hw_interrupt_type open_pic; 34extern struct hw_interrupt_type open_pic;
30 35
@@ -42,6 +47,7 @@ extern int epic_serial_mode;
42extern void openpic_set_sources(int first_irq, int num_irqs, void __iomem *isr); 47extern void openpic_set_sources(int first_irq, int num_irqs, void __iomem *isr);
43extern void openpic_init(int linux_irq_offset); 48extern void openpic_init(int linux_irq_offset);
44extern void openpic_init_nmi_irq(u_int irq); 49extern void openpic_init_nmi_irq(u_int irq);
50extern void openpic_set_irq_priority(u_int irq, u_int pri);
45extern void openpic_hookup_cascade(u_int irq, char *name, 51extern void openpic_hookup_cascade(u_int irq, char *name,
46 int (*cascade_fn)(struct pt_regs *)); 52 int (*cascade_fn)(struct pt_regs *));
47extern u_int openpic_irq(void); 53extern u_int openpic_irq(void);