[media] v4l: vb2: Add fatal error condition flag
[deliverable/linux.git] / drivers / media / v4l2-core / videobuf2-core.c
index 7c4489c4236502042fc1fcb3a0ff545f2f7639a7..a5c41cc65d1c7024d28e5a5b35c6caa93abaeab4 100644 (file)
@@ -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;
@@ -1750,12 +1755,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;
@@ -1901,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.
@@ -1926,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
@@ -2123,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...
@@ -2199,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
@@ -2557,9 +2592,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, or if the error flag is set.
         */
-       if (list_empty(&q->queued_list))
+       if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error)
                return res | POLLERR;
 
        if (list_empty(&q->done_list))
This page took 0.029774 seconds and 5 git commands to generate.