diff options
author | Luke Browning <lukebr@linux.vnet.ibm.com> | 2008-04-27 22:41:55 +0400 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2008-05-05 07:33:44 +0400 |
commit | f3d69e0507f84903059d456c5d19f10b2df3ac69 (patch) | |
tree | f8aa4062bc1a0939d7bdb3a634c01869f2bb32a2 /arch/powerpc/platforms/cell/spu_base.c | |
parent | 7a2142002f29a7b398c49da9bdec712dc57087c7 (diff) | |
download | linux-f3d69e0507f84903059d456c5d19f10b2df3ac69.tar.xz |
[POWERPC] spufs: fix concurrent delivery of class 0 & 1 exceptions
SPU class 0 & 1 exceptions may occur in parallel, so we may end up
overwriting csa.dsisr.
This change adds dedicated fields for each class to the spu and the spu
context so that fault data is not overwritten.
Signed-off-by: Luke Browning <lukebr@linux.vnet.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'arch/powerpc/platforms/cell/spu_base.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 6bab44b7716b..b9ae675640d0 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -226,11 +226,13 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) return 0; } - spu->class_0_pending = 0; - spu->dar = ea; - spu->dsisr = dsisr; + spu->class_1_dar = ea; + spu->class_1_dsisr = dsisr; + + spu->stop_callback(spu, 1); - spu->stop_callback(spu); + spu->class_1_dar = 0; + spu->class_1_dsisr = 0; return 0; } @@ -318,11 +320,15 @@ spu_irq_class_0(int irq, void *data) stat = spu_int_stat_get(spu, 0) & mask; spu->class_0_pending |= stat; - spu->dsisr = spu_mfc_dsisr_get(spu); - spu->dar = spu_mfc_dar_get(spu); + spu->class_0_dsisr = spu_mfc_dsisr_get(spu); + spu->class_0_dar = spu_mfc_dar_get(spu); spin_unlock(&spu->register_lock); - spu->stop_callback(spu); + spu->stop_callback(spu, 0); + + spu->class_0_pending = 0; + spu->class_0_dsisr = 0; + spu->class_0_dar = 0; spu_int_stat_clear(spu, 0, stat); @@ -363,6 +369,9 @@ spu_irq_class_1(int irq, void *data) if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR) ; + spu->class_1_dsisr = 0; + spu->class_1_dar = 0; + return stat ? IRQ_HANDLED : IRQ_NONE; } @@ -396,10 +405,10 @@ spu_irq_class_2(int irq, void *data) spu->ibox_callback(spu); if (stat & CLASS2_SPU_STOP_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_HALT_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR) spu->mfc_callback(spu); |