[Cbe-oss-dev] [PATCH 01/02] spufs: clear all valid status bits in class 0 interrupt handler.

Masato Noguchi Masato.Noguchi at jp.sony.com
Mon Feb 5 20:45:35 EST 2007


In the PS3 platform, all interrupts are virtuailzed by hypervisor.
Thus, there is a little difference between baremetal and PS3.

Cell BE Architecture says SPU MFC class 0 interrupt is a pulse.
That means, once interrupt raised, never re-raised until someone
changes interrupt status.

Current spufs inplementation rely on it.
Class 0 handler just wake up a process and interrupt status is
cleared by that process at outside of interrupt handler.

While, the PS3 hypervisor treats all SPU interrupt as a level.
That means, if unmasked interrupt status bit remaind at
the end of interrupt handler, the hypervisor creates renewed
virtual interrupt packet.

Thus, Current kernel will freeze by interrupts raised 
over and over again, once SPE raised class 0 interrupt.


Signed-off-by: Masato Noguchi <Masato.Noguchi at jp.sony.com>
---
 arch/powerpc/platforms/cell/spu_base.c |   25 ++++++++++++++++---------
 include/asm-powerpc/spu.h              |    2 +-
 2 files changed, 17 insertions(+), 10 deletions(-)

Index: ps3-linux/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- ps3-linux.orig/arch/powerpc/platforms/cell/spu_base.c
+++ ps3-linux/arch/powerpc/platforms/cell/spu_base.c
@@ -159,25 +159,34 @@ static irqreturn_t
 spu_irq_class_0(int irq, void *data)
 {
 	struct spu *spu;
+	unsigned long stat, mask;
 
 	spu = data;
-	spu->class_0_pending = 1;
+
+	mask = spu_int_mask_get(spu, 0);
+	stat = spu_int_stat_get(spu, 0);
+	stat &= mask;
+
+	spin_lock(&spu->register_lock);
+	spu->class_0_pending |= stat;
+	spin_unlock(&spu->register_lock);
+
 	spu->stop_callback(spu);
 
+	spu_int_stat_clear(spu, 0, stat);
+
 	return IRQ_HANDLED;
 }
 
 int
 spu_irq_class_0_bottom(struct spu *spu)
 {
-	unsigned long stat, mask;
+	unsigned long stat;
 
+	spin_lock_irq(&spu->register_lock);
+	stat = spu->class_0_pending;
 	spu->class_0_pending = 0;
-
-	mask = spu_int_mask_get(spu, 0);
-	stat = spu_int_stat_get(spu, 0);
-
-	stat &= mask;
+	spin_unlock_irq(&spu->register_lock);
 
 	if (stat & 1) /* invalid DMA alignment */
 		__spu_trap_dma_align(spu);
@@ -188,8 +197,6 @@ spu_irq_class_0_bottom(struct spu *spu)
 	if (stat & 4) /* error on SPU */
 		__spu_trap_error(spu);
 
-	spu_int_stat_clear(spu, 0, stat);
-
 	return (stat & 0x7) ? -EIO : 0;
 }
 EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);
Index: ps3-linux/include/asm-powerpc/spu.h
===================================================================
--- ps3-linux.orig/include/asm-powerpc/spu.h
+++ ps3-linux/include/asm-powerpc/spu.h
@@ -121,6 +121,7 @@ struct spu {
 	u64 flags;
 	u64 dar;
 	u64 dsisr;
+	u64 class_0_pending;
 	size_t ls_size;
 	unsigned int slb_replace;
 	struct mm_struct *mm;
@@ -129,7 +130,6 @@ struct spu {
 	unsigned long long timestamp;
 	pid_t pid;
 	int prio;
-	int class_0_pending;
 	spinlock_t register_lock;
 
 	void (* wbox_callback)(struct spu *spu);




More information about the cbe-oss-dev mailing list