From bd994ddb2a12a3ff48cd549ec82cdceaea9614df Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 23 Jun 2014 18:00:22 -0300 Subject: [media] v4l: vb2: Fix stream start and buffer completion race videobuf2 stores the driver streaming state internally in the queue in the start_streaming_called variable. The state is set right after the driver start_stream operation returns, and checked in the vb2_buffer_done() function, typically called from the frame completion interrupt handler. A race condition exists if the hardware finishes processing the first frame before the start_stream operation returns. Fix this by setting start_streaming_called to 1 before calling the start_stream operation, and resetting it to 0 if the operation fails. Cc: stable@vger.kernel.org # for v3.15 and up Signed-off-by: Laurent Pinchart Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 7c4489c42365..1d67e95311d6 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1750,12 +1750,14 @@ static int vb2_start_streaming(struct vb2_queue *q) __enqueue_in_driver(vb); /* Tell the driver to start streaming */ + q->start_streaming_called = 1; ret = call_qop(q, start_streaming, q, atomic_read(&q->owned_by_drv_count)); - q->start_streaming_called = ret == 0; if (!ret) return 0; + q->start_streaming_called = 0; + dprintk(1, "driver refused to start streaming\n"); if (WARN_ON(atomic_read(&q->owned_by_drv_count))) { unsigned i; -- cgit v1.2.3 From 9241650d62f79a3da01f1d5e8ebd195083330b75 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 3 Jun 2014 17:41:06 -0300 Subject: [media] v4l: vb2: Don't return POLLERR during transient buffer underruns The V4L2 specification states that "When the application did not call VIDIOC_QBUF or VIDIOC_STREAMON yet the poll() function succeeds, but sets the POLLERR flag in the revents field." The vb2_poll() function sets POLLERR when the queued buffers list is empty, regardless of whether this is caused by the stream not being active yet, or by a transient buffer underrun. Bring the implementation in line with the specification by returning POLLERR if no buffer has been queued only when the queue is not streaming. Buffer underruns during streaming are not treated specially anymore and just result in poll() blocking until the next event. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Acked-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 1d67e95311d6..1fc85fb964ce 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2559,9 +2559,10 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) } /* - * There is nothing to wait for if no buffers have already been queued. + * There is nothing to wait for if no buffer has been queued and the + * queue isn't streaming. */ - if (list_empty(&q->queued_list)) + if (list_empty(&q->queued_list) && !vb2_is_streaming(q)) return res | POLLERR; if (list_empty(&q->done_list)) -- cgit v1.2.3 From 4bb7267dc41247810815e8b15f0e9fb1456c8d8c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 3 Jun 2014 18:53:25 -0300 Subject: [media] v4l: vb2: Add fatal error condition flag When a fatal error occurs that render the device unusable, the only options for a driver to signal the error condition to userspace is to set the V4L2_BUF_FLAG_ERROR flag when dequeuing buffers and to return an error from the buffer prepare handler when queuing buffers. The buffer error flag indicates a transient error and can't be used by applications to detect fatal errors. Returning an error from vb2_qbuf() is thus the only real indication that a fatal error occurred. However, this is difficult to handle for multithreaded applications that requeue buffers from a thread other than the control thread. In particular the poll() call in the control thread will not notify userspace of the error. This patch adds an explicit mechanism to report fatal errors to userspace. Drivers can call the vb2_queue_error() function to signal a fatal error. From this moment on, buffer preparation will return -EIO to userspace, and vb2_poll() will set the POLLERR flag and return immediately. The error flag is cleared when cancelling the queue, either at stream off time (through vb2_streamoff) or when releasing the queue with vb2_queue_release(). Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 39 +++++++++++++++++++++++++++++--- include/media/videobuf2-core.h | 3 +++ 2 files changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 1fc85fb964ce..a5c41cc65d1c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1606,6 +1606,11 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) return -EINVAL; } + if (q->error) { + dprintk(1, "fatal error occurred on queue\n"); + return -EIO; + } + vb->state = VB2_BUF_STATE_PREPARING; vb->v4l2_buf.timestamp.tv_sec = 0; vb->v4l2_buf.timestamp.tv_usec = 0; @@ -1903,6 +1908,11 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) return -EINVAL; } + if (q->error) { + dprintk(1, "Queue in error state, will not wait for buffers\n"); + return -EIO; + } + if (!list_empty(&q->done_list)) { /* * Found a buffer that we were waiting for. @@ -1928,7 +1938,8 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) */ dprintk(3, "will sleep waiting for buffers\n"); ret = wait_event_interruptible(q->done_wq, - !list_empty(&q->done_list) || !q->streaming); + !list_empty(&q->done_list) || !q->streaming || + q->error); /* * We need to reevaluate both conditions again after reacquiring @@ -2125,6 +2136,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q) q->streaming = 0; q->start_streaming_called = 0; q->queued_count = 0; + q->error = 0; /* * Remove all buffers from videobuf's list... @@ -2201,6 +2213,27 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type) return 0; } +/** + * vb2_queue_error() - signal a fatal error on the queue + * @q: videobuf2 queue + * + * Flag that a fatal unrecoverable error has occurred and wake up all processes + * waiting on the queue. Polling will now set POLLERR and queuing and dequeuing + * buffers will return -EIO. + * + * The error flag will be cleared when cancelling the queue, either from + * vb2_streamoff or vb2_queue_release. Drivers should thus not call this + * function before starting the stream, otherwise the error flag will remain set + * until the queue is released when closing the device node. + */ +void vb2_queue_error(struct vb2_queue *q) +{ + q->error = 1; + + wake_up_all(&q->done_wq); +} +EXPORT_SYMBOL_GPL(vb2_queue_error); + /** * vb2_streamon - start streaming * @q: videobuf2 queue @@ -2560,9 +2593,9 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) /* * There is nothing to wait for if no buffer has been queued and the - * queue isn't streaming. + * queue isn't streaming, or if the error flag is set. */ - if (list_empty(&q->queued_list) && !vb2_is_streaming(q)) + if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error) return res | POLLERR; if (list_empty(&q->done_list)) diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 8fab6fa0dbfb..1a262aeb1741 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -375,6 +375,7 @@ struct v4l2_fh; * @streaming: current streaming state * @start_streaming_called: start_streaming() was called successfully and we * started streaming. + * @error: a fatal error occurred on the queue * @fileio: file io emulator internal data, used only if emulator is active * @threadio: thread io internal data, used only if thread is active */ @@ -411,6 +412,7 @@ struct vb2_queue { unsigned int streaming:1; unsigned int start_streaming_called:1; + unsigned int error:1; struct vb2_fileio_data *fileio; struct vb2_threadio_data *threadio; @@ -444,6 +446,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b); int __must_check vb2_queue_init(struct vb2_queue *q); void vb2_queue_release(struct vb2_queue *q); +void vb2_queue_error(struct vb2_queue *q); int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b); int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb); -- cgit v1.2.3 From 8a75ffb81b1c1b6949d191fbef3eaa03fd648852 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 17 Jul 2014 06:53:08 -0300 Subject: [media] vb2: fix bytesused == 0 handling The original report from Nikhil was that if data_offset > 0 and bytesused == 0, then the check in __verify_length() would fail, even though the spec says that if bytes_used == 0, then it will be replaced by the actual length of the buffer. After digging into it a bit more I realized that there were several other things wrong: - in __verify_length() it would use the application-provided length value for USERPTR and the vb2 core length for other memory models, but it should have used the application-provided length as well for DMABUF. - in __fill_vb2_buffer() on the other hand it would replace bytesused == 0 by the application-provided length, even for MMAP buffers where the length is determined by the vb2 core. - in __fill_vb2_buffer() it tries to figure out if all the planes have bytesused == 0 before it will decide to replace bytesused by length. However, the spec makes no such provision, and it makes for convoluted code. So just replace any bytesused == 0 by the proper length. The idea behind this was that you could use bytesused to signal empty planes, something that is currently not supported. But that is better done in the future by using one of the reserved fields in strucy v4l2_plane. This patch fixes all these issues. Regards, Hans Signed-off-by: Hans Verkuil Reported-by: Nikhil Devshatwar Cc: Nikhil Devshatwar Acked-by: Marek Szyprowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 78 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 40 deletions(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index a5c41cc65d1c..f33508f854a4 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -576,6 +576,7 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) { unsigned int length; + unsigned int bytesused; unsigned int plane; if (!V4L2_TYPE_IS_OUTPUT(b->type)) @@ -583,21 +584,24 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { for (plane = 0; plane < vb->num_planes; ++plane) { - length = (b->memory == V4L2_MEMORY_USERPTR) + length = (b->memory == V4L2_MEMORY_USERPTR || + b->memory == V4L2_MEMORY_DMABUF) ? b->m.planes[plane].length : vb->v4l2_planes[plane].length; + bytesused = b->m.planes[plane].bytesused + ? b->m.planes[plane].bytesused : length; if (b->m.planes[plane].bytesused > length) return -EINVAL; if (b->m.planes[plane].data_offset > 0 && - b->m.planes[plane].data_offset >= - b->m.planes[plane].bytesused) + b->m.planes[plane].data_offset >= bytesused) return -EINVAL; } } else { length = (b->memory == V4L2_MEMORY_USERPTR) ? b->length : vb->v4l2_planes[0].length; + bytesused = b->bytesused ? b->bytesused : length; if (b->bytesused > length) return -EINVAL; @@ -1234,35 +1238,6 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b unsigned int plane; if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { - /* Fill in driver-provided information for OUTPUT types */ - if (V4L2_TYPE_IS_OUTPUT(b->type)) { - bool bytesused_is_used; - - /* Check if bytesused == 0 for all planes */ - for (plane = 0; plane < vb->num_planes; ++plane) - if (b->m.planes[plane].bytesused) - break; - bytesused_is_used = plane < vb->num_planes; - - /* - * Will have to go up to b->length when API starts - * accepting variable number of planes. - * - * If bytesused_is_used is false, then fall back to the - * full buffer size. In that case userspace clearly - * never bothered to set it and it's a safe assumption - * that they really meant to use the full plane sizes. - */ - for (plane = 0; plane < vb->num_planes; ++plane) { - struct v4l2_plane *pdst = &v4l2_planes[plane]; - struct v4l2_plane *psrc = &b->m.planes[plane]; - - pdst->bytesused = bytesused_is_used ? - psrc->bytesused : psrc->length; - pdst->data_offset = psrc->data_offset; - } - } - if (b->memory == V4L2_MEMORY_USERPTR) { for (plane = 0; plane < vb->num_planes; ++plane) { v4l2_planes[plane].m.userptr = @@ -1279,6 +1254,28 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b b->m.planes[plane].length; } } + + /* Fill in driver-provided information for OUTPUT types */ + if (V4L2_TYPE_IS_OUTPUT(b->type)) { + /* + * Will have to go up to b->length when API starts + * accepting variable number of planes. + * + * If bytesused == 0 for the output buffer, then fall + * back to the full buffer size. In that case + * userspace clearly never bothered to set it and + * it's a safe assumption that they really meant to + * use the full plane sizes. + */ + for (plane = 0; plane < vb->num_planes; ++plane) { + struct v4l2_plane *pdst = &v4l2_planes[plane]; + struct v4l2_plane *psrc = &b->m.planes[plane]; + + pdst->bytesused = psrc->bytesused ? + psrc->bytesused : pdst->length; + pdst->data_offset = psrc->data_offset; + } + } } else { /* * Single-planar buffers do not use planes array, @@ -1286,15 +1283,9 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b * In videobuf we use our internal V4l2_planes struct for * single-planar buffers as well, for simplicity. * - * If bytesused == 0, then fall back to the full buffer size - * as that's a sensible default. + * If bytesused == 0 for the output buffer, then fall back + * to the full buffer size as that's a sensible default. */ - if (V4L2_TYPE_IS_OUTPUT(b->type)) - v4l2_planes[0].bytesused = - b->bytesused ? b->bytesused : b->length; - else - v4l2_planes[0].bytesused = 0; - if (b->memory == V4L2_MEMORY_USERPTR) { v4l2_planes[0].m.userptr = b->m.userptr; v4l2_planes[0].length = b->length; @@ -1304,6 +1295,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b v4l2_planes[0].m.fd = b->m.fd; v4l2_planes[0].length = b->length; } + + if (V4L2_TYPE_IS_OUTPUT(b->type)) + v4l2_planes[0].bytesused = b->bytesused ? + b->bytesused : v4l2_planes[0].length; + else + v4l2_planes[0].bytesused = 0; + } /* Zero flags that the vb2 core handles */ -- cgit v1.2.3 From 1612f20ea025f55741b2d6e8b9c91047a7324a76 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Jul 2014 09:19:37 -0300 Subject: [media] vb2: fix vb2_poll for output streams vb2_poll should always return POLLOUT | POLLWRNORM as long as there are fewer buffers queued than there are buffers available. Poll for an output stream should only wait if all buffers are queued and nobody is dequeuing them. Signed-off-by: Hans Verkuil Acked-by: Marek Szyprowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index f33508f854a4..c359006074a8 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2596,6 +2596,13 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error) return res | POLLERR; + /* + * For output streams you can write as long as there are fewer buffers + * queued than there are buffers available. + */ + if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers) + return res | POLLOUT | POLLWRNORM; + if (list_empty(&q->done_list)) poll_wait(file, &q->done_wq, wait); -- cgit v1.2.3 From 23cd08c8f72405359862aff2ad2a8be1c232198c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 4 Aug 2014 02:33:53 -0300 Subject: [media] videobuf2-core: add comments before the WARN_ON Recently WARN_ON() calls have been added to warn if the driver is not properly returning buffers to vb2 in start_streaming (if it fails) or stop_streaming(). Add comments before those WARN_ON calls that refer to the videobuf2-core.h header that explains what drivers are supposed to do in these situations. That should help point developers in the right direction if they see these warnings. Signed-off-by: Hans Verkuil Acked-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index c359006074a8..d3f2a221db62 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1762,6 +1762,12 @@ static int vb2_start_streaming(struct vb2_queue *q) q->start_streaming_called = 0; dprintk(1, "driver refused to start streaming\n"); + /* + * If you see this warning, then the driver isn't cleaning up properly + * after a failed start_streaming(). See the start_streaming() + * documentation in videobuf2-core.h for more information how buffers + * should be returned to vb2 in start_streaming(). + */ if (WARN_ON(atomic_read(&q->owned_by_drv_count))) { unsigned i; @@ -2123,6 +2129,12 @@ static void __vb2_queue_cancel(struct vb2_queue *q) if (q->start_streaming_called) call_void_qop(q, stop_streaming, q); + /* + * If you see this warning, then the driver isn't cleaning up properly + * in stop_streaming(). See the stop_streaming() documentation in + * videobuf2-core.h for more information how buffers should be returned + * to vb2 in stop_streaming(). + */ if (WARN_ON(atomic_read(&q->owned_by_drv_count))) { for (i = 0; i < q->num_buffers; ++i) if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) -- cgit v1.2.3 From bf3593d939520559774cbfee03ba5f314d909620 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 4 Aug 2014 07:14:14 -0300 Subject: [media] vb2: fix vb2 state check when start_streaming fails Commit bd994ddb2a12a3ff48cd549ec82cdceaea9614df (vb2: Fix stream start and buffer completion race) broke the buffer state check in vb2_buffer_done. So accept all three possible states there since I can no longer tell the difference between vb2_buffer_done called from start_streaming or from elsewhere. Instead add a WARN_ON at the end of start_streaming that will check whether any buffers were added to the done list, since that implies that the wrong state was used as well. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Cc: stable@vger.kernel.org # for v3.15 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index d3f2a221db62..7f70fd521ab1 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1165,13 +1165,10 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE)) return; - if (!q->start_streaming_called) { - if (WARN_ON(state != VB2_BUF_STATE_QUEUED)) - state = VB2_BUF_STATE_QUEUED; - } else if (WARN_ON(state != VB2_BUF_STATE_DONE && - state != VB2_BUF_STATE_ERROR)) { - state = VB2_BUF_STATE_ERROR; - } + if (WARN_ON(state != VB2_BUF_STATE_DONE && + state != VB2_BUF_STATE_ERROR && + state != VB2_BUF_STATE_QUEUED)) + state = VB2_BUF_STATE_ERROR; #ifdef CONFIG_VIDEO_ADV_DEBUG /* @@ -1783,6 +1780,12 @@ static int vb2_start_streaming(struct vb2_queue *q) /* Must be zero now */ WARN_ON(atomic_read(&q->owned_by_drv_count)); } + /* + * If done_list is not empty, then start_streaming() didn't call + * vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED) but STATE_ERROR or + * STATE_DONE. + */ + WARN_ON(!list_empty(&q->done_list)); return ret; } -- cgit v1.2.3 From a9ae4692eda4b99f85757b15d60971ff78a0a0e2 Mon Sep 17 00:00:00 2001 From: Zhaowei Yuan Date: Thu, 21 Aug 2014 23:28:21 -0300 Subject: [media] vb2: fix plane index sanity check in vb2_plane_cookie() It's also invalid when plane_no is equal to vb->num_planes Signed-off-by: Zhaowei Yuan Cc: stable@vger.kernel.org # for v3.7 and up Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 7f70fd521ab1..c2126d874549 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1130,7 +1130,7 @@ EXPORT_SYMBOL_GPL(vb2_plane_vaddr); */ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) { - if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) + if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) return NULL; return call_ptr_memop(vb, cookie, vb->planes[plane_no].mem_priv); -- cgit v1.2.3 From 58d75f4b1ce26324b4d809b18f94819843a98731 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Sep 2014 16:16:35 -0300 Subject: [media] vb2: fix VBI/poll regression The recent conversion of saa7134 to vb2 unconvered a poll() bug that broke the teletext applications alevt and mtt. These applications expect that calling poll() without having called VIDIOC_STREAMON will cause poll() to return POLLERR. That did not happen in vb2. This patch fixes that behavior. It also fixes what should happen when poll() is called when STREAMON is called but no buffers have been queued. In that case poll() will also return POLLERR, but only for capture queues since output queues will always return POLLOUT anyway in that situation. This brings the vb2 behavior in line with the old videobuf behavior. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 17 ++++++++++++++--- include/media/videobuf2-core.h | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/media/v4l2-core/videobuf2-core.c') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index c2126d874549..25d3ae2188cb 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -971,6 +971,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) * to the userspace. */ req->count = allocated_buffers; + q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); return 0; } @@ -1018,6 +1019,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); q->memory = create->memory; + q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); } num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers); @@ -1821,6 +1823,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) */ list_add_tail(&vb->queued_entry, &q->queued_list); q->queued_count++; + q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; if (V4L2_TYPE_IS_OUTPUT(q->type)) { /* @@ -2287,6 +2290,7 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) * their normal dequeued state. */ __vb2_queue_cancel(q); + q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); dprintk(3, "successful\n"); return 0; @@ -2605,10 +2609,17 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) } /* - * There is nothing to wait for if no buffer has been queued and the - * queue isn't streaming, or if the error flag is set. + * There is nothing to wait for if the queue isn't streaming, or if the + * error flag is set. */ - if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error) + if (!vb2_is_streaming(q) || q->error) + return res | POLLERR; + /* + * For compatibility with vb1: if QBUF hasn't been called yet, then + * return POLLERR as well. This only affects capture queues, output + * queues will always initialize waiting_for_buffers to false. + */ + if (q->waiting_for_buffers) return res | POLLERR; /* diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 80fa7253e483..2fefcf491aa8 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -380,6 +380,9 @@ struct v4l2_fh; * @start_streaming_called: start_streaming() was called successfully and we * started streaming. * @error: a fatal error occurred on the queue + * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for + * buffers. Only set for capture queues if qbuf has not yet been + * called since poll() needs to return POLLERR in that situation. * @fileio: file io emulator internal data, used only if emulator is active * @threadio: thread io internal data, used only if thread is active */ @@ -417,6 +420,7 @@ struct vb2_queue { unsigned int streaming:1; unsigned int start_streaming_called:1; unsigned int error:1; + unsigned int waiting_for_buffers:1; struct vb2_fileio_data *fileio; struct vb2_threadio_data *threadio; -- cgit v1.2.3