[PATCH] spufs: Suspend/restore MFC DMA operations at SPU context switch.
authorGeoff Levand <geoffrey.levand@am.sony.com>
Wed, 11 Jan 2006 03:47:37 +0000 (19:47 -0800)
committerPaul Mackerras <paulus@samba.org>
Wed, 11 Jan 2006 04:35:11 +0000 (15:35 +1100)
The SPE Book IV indicates that MFC DMA operations must be
suspended and restored on SPU context switch (in Step 8).

This patch adds that operation, which is missing from the
current spufs implementation.

Signed-off-by: Masato Noguchi <Masato.Noguchi@jp.sony.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Acked-by: Arnd Bergmann <arndb@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/cell/spufs/switch.c

index 1061c12b2edb5c1d4521ee14205c6281b36676ed..212db28531fabff2185d14c6bf6420c8b642e885 100644 (file)
@@ -169,11 +169,33 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu)
        struct spu_priv2 __iomem *priv2 = spu->priv2;
 
        /* Save, Step 8:
-        *     Read and save MFC_CNTL[Ss].
-        */
-       if (csa) {
-               csa->priv2.mfc_control_RW = in_be64(&priv2->mfc_control_RW) &
-                   MFC_CNTL_SUSPEND_DMA_STATUS_MASK;
+        *     Suspend DMA and save MFC_CNTL.
+        */
+       switch (in_be64(&priv2->mfc_control_RW) &
+              MFC_CNTL_SUSPEND_DMA_STATUS_MASK) {
+       case MFC_CNTL_SUSPEND_IN_PROGRESS:
+               POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
+                                 MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
+                                MFC_CNTL_SUSPEND_COMPLETE);
+               /* fall through */
+       case MFC_CNTL_SUSPEND_COMPLETE:
+               if (csa) {
+                       csa->priv2.mfc_control_RW =
+                               in_be64(&priv2->mfc_control_RW) |
+                               MFC_CNTL_SUSPEND_DMA_QUEUE;
+               }
+               break;
+       case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION:
+               out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE);
+               POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
+                                 MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
+                                MFC_CNTL_SUSPEND_COMPLETE);
+               if (csa) {
+                       csa->priv2.mfc_control_RW =
+                               in_be64(&priv2->mfc_control_RW) &
+                               ~MFC_CNTL_SUSPEND_DMA_QUEUE;
+               }
+               break;
        }
 }
 
@@ -237,6 +259,8 @@ static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu)
                eieio();
                csa->spu_chnldata_RW[7] = in_be64(&priv2->spu_chnldata_RW);
                eieio();
+       } else {
+               csa->priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING;
        }
 }