]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.arch/ppc-xics-EOI-unmapped-irqs.patch
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc-xics-EOI-unmapped-irqs.patch
1 From: Milton Miller <miltonm@bga.com>
2 Subject: powerpc/xics: EOI unmapped irqs after disabling them
3 Date: Fri Oct 10 01:56:23 2008 +0000
4 X-Git-Tag: v2.6.28-rc1~569^2~27
5 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8767e9badca7cdf0adc2564d7524092d47ababf3
6 Patch-mainline: v2.6.28-rc1
7 References: bnc#459065
8
9 When reciving an irq vector that does not have a linux mapping, the kernel
10 prints a message and calls RTAS to disable the irq source. Previously
11 the kernel did not EOI the interrupt, causing the source to think it is
12 still being processed by software. While this does add an additional
13 layer of protection against interrupt storms had RTAS failed to disable
14 the source, it also prevents the interrupt from working when a driver
15 later enables it. (We could alternatively send an EOI on startup, but
16 that strategy would likely fail on an emulated xics.)
17
18 All interrupts should be disabled when the kernel starts, but this can
19 be observed if a driver does not shutdown an interrupt in its reboot
20 hook before starting a new kernel with kexec.
21
22 Michael reports this can be reproduced trivially by banging the keyboard
23 while kexec'ing on a P5 LPAR: even though the hvc_console driver request's
24 the console irq later in boot, the console is non-functional because
25 we're receiving no console interrupts.
26
27 Reported-By: Michael Ellerman
28 Signed-off-by: Milton Miller <miltonm@bga.com>
29 Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
30 Acked-by: Petr Tesarik <ptesarik@suse.cz>
31
32 ---
33 arch/powerpc/platforms/pseries/xics.c | 53 ++++++++++++++++++++++++++--------
34 1 file changed, 41 insertions(+), 12 deletions(-)
35
36 --- linux-2.6.27-SLE11_BRANCH.orig/arch/powerpc/platforms/pseries/xics.c 2009-04-16 10:33:47.000000000 +0200
37 +++ linux-2.6.27-SLE11_BRANCH/arch/powerpc/platforms/pseries/xics.c 2009-04-16 10:52:29.000000000 +0200
38 @@ -335,32 +335,61 @@ static void xics_eoi_lpar(unsigned int v
39 lpar_xirr_info_set((0xff << 24) | irq);
40 }
41
42 -static inline unsigned int xics_remap_irq(unsigned int vec)
43 +static inline unsigned int xics_xirr_vector(unsigned int xirr)
44 {
45 - unsigned int irq;
46 + /*
47 + * The top byte is the old cppr, to be restored on EOI.
48 + * The remaining 24 bits are the vector.
49 + */
50 + return xirr & 0x00ffffff;
51 +}
52
53 - vec &= 0x00ffffff;
54 +static void xics_mask_unknown_vec(unsigned int vec)
55 +{
56 + printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
57 + xics_mask_real_irq(vec);
58 +}
59 +
60 +static unsigned int xics_get_irq_direct(void)
61 +{
62 + unsigned int xirr = direct_xirr_info_get();
63 + unsigned int vec = xics_xirr_vector(xirr);
64 + unsigned int irq;
65
66 if (vec == XICS_IRQ_SPURIOUS)
67 return NO_IRQ;
68 +
69 irq = irq_radix_revmap(xics_host, vec);
70 if (likely(irq != NO_IRQ))
71 return irq;
72
73 - printk(KERN_ERR "Interrupt %u (real) is invalid,"
74 - " disabling it.\n", vec);
75 - xics_mask_real_irq(vec);
76 - return NO_IRQ;
77 -}
78 + /* We don't have a linux mapping, so have rtas mask it. */
79 + xics_mask_unknown_vec(vec);
80
81 -static unsigned int xics_get_irq_direct(void)
82 -{
83 - return xics_remap_irq(direct_xirr_info_get());
84 + /* We might learn about it later, so EOI it */
85 + direct_xirr_info_set(xirr);
86 + return NO_IRQ;
87 }
88
89 static unsigned int xics_get_irq_lpar(void)
90 {
91 - return xics_remap_irq(lpar_xirr_info_get());
92 + unsigned int xirr = lpar_xirr_info_get();
93 + unsigned int vec = xics_xirr_vector(xirr);
94 + unsigned int irq;
95 +
96 + if (vec == XICS_IRQ_SPURIOUS)
97 + return NO_IRQ;
98 +
99 + irq = irq_radix_revmap(xics_host, vec);
100 + if (likely(irq != NO_IRQ))
101 + return irq;
102 +
103 + /* We don't have a linux mapping, so have RTAS mask it. */
104 + xics_mask_unknown_vec(vec);
105 +
106 + /* We might learn about it later, so EOI it */
107 + lpar_xirr_info_set(xirr);
108 + return NO_IRQ;
109 }
110
111 #ifdef CONFIG_SMP