diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 095a30304c56..106d2921e2d9 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -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; diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 8836c0f1f2f7..5bde3980bf49 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -130,6 +130,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; @@ -138,7 +139,6 @@ struct spu { unsigned long long timestamp; pid_t pid; pid_t tgid; - int class_0_pending; spinlock_t register_lock; void (* wbox_callback)(struct spu *spu);