]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.arch/ppc-xics-EOI-unmapped-irqs.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc-xics-EOI-unmapped-irqs.patch
diff --git a/src/patches/suse-2.6.27.31/patches.arch/ppc-xics-EOI-unmapped-irqs.patch b/src/patches/suse-2.6.27.31/patches.arch/ppc-xics-EOI-unmapped-irqs.patch
new file mode 100644 (file)
index 0000000..b014428
--- /dev/null
@@ -0,0 +1,111 @@
+From: Milton Miller <miltonm@bga.com>
+Subject: powerpc/xics: EOI unmapped irqs after disabling them
+Date: Fri Oct 10 01:56:23 2008 +0000
+X-Git-Tag: v2.6.28-rc1~569^2~27
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8767e9badca7cdf0adc2564d7524092d47ababf3
+Patch-mainline: v2.6.28-rc1
+References: bnc#459065
+
+When reciving an irq vector that does not have a linux mapping, the kernel
+prints a message and calls RTAS to disable the irq source.   Previously
+the kernel did not EOI the interrupt, causing the source to think it is
+still being processed by software.  While this does add an additional
+layer of protection against interrupt storms had RTAS failed to disable
+the source, it also prevents the interrupt from working when a driver
+later enables it.  (We could alternatively send an EOI on startup, but
+that strategy would likely fail on an emulated xics.)
+
+All interrupts should be disabled when the kernel starts, but this can
+be observed if a driver does not shutdown an interrupt in its reboot
+hook before starting a new kernel with kexec.
+
+Michael reports this can be reproduced trivially by banging the keyboard
+while kexec'ing on a P5 LPAR: even though the hvc_console driver request's
+the console irq later in boot, the console is non-functional because
+we're receiving no console interrupts.
+
+Reported-By: Michael Ellerman
+Signed-off-by: Milton Miller <miltonm@bga.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Acked-by: Petr Tesarik <ptesarik@suse.cz>
+
+---
+ arch/powerpc/platforms/pseries/xics.c |   53 ++++++++++++++++++++++++++--------
+ 1 file changed, 41 insertions(+), 12 deletions(-)
+
+--- linux-2.6.27-SLE11_BRANCH.orig/arch/powerpc/platforms/pseries/xics.c       2009-04-16 10:33:47.000000000 +0200
++++ linux-2.6.27-SLE11_BRANCH/arch/powerpc/platforms/pseries/xics.c    2009-04-16 10:52:29.000000000 +0200
+@@ -335,32 +335,61 @@ static void xics_eoi_lpar(unsigned int v
+       lpar_xirr_info_set((0xff << 24) | irq);
+ }
+-static inline unsigned int xics_remap_irq(unsigned int vec)
++static inline unsigned int xics_xirr_vector(unsigned int xirr)
+ {
+-      unsigned int irq;
++      /*
++       * The top byte is the old cppr, to be restored on EOI.
++       * The remaining 24 bits are the vector.
++       */
++      return xirr & 0x00ffffff;
++}
+-      vec &= 0x00ffffff;
++static void xics_mask_unknown_vec(unsigned int vec)
++{
++      printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
++      xics_mask_real_irq(vec);
++}
++
++static unsigned int xics_get_irq_direct(void)
++{
++      unsigned int xirr = direct_xirr_info_get();
++      unsigned int vec = xics_xirr_vector(xirr);
++      unsigned int irq;
+       if (vec == XICS_IRQ_SPURIOUS)
+               return NO_IRQ;
++
+       irq = irq_radix_revmap(xics_host, vec);
+       if (likely(irq != NO_IRQ))
+               return irq;
+-      printk(KERN_ERR "Interrupt %u (real) is invalid,"
+-             " disabling it.\n", vec);
+-      xics_mask_real_irq(vec);
+-      return NO_IRQ;
+-}
++      /* We don't have a linux mapping, so have rtas mask it. */
++      xics_mask_unknown_vec(vec);
+-static unsigned int xics_get_irq_direct(void)
+-{
+-      return xics_remap_irq(direct_xirr_info_get());
++      /* We might learn about it later, so EOI it */
++      direct_xirr_info_set(xirr);
++      return NO_IRQ;
+ }
+ static unsigned int xics_get_irq_lpar(void)
+ {
+-      return xics_remap_irq(lpar_xirr_info_get());
++      unsigned int xirr = lpar_xirr_info_get();
++      unsigned int vec = xics_xirr_vector(xirr);
++      unsigned int irq;
++
++      if (vec == XICS_IRQ_SPURIOUS)
++              return NO_IRQ;
++
++      irq = irq_radix_revmap(xics_host, vec);
++      if (likely(irq != NO_IRQ))
++              return irq;
++
++      /* We don't have a linux mapping, so have RTAS mask it. */
++      xics_mask_unknown_vec(vec);
++
++      /* We might learn about it later, so EOI it */
++      lpar_xirr_info_set(xirr);
++      return NO_IRQ;
+ }
+ #ifdef CONFIG_SMP