Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Benjamin Herrenschmidt and committed by
Linus Torvalds
e4ee69c8 bb165746

+35 -7
+19 -7
arch/ppc/syslib/open_pic.c
··· 370 370 /* Initialize IPI interrupts */ 371 371 if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb); 372 372 for (i = 0; i < OPENPIC_NUM_IPI; i++) { 373 - /* Disabled, Priority 10..13 */ 374 - openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset); 373 + /* Disabled, increased priorities 10..13 */ 374 + openpic_initipi(i, OPENPIC_PRIORITY_IPI_BASE+i, 375 + OPENPIC_VEC_IPI+i+offset); 375 376 /* IPIs are per-CPU */ 376 377 irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU; 377 378 irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi; ··· 400 399 if (sense & IRQ_SENSE_MASK) 401 400 irq_desc[i+offset].status = IRQ_LEVEL; 402 401 403 - /* Enabled, Priority 8 */ 404 - openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK), 402 + /* Enabled, Default priority */ 403 + openpic_initirq(i, OPENPIC_PRIORITY_DEFAULT, i+offset, 404 + (sense & IRQ_POLARITY_MASK), 405 405 (sense & IRQ_SENSE_MASK)); 406 406 /* Processor 0 */ 407 407 openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE); ··· 658 656 } 659 657 660 658 /* 659 + * Change the priority of an interrupt 660 + */ 661 + void __init 662 + openpic_set_irq_priority(u_int irq, u_int pri) 663 + { 664 + check_arg_irq(irq); 665 + openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority, 666 + OPENPIC_PRIORITY_MASK, 667 + pri << OPENPIC_PRIORITY_SHIFT); 668 + } 669 + 670 + /* 661 671 * Initalize the interrupt source which will generate an NMI. 662 672 * This raises the interrupt's priority from 8 to 9. 663 673 * ··· 679 665 openpic_init_nmi_irq(u_int irq) 680 666 { 681 667 check_arg_irq(irq); 682 - openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority, 683 - OPENPIC_PRIORITY_MASK, 684 - 9 << OPENPIC_PRIORITY_SHIFT); 668 + openpic_set_irq_priority(irq, OPENPIC_PRIORITY_NMI); 685 669 } 686 670 687 671 /*
+10
drivers/macintosh/via-pmu.c
··· 63 63 #include <asm/backlight.h> 64 64 #endif 65 65 66 + #ifdef CONFIG_PPC32 67 + #include <asm/open_pic.h> 68 + #endif 69 + 66 70 /* Some compile options */ 67 71 #undef SUSPEND_USES_PMU 68 72 #define DEBUG_SLEEP ··· 409 405 bright_req_2.complete = 1; 410 406 #ifdef CONFIG_PMAC_PBOOK 411 407 batt_req.complete = 1; 408 + #endif 409 + 410 + #ifdef CONFIG_PPC32 411 + if (pmu_kind == PMU_KEYLARGO_BASED) 412 + openpic_set_irq_priority(vias->intrs[0].line, 413 + OPENPIC_PRIORITY_DEFAULT + 1); 412 414 #endif 413 415 414 416 if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU",
+6
include/asm-ppc/open_pic.h
··· 25 25 #define OPENPIC_VEC_IPI 118 /* and up */ 26 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 33 /* OpenPIC IRQ controller structure */ 29 34 extern struct hw_interrupt_type open_pic; 30 35 ··· 47 42 extern void openpic_set_sources(int first_irq, int num_irqs, void __iomem *isr); 48 43 extern void openpic_init(int linux_irq_offset); 49 44 extern void openpic_init_nmi_irq(u_int irq); 45 + extern void openpic_set_irq_priority(u_int irq, u_int pri); 50 46 extern void openpic_hookup_cascade(u_int irq, char *name, 51 47 int (*cascade_fn)(struct pt_regs *)); 52 48 extern u_int openpic_irq(void);