aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2008-04-09 01:24:22 -0400
committerJeremy Kerr <jk@ozlabs.org>2008-05-04 23:33:42 -0400
commit1ca4264ee17745779c341966c5e61ac69bfd17a6 (patch)
tree86c27361d4d89853c387934879573ce7b658dae5 /arch
parent943906ba4bebf629d5cd770e48b8ec0ddc433869 (diff)
[POWERPC] spufs: fix save of mfc_cntl register
Currently, we can introduce invalid entries into the MFC queues: 1) context starts a DMA 2) context gets scheduled out during a DMA - kernel saves MFC queue to CSA - kernel saves 0x0 in csa->mfc_control_RW 3) context gets scheduled in - csa->mfc_control[Q] ('queues empty') isn't set, so DMA queues are restored from the CSA 4) context's DMA is completed 5) context gets scheduled out again, no DMA occuring this time - kernel sees that MFC_CNTL[Q] ('queues empty') is set, so doesn't touch saved queue data in CSA - kernel saves 0x0 in csa->mfc_control_RW 6) context gets scheduled in - csa->mfc_control[Q] ('queues empty') isn't set (we saved is as 0!), so DMA queues are restored from the CSA In this last restore, we've restored the queue status from step 2, which are now invalid. This change makes save_mfc_cntl() closer to the save/restore sequence, as specified in the CBE handbook. With changes from Luke Browning. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 65b423b6da48..4131784216bb 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -186,20 +186,21 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu)
186 MFC_CNTL_SUSPEND_COMPLETE); 186 MFC_CNTL_SUSPEND_COMPLETE);
187 /* fall through */ 187 /* fall through */
188 case MFC_CNTL_SUSPEND_COMPLETE: 188 case MFC_CNTL_SUSPEND_COMPLETE:
189 if (csa) { 189 if (csa)
190 csa->priv2.mfc_control_RW = 190 csa->priv2.mfc_control_RW =
191 MFC_CNTL_SUSPEND_MASK | 191 in_be64(&priv2->mfc_control_RW) |
192 MFC_CNTL_SUSPEND_DMA_QUEUE; 192 MFC_CNTL_SUSPEND_DMA_QUEUE;
193 }
194 break; 193 break;
195 case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION: 194 case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION:
196 out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE); 195 out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE);
197 POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & 196 POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
198 MFC_CNTL_SUSPEND_DMA_STATUS_MASK) == 197 MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
199 MFC_CNTL_SUSPEND_COMPLETE); 198 MFC_CNTL_SUSPEND_COMPLETE);
200 if (csa) { 199 if (csa)
201 csa->priv2.mfc_control_RW = 0; 200 csa->priv2.mfc_control_RW =
202 } 201 in_be64(&priv2->mfc_control_RW) &
202 ~MFC_CNTL_SUSPEND_DMA_QUEUE &
203 ~MFC_CNTL_SUSPEND_MASK;
203 break; 204 break;
204 } 205 }
205} 206}