[RFC/PATCH] powerpc: Fix kdump EOI bug (often exhibits as dead console)
Michael Ellerman
michael at ellerman.id.au
Mon Mar 13 19:16:32 EST 2006
If we take an interrupt, and while processing it, decide to kdump we never
EOI that interrupt. This can happen for any interrupt, but most commonly it's
the console interrupt from a user hitting 'sysrq-c', which prevents the
console from working in the second kernel.
We're panicking so we don't want to do any more than we need to in the first
kernel, so leave things alone there. When we come back up iff we reenable the
interrupt in question, do an EOI then. This fixes the bug for me, and appears
to cause no issue for other interrupts.
Tested on P5 LPAR.
Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
---
arch/powerpc/platforms/pseries/xics.c | 31 +++++++++++++++++++++----------
1 files changed, 21 insertions(+), 10 deletions(-)
Index: kdump/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- kdump.orig/arch/powerpc/platforms/pseries/xics.c
+++ kdump/arch/powerpc/platforms/pseries/xics.c
@@ -208,11 +208,32 @@ xics_ops pSeriesLP_ops = {
pSeriesLP_qirr_info
};
+static unsigned int real_irq_to_virt(unsigned int real_irq)
+{
+ unsigned int *ptr;
+
+ ptr = radix_tree_lookup(&irq_map, real_irq);
+ if (ptr == NULL)
+ return NO_IRQ;
+ return ptr - virt_irq_to_real_map;
+}
+
static unsigned int xics_startup(unsigned int virq)
{
unsigned int irq;
irq = irq_offset_down(virq);
+
+#ifdef CONFIG_CRASH_DUMP
+ /* We may have kdumped from an interrupt handler in which case we
+ * won't have EOI'ed that irq, so do it now. We only want to do
+ * this the first time we're called for each irq, so exploit the
+ * radix tree as a way to check if we've already enabled this irq.
+ */
+ if (real_irq_to_virt(virt_irq_to_real(irq)) == NO_IRQ)
+ xics_end_irq(virq);
+#endif
+
if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
&virt_irq_to_real_map[irq]) == -ENOMEM)
printk(KERN_CRIT "Out of memory creating real -> virtual"
@@ -222,16 +243,6 @@ static unsigned int xics_startup(unsigne
return 0; /* return value is ignored */
}
-static unsigned int real_irq_to_virt(unsigned int real_irq)
-{
- unsigned int *ptr;
-
- ptr = radix_tree_lookup(&irq_map, real_irq);
- if (ptr == NULL)
- return NO_IRQ;
- return ptr - virt_irq_to_real_map;
-}
-
#ifdef CONFIG_SMP
static int get_irq_server(unsigned int irq)
{
More information about the Linuxppc64-dev
mailing list