2006-03-23 20:40:21

by Arnd Bergmann

[permalink] [raw]
Subject: [patch 07/13] powerpc: work around a cell interrupt HW bug

Apparently we have found a bug in the CPU that causes
external interrupts to sometimes get disabled indefinitely.
This adds a workaround for the problem.

Signed-off-by: Arnd Bergmann <[email protected]>

Index: linux-2.6.15.4/arch/powerpc/platforms/cell/interrupt.c
===================================================================
--- linux-2.6.15.4.orig/arch/powerpc/platforms/cell/interrupt.c
+++ linux-2.6.15.4/arch/powerpc/platforms/cell/interrupt.c
@@ -63,7 +63,24 @@ static DEFINE_PER_CPU(struct iic, iic);

void iic_local_enable(void)
{
- out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+ struct iic *iic = &__get_cpu_var(iic);
+ u64 tmp;
+
+ /*
+ * There seems to be a bug that is present in DD2.x CPUs
+ * and still only partially fixed in DD3.1.
+ * This bug causes a value written to the priority register
+ * not to make it there, resulting in a system hang unless we
+ * write it again.
+ * Masking with 0xf0 is done because the Cell BE does not
+ * implement the lower four bits of the interrupt priority,
+ * they always read back as zeroes, although future CPUs
+ * might implement different bits.
+ */
+ do {
+ out_be64(&iic->regs->prio, 0xff);
+ tmp = in_be64(&iic->regs->prio);
+ } while ((tmp & 0xf0) != 0xf0);
}

void iic_local_disable(void)

--