summaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/v4l2-core')
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c39
1 files changed, 36 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))
OpenPOWER on IntegriCloud