[media] marvell-cam: fix the green screen of death

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>
This commit is contained in:
Jonathan Corbet 2012-03-16 19:14:53 -03:00 коммит произвёл Mauro Carvalho Chehab
Родитель 482d35c41f
Коммит 121bbe254a
1 изменённых файлов: 6 добавлений и 7 удалений

Просмотреть файл

@ -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