summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2014-03-04 07:34:49 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-03-11 06:56:39 -0300
commit9c0863b1cc485f2bacac0675c68b73e5341cfd26 (patch)
treeadd2ca56deca15ea064d34966edfa21dcef40fe3 /drivers
parent1a17948184a3320e0bb0aab561112211d2e9b7a8 (diff)
[media] vb2: call buf_finish from __queue_cancel
If a queue was canceled, then the buf_finish op was never called for the pending buffers. So add this call to queue_cancel. Before calling buf_finish set the buffer state to PREPARED, which is the correct state. That way the states DONE and ERROR will only be seen in buf_finish if streaming is in progress. Since buf_finish can now be called from non-streaming state we need to adapt the handful of drivers that actually need to know this. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/parport/bw-qcam.c3
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c3
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c3
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c17
4 files changed, 22 insertions, 4 deletions
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
index cf2db63da3b..8a0e84c7d49 100644
--- a/drivers/media/parport/bw-qcam.c
+++ b/drivers/media/parport/bw-qcam.c
@@ -674,6 +674,9 @@ static void buffer_finish(struct vb2_buffer *vb)
int size = vb->vb2_queue->plane_sizes[0];
int len;
+ if (!vb2_is_streaming(vb->vb2_queue))
+ return;
+
mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev);
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index e66556cae7e..bb11443ed63 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -337,7 +337,8 @@ static void buffer_finish(struct vb2_buffer *vb)
list_del_init(&vip_buf->list);
spin_unlock(&vip->lock);
- vip_active_buf_next(vip);
+ if (vb2_is_streaming(vb->vb2_queue))
+ vip_active_buf_next(vip);
}
static int start_streaming(struct vb2_queue *vq, unsigned int count)
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 26172cbcf09..6e92d208025 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -113,7 +113,8 @@ static void uvc_buffer_finish(struct vb2_buffer *vb)
container_of(queue, struct uvc_streaming, queue);
struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
- uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+ if (vb->state == VB2_BUF_STATE_DONE)
+ uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
}
static void uvc_wait_prepare(struct vb2_queue *vq)
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 2be3cfec2ac..16ae66f5584 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1929,9 +1929,22 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
/*
* Reinitialize all buffers for next use.
+ * Make sure to call buf_finish for any queued buffers. Normally
+ * that's done in dqbuf, but that's not going to happen when we
+ * cancel the whole queue. Note: this code belongs here, not in
+ * __vb2_dqbuf() since in vb2_internal_dqbuf() there is a critical
+ * call to __fill_v4l2_buffer() after buf_finish(). That order can't
+ * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
*/
- for (i = 0; i < q->num_buffers; ++i)
- __vb2_dqbuf(q->bufs[i]);
+ for (i = 0; i < q->num_buffers; ++i) {
+ struct vb2_buffer *vb = q->bufs[i];
+
+ if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+ vb->state = VB2_BUF_STATE_PREPARED;
+ call_vb_qop(vb, buf_finish, vb);
+ }
+ __vb2_dqbuf(vb);
+ }
}
static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)