diff options
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-core.c | 39 | ||||
-rw-r--r-- | include/media/videobuf2-core.h | 3 |
2 files changed, 39 insertions, 3 deletions
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... @@ -2202,6 +2214,27 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type) } /** + * 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 * @type: type argument passed from userspace to vidioc_streamon handler @@ -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); |