Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 121bbe25 authored by Jonathan Corbet's avatar Jonathan Corbet Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarJonathan Corbet <corbet@lwn.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 482d35c4
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -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