[media] marvell-cam: fix the green screen of death
authorJonathan Corbet <corbet@lwn.net>
Fri, 16 Mar 2012 22:14:53 +0000 (19:14 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 20 Mar 2012 01:16:19 +0000 (22:16 -0300)
I had learned through hard experience that dinking around with the DMA
descriptors while the C1_DESC_ENA enable bit was set is a recipe for all
kinds of truly malicious behavior on the hardware's part, regardless of
whether the DMA engine is actually operating at the time.  That
notwithstanding, the driver did so dink, resulting in "green frame"
captures and the death of the system in random, spectacular ways.

Move the tweaking of C1_DESC_ENA to the same function that sets the
descriptor so we know that we'll never try to set a descriptor while that
bit is set.

Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/marvell-ccic/mcam-core.c

index 050724f..e46a72a 100644 (file)
@@ -509,11 +509,17 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam)
 
        buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
        list_del_init(&buf->queue);
+       /*
+        * Very Bad Not Good Things happen if you don't clear
+        * C1_DESC_ENA before making any descriptor changes.
+        */
+       mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA);
        mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa);
        mcam_reg_write(cam, REG_DESC_LEN_Y,
                        buf->dma_desc_nent*sizeof(struct mcam_dma_desc));
        mcam_reg_write(cam, REG_DESC_LEN_U, 0);
        mcam_reg_write(cam, REG_DESC_LEN_V, 0);
+       mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
        cam->vb_bufs[0] = buf;
 }
 
@@ -533,7 +539,6 @@ static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
 
        mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD);
        mcam_sg_next_buffer(cam);
-       mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
        cam->nbufs = 3;
 }
 
@@ -560,18 +565,12 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
         */
        if (cam->state != S_STREAMING)
                return;
-       /*
-        * Very Bad Not Good Things happen if you don't clear
-        * C1_DESC_ENA before making any descriptor changes.
-        */
-       mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA);
        /*
         * If we have another buffer available, put it in and
         * restart the engine.
         */
        if (!list_empty(&cam->buffers)) {
                mcam_sg_next_buffer(cam);
-               mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
                mcam_ctlr_start(cam);
        /*
         * Otherwise set CF_SG_RESTART and the controller will