]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/platforms/cell/spu_base.c
[POWERPC] cell/PS3: Fix a bug that causes the PS3 to hang on the SPU Class 0 interrupt.
[linux-2.6-omap-h63xx.git] / arch / powerpc / platforms / cell / spu_base.c
index 095a30304c56861b8259cf776a9870907238083d..106d2921e2d9f5a057337935c94d4e05ed18f3d2 100644 (file)
@@ -236,27 +236,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 flags;
-
-       spu->class_0_pending = 0;
+       unsigned long stat;
 
        spin_lock_irqsave(&spu->register_lock, flags);
-       mask = spu_int_mask_get(spu, 0);
-       stat = spu_int_stat_get(spu, 0);
-
-       stat &= mask;
+       stat = spu->class_0_pending;
+       spu->class_0_pending = 0;
 
        if (stat & 1) /* invalid DMA alignment */
                __spu_trap_dma_align(spu);
@@ -267,7 +274,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);
        spin_unlock_irqrestore(&spu->register_lock, flags);
 
        return (stat & 0x7) ? -EIO : 0;