提交 4abec468 编写于 作者: I Ian Molton 提交者: Mauro Carvalho Chehab

[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: NIan Molton <ian.molton@codethink.co.uk>
Signed-off-by: NWilliam Towle <william.towle@codethink.co.uk>
Signed-off-by: NGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: NMauro Carvalho Chehab <mchehab@osg.samsung.com>
上级 650b1815
...@@ -804,6 +804,28 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) ...@@ -804,6 +804,28 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); 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) static void rcar_vin_videobuf_release(struct vb2_buffer *vb)
{ {
struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); 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) ...@@ -823,20 +845,8 @@ static void rcar_vin_videobuf_release(struct vb2_buffer *vb)
} }
if (buf_in_use) { 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 * Capturing has now stopped. The buffer we have been asked
* to release could be any of the current buffers in use, so * 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) ...@@ -870,8 +880,11 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq)
struct list_head *buf_head, *tmp; struct list_head *buf_head, *tmp;
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
rcar_vin_wait_stop_streaming(priv);
list_for_each_safe(buf_head, tmp, &priv->capture) list_for_each_safe(buf_head, tmp, &priv->capture)
list_del_init(buf_head); list_del_init(buf_head);
spin_unlock_irq(&priv->lock); spin_unlock_irq(&priv->lock);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册