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

Commit 4abec468 authored by Ian Molton's avatar Ian Molton Committed by Mauro Carvalho Chehab
Browse files

[media] rcar_vin: helper function for streaming stop



The code that tests that capture from a stream has stopped is
presently insufficient and the potential for a race condition
exists where frame capture may generate an interrupt between
requesting the capture process halt and freeing buffers.

This patch refactors code out of rcar_vin_videobuf_release() and
into rcar_vin_wait_stop_streaming(), and ensures there are calls
in places where we need to know that capturing has finished.

Signed-off-by: default avatarIan Molton <ian.molton@codethink.co.uk>
Signed-off-by: default avatarWilliam Towle <william.towle@codethink.co.uk>
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 650b1815
Loading
Loading
Loading
Loading
+27 −14
Original line number Diff line number Diff line
@@ -804,6 +804,28 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
	vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}

/*
 * Wait for capture to stop and all in-flight buffers to be finished with by
 * the video hardware. This must be called under &priv->lock
 *
 */
static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
{
	while (priv->state != STOPPED) {
		/* issue stop if running */
		if (priv->state == RUNNING)
			rcar_vin_request_capture_stop(priv);

		/* wait until capturing has been stopped */
		if (priv->state == STOPPING) {
			priv->request_to_stop = true;
			spin_unlock_irq(&priv->lock);
			wait_for_completion(&priv->capture_stop);
			spin_lock_irq(&priv->lock);
		}
	}
}

static void rcar_vin_videobuf_release(struct vb2_buffer *vb)
{
	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
@@ -823,20 +845,8 @@ static void rcar_vin_videobuf_release(struct vb2_buffer *vb)
	}

	if (buf_in_use) {
		while (priv->state != STOPPED) {
		rcar_vin_wait_stop_streaming(priv);

			/* issue stop if running */
			if (priv->state == RUNNING)
				rcar_vin_request_capture_stop(priv);

			/* wait until capturing has been stopped */
			if (priv->state == STOPPING) {
				priv->request_to_stop = true;
				spin_unlock_irq(&priv->lock);
				wait_for_completion(&priv->capture_stop);
				spin_lock_irq(&priv->lock);
			}
		}
		/*
		 * Capturing has now stopped. The buffer we have been asked
		 * to release could be any of the current buffers in use, so
@@ -870,8 +880,11 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq)
	struct list_head *buf_head, *tmp;

	spin_lock_irq(&priv->lock);

	rcar_vin_wait_stop_streaming(priv);
	list_for_each_safe(buf_head, tmp, &priv->capture)
		list_del_init(buf_head);

	spin_unlock_irq(&priv->lock);
}