aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorLuke Browning <lukebr@linux.vnet.ibm.com>2008-04-25 00:00:00 -0400
committerJeremy Kerr <jk@ozlabs.org>2008-05-04 23:33:43 -0400
commit093c16bf9b107433643cbf0843ca7808df90823b (patch)
tree1776b417f366894e9fde4d58f456e3fef6697890 /arch/powerpc
parentd29694f0681e188cf75477f20904041744e78ef7 (diff)
[POWERPC] spufs: set SPU_CONTEXT_SWITCH_PENDING before synchronising SPU irqs
synchronize_irq() provides the serialization for SPU_CONTEXT_SWITCH_PENDING which is read with a simple load. This routine guarantees that the relevant interrupt handlers are not running, so that the next time they do run they will see the update memory value. This must be done correctly so that exception handling code does not restart the mfc in the middle of a context switch while we are trying to atomically stop it and save state. Signed-off-by: Luke Browning <lukebr@linux.vnet.ibm.com> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 53361d0c070f..9748808b0f19 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -132,6 +132,13 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)
132 spu_int_mask_set(spu, 2, 0ul); 132 spu_int_mask_set(spu, 2, 0ul);
133 eieio(); 133 eieio();
134 spin_unlock_irq(&spu->register_lock); 134 spin_unlock_irq(&spu->register_lock);
135
136 /*
137 * This flag needs to be set before calling synchronize_irq so
138 * that the update will be visible to the relevant handlers
139 * via a simple load.
140 */
141 set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags);
135 synchronize_irq(spu->irqs[0]); 142 synchronize_irq(spu->irqs[0]);
136 synchronize_irq(spu->irqs[1]); 143 synchronize_irq(spu->irqs[1]);
137 synchronize_irq(spu->irqs[2]); 144 synchronize_irq(spu->irqs[2]);
@@ -166,9 +173,8 @@ static inline void set_switch_pending(struct spu_state *csa, struct spu *spu)
166 /* Save, Step 7: 173 /* Save, Step 7:
167 * Restore, Step 5: 174 * Restore, Step 5:
168 * Set a software context switch pending flag. 175 * Set a software context switch pending flag.
176 * Done above in Step 3 - disable_interrupts().
169 */ 177 */
170 set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags);
171 mb();
172} 178}
173 179
174static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) 180static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu)