From 90752ebfb49ae884eefcd2f25c019c98a4ed615d Mon Sep 17 00:00:00 2001 From: Ashray Kulkarni Date: Thu, 16 Aug 2012 22:44:34 -0700 Subject: [PATCH] v4l2: Add mutex to streamon() and dqbuf()in v4l2 framework. When v4l2 streamon() is called the framework moves to streamon state, after queueing the buffer. A state check is performed during dqbuf(). Sometimes when dqbuf() is called streamon() function has not completed setting the state transisiton flag. This results in failure to dqbuf() as the framework has not moved to streamon. This patch adds a mutex around state transitions and dqbuf() calls. Change-Id: I0eadc4aaffbed62facd7dd250893e50448d7e52b Signed-off-by: Ashray Kulkarni --- drivers/media/video/videobuf2-core.c | 9 +++++++-- include/media/videobuf2-core.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 2bc0938ebb1..a7d13a81079 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -1330,12 +1330,14 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) return -EINVAL; } + mutex_lock(&q->q_lock); ret = __vb2_get_done_vb(q, &vb, nonblocking); if (ret < 0) { dprintk(1, "dqbuf: error getting next done buffer\n"); + mutex_unlock(&q->q_lock); return ret; } - + mutex_unlock(&q->q_lock); ret = call_qop(q, buf_finish, vb); if (ret) { dprintk(1, "dqbuf: buffer finish failed\n"); @@ -1447,15 +1449,17 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) /* * Let driver notice that streaming state has been enabled. */ + mutex_lock(&q->q_lock); ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count)); if (ret) { dprintk(1, "streamon: driver refused to start streaming\n"); __vb2_queue_cancel(q); + mutex_unlock(&q->q_lock); return ret; } q->streaming = 1; - + mutex_unlock(&q->q_lock); dprintk(3, "Streamon successful\n"); return 0; } @@ -1729,6 +1733,7 @@ int vb2_queue_init(struct vb2_queue *q) INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->done_list); spin_lock_init(&q->done_lock); + mutex_init(&q->q_lock); init_waitqueue_head(&q->done_wq); if (q->buf_struct_size == 0) diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index a15d1f1b319..2918b947dd5 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -289,6 +289,7 @@ struct vb2_queue { atomic_t queued_count; struct list_head done_list; spinlock_t done_lock; + struct mutex q_lock; wait_queue_head_t done_wq; void *alloc_ctx[VIDEO_MAX_PLANES];