[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