Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b7f90a406ff72d6698b619210c205e3375dd099a
Commit:     b7f90a406ff72d6698b619210c205e3375dd099a
Parent:     b21010ed6498391c0f359f2a89c907533fe07fec
Author:     Masato Noguchi <[EMAIL PROTECTED]>
AuthorDate: Fri Sep 7 18:28:27 2007 +1000
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Tue Sep 11 04:30:36 2007 +1000

    [POWERPC] cell/PS3: Fix a bug that causes the PS3 to hang on the SPU Class 
0 interrupt.
    
    The Cell BE Architecture spec states that the SPU MFC Class 0 interrupt
    is edge-triggered.  The current spu interrupt handler assumes this
    behavior and does not clear the interrupt status.
    
    The PS3 hypervisor visualizes all SPU interrupts as level, and on return
    from the interrupt handler the hypervisor will deliver a new virtual
    interrupt for any unmasked interrupts which for which the status has not
    been cleared.  This fix clears the interrupt status in the interrupt
    handler.
    
    Signed-off-by: Masato Noguchi <[EMAIL PROTECTED]>
    Signed-off-by: Geoff Levand <[EMAIL PROTECTED]>
    Signed-off-by: Jeremy Kerr <[EMAIL PROTECTED]>
    Acked-by: Arnd Bergmann <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/cell/spu_base.c |   24 +++++++++++++++---------
 include/asm-powerpc/spu.h              |    2 +-
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spu_base.c 
b/arch/powerpc/platforms/cell/spu_base.c
index 095a303..106d292 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 8836c0f..5bde398 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);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to