diff options
author | Luke Browning <lukebr@linux.vnet.ibm.com> | 2008-04-25 00:00:00 -0400 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2008-05-04 23:33:43 -0400 |
commit | 093c16bf9b107433643cbf0843ca7808df90823b (patch) | |
tree | 1776b417f366894e9fde4d58f456e3fef6697890 /arch/powerpc | |
parent | d29694f0681e188cf75477f20904041744e78ef7 (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.c | 10 |
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 | ||
174 | static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) | 180 | static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) |