Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[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 <Masato.Noguchi@jp.sony.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

Masato Noguchi and committed by
Paul Mackerras
b7f90a40 b21010ed

+16 -10
+15 -9
arch/powerpc/platforms/cell/spu_base.c
··· 236 236 spu_irq_class_0(int irq, void *data) 237 237 { 238 238 struct spu *spu; 239 + unsigned long stat, mask; 239 240 240 241 spu = data; 241 - spu->class_0_pending = 1; 242 + 243 + mask = spu_int_mask_get(spu, 0); 244 + stat = spu_int_stat_get(spu, 0); 245 + stat &= mask; 246 + 247 + spin_lock(&spu->register_lock); 248 + spu->class_0_pending |= stat; 249 + spin_unlock(&spu->register_lock); 250 + 242 251 spu->stop_callback(spu); 252 + 253 + spu_int_stat_clear(spu, 0, stat); 243 254 244 255 return IRQ_HANDLED; 245 256 } ··· 258 247 int 259 248 spu_irq_class_0_bottom(struct spu *spu) 260 249 { 261 - unsigned long stat, mask; 262 250 unsigned long flags; 263 - 264 - spu->class_0_pending = 0; 251 + unsigned long stat; 265 252 266 253 spin_lock_irqsave(&spu->register_lock, flags); 267 - mask = spu_int_mask_get(spu, 0); 268 - stat = spu_int_stat_get(spu, 0); 269 - 270 - stat &= mask; 254 + stat = spu->class_0_pending; 255 + spu->class_0_pending = 0; 271 256 272 257 if (stat & 1) /* invalid DMA alignment */ 273 258 __spu_trap_dma_align(spu); ··· 274 267 if (stat & 4) /* error on SPU */ 275 268 __spu_trap_error(spu); 276 269 277 - spu_int_stat_clear(spu, 0, stat); 278 270 spin_unlock_irqrestore(&spu->register_lock, flags); 279 271 280 272 return (stat & 0x7) ? -EIO : 0;
+1 -1
include/asm-powerpc/spu.h
··· 130 130 u64 flags; 131 131 u64 dar; 132 132 u64 dsisr; 133 + u64 class_0_pending; 133 134 size_t ls_size; 134 135 unsigned int slb_replace; 135 136 struct mm_struct *mm; ··· 139 138 unsigned long long timestamp; 140 139 pid_t pid; 141 140 pid_t tgid; 142 - int class_0_pending; 143 141 spinlock_t register_lock; 144 142 145 143 void (* wbox_callback)(struct spu *spu);