From 1c80d4725af213093775cd2c86ff045fa1aed57a Mon Sep 17 00:00:00 2001 From: John Sheu Date: Tue, 16 Apr 2013 22:04:18 -0700 Subject: [PATCH] v4l2: dequeue buffers properly on VIDIOC_STREAMOFF Instead of just marking all buffers as dequeued on STREAMOFF, properly dequeue them -- this will, most notably, make sure that any mapped DMABUF buffers will be properly unmapped. BUG=chromium:232121 TEST=local build, run on CrOS snow Change-Id: Ide111378caa70cf603b3edec65b4dedd0f1e1ea0 Signed-off-by: John Sheu Reviewed-on: https://gerrit.chromium.org/gerrit/48346 Reviewed-by: Pawel Osciak --- drivers/media/video/videobuf2-core.c | 47 +++++++++++++++++++--------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index ecab4a38f693..0956bd290e3a 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -1473,6 +1473,35 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers); +/** + * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state + */ +static void __vb2_dqbuf(struct vb2_buffer *vb) +{ + struct vb2_queue *q = vb->vb2_queue; + unsigned int i; + + /* nothing to do if the buffer is already dequeued */ + if (vb->state == VB2_BUF_STATE_DEQUEUED) + return; + + vb->state = VB2_BUF_STATE_DEQUEUED; + + /* unmap DMABUF buffer + * TODO: this unpins the buffer(dma_buf_unmap_attachment()).. but + * really we want to do this just after DMA, not when the + * buffer is dequeued.. + */ + if (q->memory == V4L2_MEMORY_DMABUF) { + for (i = 0; i < vb->num_planes; ++i) { + if (!vb->planes[i].dbuf_mapped) + continue; + call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv); + vb->planes[i].dbuf_mapped = 0; + } + } +} + /** * vb2_dqbuf() - Dequeue a buffer to the userspace * @q: videobuf2 queue @@ -1521,19 +1550,6 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) return ret; } - /* TODO: this unpins the buffer(dma_buf_unmap_attachment()).. but - * really we want to do this just after DMA, not when the - * buffer is dequeued.. - */ - if (q->memory == V4L2_MEMORY_DMABUF) { - unsigned int i; - - for (i = 0; i < vb->num_planes; ++i) { - call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv); - vb->planes[i].dbuf_mapped = 0; - } - } - switch (vb->state) { case VB2_BUF_STATE_DONE: dprintk(3, "dqbuf: Returning done buffer\n"); @@ -1550,11 +1566,12 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) __fill_v4l2_buffer(vb, b); /* Remove from videobuf queue */ list_del(&vb->queued_entry); + /* go back to dequeued state */ + __vb2_dqbuf(vb); dprintk(1, "dqbuf of buffer %d, with state %d\n", vb->v4l2_buf.index, vb->state); - vb->state = VB2_BUF_STATE_DEQUEUED; return 0; } EXPORT_SYMBOL_GPL(vb2_dqbuf); @@ -1593,7 +1610,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q) * Reinitialize all buffers for next use. */ for (i = 0; i < q->num_buffers; ++i) - q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; + __vb2_dqbuf(q->bufs[i]); } /** -- 2.20.1