diff options
Diffstat (limited to 'drivers/media/v4l2-core/videobuf2-core.c')
| -rw-r--r-- | drivers/media/v4l2-core/videobuf2-core.c | 1573 |
1 files changed, 1142 insertions, 431 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 594c75eab5a..7c4489c4236 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -6,6 +6,9 @@ * Author: Pawel Osciak <pawel@osciak.com> * Marek Szyprowski <m.szyprowski@samsung.com> * + * The vb2_thread implementation was based on code from videobuf-dvb.c: + * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. @@ -18,32 +21,167 @@ #include <linux/poll.h> #include <linux/slab.h> #include <linux/sched.h> +#include <linux/freezer.h> +#include <linux/kthread.h> #include <media/v4l2-dev.h> #include <media/v4l2-fh.h> #include <media/v4l2-event.h> +#include <media/v4l2-common.h> #include <media/videobuf2-core.h> static int debug; module_param(debug, int, 0644); -#define dprintk(level, fmt, arg...) \ - do { \ - if (debug >= level) \ - printk(KERN_DEBUG "vb2: " fmt, ## arg); \ +#define dprintk(level, fmt, arg...) \ + do { \ + if (debug >= level) \ + pr_debug("vb2: %s: " fmt, __func__, ## arg); \ } while (0) -#define call_memop(q, op, args...) \ - (((q)->mem_ops->op) ? \ - ((q)->mem_ops->op(args)) : 0) +#ifdef CONFIG_VIDEO_ADV_DEBUG + +/* + * If advanced debugging is on, then count how often each op is called + * successfully, which can either be per-buffer or per-queue. + * + * This makes it easy to check that the 'init' and 'cleanup' + * (and variations thereof) stay balanced. + */ + +#define log_memop(vb, op) \ + dprintk(2, "call_memop(%p, %d, %s)%s\n", \ + (vb)->vb2_queue, (vb)->v4l2_buf.index, #op, \ + (vb)->vb2_queue->mem_ops->op ? "" : " (nop)") + +#define call_memop(vb, op, args...) \ +({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + int err; \ + \ + log_memop(vb, op); \ + err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \ + if (!err) \ + (vb)->cnt_mem_ ## op++; \ + err; \ +}) + +#define call_ptr_memop(vb, op, args...) \ +({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + void *ptr; \ + \ + log_memop(vb, op); \ + ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \ + if (!IS_ERR_OR_NULL(ptr)) \ + (vb)->cnt_mem_ ## op++; \ + ptr; \ +}) + +#define call_void_memop(vb, op, args...) \ +({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + \ + log_memop(vb, op); \ + if (_q->mem_ops->op) \ + _q->mem_ops->op(args); \ + (vb)->cnt_mem_ ## op++; \ +}) + +#define log_qop(q, op) \ + dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \ + (q)->ops->op ? "" : " (nop)") + +#define call_qop(q, op, args...) \ +({ \ + int err; \ + \ + log_qop(q, op); \ + err = (q)->ops->op ? (q)->ops->op(args) : 0; \ + if (!err) \ + (q)->cnt_ ## op++; \ + err; \ +}) + +#define call_void_qop(q, op, args...) \ +({ \ + log_qop(q, op); \ + if ((q)->ops->op) \ + (q)->ops->op(args); \ + (q)->cnt_ ## op++; \ +}) + +#define log_vb_qop(vb, op, args...) \ + dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \ + (vb)->vb2_queue, (vb)->v4l2_buf.index, #op, \ + (vb)->vb2_queue->ops->op ? "" : " (nop)") + +#define call_vb_qop(vb, op, args...) \ +({ \ + int err; \ + \ + log_vb_qop(vb, op); \ + err = (vb)->vb2_queue->ops->op ? \ + (vb)->vb2_queue->ops->op(args) : 0; \ + if (!err) \ + (vb)->cnt_ ## op++; \ + err; \ +}) + +#define call_void_vb_qop(vb, op, args...) \ +({ \ + log_vb_qop(vb, op); \ + if ((vb)->vb2_queue->ops->op) \ + (vb)->vb2_queue->ops->op(args); \ + (vb)->cnt_ ## op++; \ +}) + +#else + +#define call_memop(vb, op, args...) \ + ((vb)->vb2_queue->mem_ops->op ? \ + (vb)->vb2_queue->mem_ops->op(args) : 0) + +#define call_ptr_memop(vb, op, args...) \ + ((vb)->vb2_queue->mem_ops->op ? \ + (vb)->vb2_queue->mem_ops->op(args) : NULL) + +#define call_void_memop(vb, op, args...) \ + do { \ + if ((vb)->vb2_queue->mem_ops->op) \ + (vb)->vb2_queue->mem_ops->op(args); \ + } while (0) #define call_qop(q, op, args...) \ - (((q)->ops->op) ? ((q)->ops->op(args)) : 0) + ((q)->ops->op ? (q)->ops->op(args) : 0) + +#define call_void_qop(q, op, args...) \ + do { \ + if ((q)->ops->op) \ + (q)->ops->op(args); \ + } while (0) + +#define call_vb_qop(vb, op, args...) \ + ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0) + +#define call_void_vb_qop(vb, op, args...) \ + do { \ + if ((vb)->vb2_queue->ops->op) \ + (vb)->vb2_queue->ops->op(args); \ + } while (0) +#endif + +/* Flags that are set by the vb2 core */ #define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \ V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \ V4L2_BUF_FLAG_PREPARED | \ V4L2_BUF_FLAG_TIMESTAMP_MASK) +/* Output buffer flags that should be passed on to the driver */ +#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \ + V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE) + +static void __vb2_queue_cancel(struct vb2_queue *q); /** * __vb2_buf_mem_alloc() - allocate video memory for the given buffer @@ -61,7 +199,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) for (plane = 0; plane < vb->num_planes; ++plane) { unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]); - mem_priv = call_memop(q, alloc, q->alloc_ctx[plane], + mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane], size, q->gfp_flags); if (IS_ERR_OR_NULL(mem_priv)) goto free; @@ -75,7 +213,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) free: /* Free already allocated memory if one of the allocations failed */ for (; plane > 0; --plane) { - call_memop(q, put, vb->planes[plane - 1].mem_priv); + call_void_memop(vb, put, vb->planes[plane - 1].mem_priv); vb->planes[plane - 1].mem_priv = NULL; } @@ -87,13 +225,12 @@ free: */ static void __vb2_buf_mem_free(struct vb2_buffer *vb) { - struct vb2_queue *q = vb->vb2_queue; unsigned int plane; for (plane = 0; plane < vb->num_planes; ++plane) { - call_memop(q, put, vb->planes[plane].mem_priv); + call_void_memop(vb, put, vb->planes[plane].mem_priv); vb->planes[plane].mem_priv = NULL; - dprintk(3, "Freed plane %d of buffer %d\n", plane, + dprintk(3, "freed plane %d of buffer %d\n", plane, vb->v4l2_buf.index); } } @@ -104,12 +241,11 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb) */ static void __vb2_buf_userptr_put(struct vb2_buffer *vb) { - struct vb2_queue *q = vb->vb2_queue; unsigned int plane; for (plane = 0; plane < vb->num_planes; ++plane) { if (vb->planes[plane].mem_priv) - call_memop(q, put_userptr, vb->planes[plane].mem_priv); + call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv); vb->planes[plane].mem_priv = NULL; } } @@ -118,15 +254,15 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb) * __vb2_plane_dmabuf_put() - release memory associated with * a DMABUF shared plane */ -static void __vb2_plane_dmabuf_put(struct vb2_queue *q, struct vb2_plane *p) +static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) { if (!p->mem_priv) return; if (p->dbuf_mapped) - call_memop(q, unmap_dmabuf, p->mem_priv); + call_void_memop(vb, unmap_dmabuf, p->mem_priv); - call_memop(q, detach_dmabuf, p->mem_priv); + call_void_memop(vb, detach_dmabuf, p->mem_priv); dma_buf_put(p->dbuf); memset(p, 0, sizeof(*p)); } @@ -137,11 +273,29 @@ static void __vb2_plane_dmabuf_put(struct vb2_queue *q, struct vb2_plane *p) */ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb) { - struct vb2_queue *q = vb->vb2_queue; unsigned int plane; for (plane = 0; plane < vb->num_planes; ++plane) - __vb2_plane_dmabuf_put(q, &vb->planes[plane]); + __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); +} + +/** + * __setup_lengths() - setup initial lengths for every plane in + * every buffer on the queue + */ +static void __setup_lengths(struct vb2_queue *q, unsigned int n) +{ + unsigned int buffer, plane; + struct vb2_buffer *vb; + + for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) { + vb = q->bufs[buffer]; + if (!vb) + continue; + + for (plane = 0; plane < vb->num_planes; ++plane) + vb->v4l2_planes[plane].length = q->plane_sizes[plane]; + } } /** @@ -169,10 +323,9 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n) continue; for (plane = 0; plane < vb->num_planes; ++plane) { - vb->v4l2_planes[plane].length = q->plane_sizes[plane]; vb->v4l2_planes[plane].m.mem_offset = off; - dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n", + dprintk(3, "buffer %d, plane %d offset 0x%08lx\n", buffer, plane, off); off += vb->v4l2_planes[plane].length; @@ -199,7 +352,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, /* Allocate videobuf buffer structures */ vb = kzalloc(q->buf_struct_size, GFP_KERNEL); if (!vb) { - dprintk(1, "Memory alloc for buffer struct failed\n"); + dprintk(1, "memory alloc for buffer struct failed\n"); break; } @@ -218,7 +371,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, if (memory == V4L2_MEMORY_MMAP) { ret = __vb2_buf_mem_alloc(vb); if (ret) { - dprintk(1, "Failed allocating memory for " + dprintk(1, "failed allocating memory for " "buffer %d\n", buffer); kfree(vb); break; @@ -228,9 +381,9 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, * callback, if given. An error in initialization * results in queue setup failure. */ - ret = call_qop(q, buf_init, vb); + ret = call_vb_qop(vb, buf_init, vb); if (ret) { - dprintk(1, "Buffer %d %p initialization" + dprintk(1, "buffer %d %p initialization" " failed\n", buffer, vb); __vb2_buf_mem_free(vb); kfree(vb); @@ -241,9 +394,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, q->bufs[q->num_buffers + buffer] = vb; } - __setup_offsets(q, buffer); + __setup_lengths(q, buffer); + if (memory == V4L2_MEMORY_MMAP) + __setup_offsets(q, buffer); - dprintk(1, "Allocated %d buffers, %d plane(s) each\n", + dprintk(1, "allocated %d buffers, %d plane(s) each\n", buffer, num_planes); return buffer; @@ -278,23 +433,102 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers) * related information, if no buffers are left return the queue to an * uninitialized state. Might be called even if the queue has already been freed. */ -static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) +static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) { unsigned int buffer; - /* Call driver-provided cleanup function for each buffer, if provided */ - if (q->ops->buf_cleanup) { - for (buffer = q->num_buffers - buffers; buffer < q->num_buffers; - ++buffer) { - if (NULL == q->bufs[buffer]) - continue; - q->ops->buf_cleanup(q->bufs[buffer]); + /* + * Sanity check: when preparing a buffer the queue lock is released for + * a short while (see __buf_prepare for the details), which would allow + * a race with a reqbufs which can call this function. Removing the + * buffers from underneath __buf_prepare is obviously a bad idea, so we + * check if any of the buffers is in the state PREPARING, and if so we + * just return -EAGAIN. + */ + for (buffer = q->num_buffers - buffers; buffer < q->num_buffers; + ++buffer) { + if (q->bufs[buffer] == NULL) + continue; + if (q->bufs[buffer]->state == VB2_BUF_STATE_PREPARING) { + dprintk(1, "preparing buffers, cannot free\n"); + return -EAGAIN; } } + /* Call driver-provided cleanup function for each buffer, if provided */ + for (buffer = q->num_buffers - buffers; buffer < q->num_buffers; + ++buffer) { + struct vb2_buffer *vb = q->bufs[buffer]; + + if (vb && vb->planes[0].mem_priv) + call_void_vb_qop(vb, buf_cleanup, vb); + } + /* Release video buffer memory */ __vb2_free_mem(q, buffers); +#ifdef CONFIG_VIDEO_ADV_DEBUG + /* + * Check that all the calls were balances during the life-time of this + * queue. If not (or if the debug level is 1 or up), then dump the + * counters to the kernel log. + */ + if (q->num_buffers) { + bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming || + q->cnt_wait_prepare != q->cnt_wait_finish; + + if (unbalanced || debug) { + pr_info("vb2: counters for queue %p:%s\n", q, + unbalanced ? " UNBALANCED!" : ""); + pr_info("vb2: setup: %u start_streaming: %u stop_streaming: %u\n", + q->cnt_queue_setup, q->cnt_start_streaming, + q->cnt_stop_streaming); + pr_info("vb2: wait_prepare: %u wait_finish: %u\n", + q->cnt_wait_prepare, q->cnt_wait_finish); + } + q->cnt_queue_setup = 0; + q->cnt_wait_prepare = 0; + q->cnt_wait_finish = 0; + q->cnt_start_streaming = 0; + q->cnt_stop_streaming = 0; + } + for (buffer = 0; buffer < q->num_buffers; ++buffer) { + struct vb2_buffer *vb = q->bufs[buffer]; + bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put || + vb->cnt_mem_prepare != vb->cnt_mem_finish || + vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr || + vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf || + vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf || + vb->cnt_buf_queue != vb->cnt_buf_done || + vb->cnt_buf_prepare != vb->cnt_buf_finish || + vb->cnt_buf_init != vb->cnt_buf_cleanup; + + if (unbalanced || debug) { + pr_info("vb2: counters for queue %p, buffer %d:%s\n", + q, buffer, unbalanced ? " UNBALANCED!" : ""); + pr_info("vb2: buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n", + vb->cnt_buf_init, vb->cnt_buf_cleanup, + vb->cnt_buf_prepare, vb->cnt_buf_finish); + pr_info("vb2: buf_queue: %u buf_done: %u\n", + vb->cnt_buf_queue, vb->cnt_buf_done); + pr_info("vb2: alloc: %u put: %u prepare: %u finish: %u mmap: %u\n", + vb->cnt_mem_alloc, vb->cnt_mem_put, + vb->cnt_mem_prepare, vb->cnt_mem_finish, + vb->cnt_mem_mmap); + pr_info("vb2: get_userptr: %u put_userptr: %u\n", + vb->cnt_mem_get_userptr, vb->cnt_mem_put_userptr); + pr_info("vb2: attach_dmabuf: %u detach_dmabuf: %u map_dmabuf: %u unmap_dmabuf: %u\n", + vb->cnt_mem_attach_dmabuf, vb->cnt_mem_detach_dmabuf, + vb->cnt_mem_map_dmabuf, vb->cnt_mem_unmap_dmabuf); + pr_info("vb2: get_dmabuf: %u num_users: %u vaddr: %u cookie: %u\n", + vb->cnt_mem_get_dmabuf, + vb->cnt_mem_num_users, + vb->cnt_mem_vaddr, + vb->cnt_mem_cookie); + } + } +#endif + /* Free videobuf buffers */ for (buffer = q->num_buffers - buffers; buffer < q->num_buffers; ++buffer) { @@ -303,9 +537,11 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) } q->num_buffers -= buffers; - if (!q->num_buffers) + if (!q->num_buffers) { q->memory = 0; - INIT_LIST_HEAD(&q->queued_list); + INIT_LIST_HEAD(&q->queued_list); + } + return 0; } /** @@ -319,13 +555,13 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer /* Is memory for copying plane information present? */ if (NULL == b->m.planes) { - dprintk(1, "Multi-planar buffer passed but " + dprintk(1, "multi-planar buffer passed but " "planes array not provided\n"); return -EINVAL; } if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) { - dprintk(1, "Incorrect planes array length, " + dprintk(1, "incorrect planes array length, " "expected %d, got %d\n", vb->num_planes, b->length); return -EINVAL; } @@ -353,7 +589,9 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) if (b->m.planes[plane].bytesused > length) return -EINVAL; - if (b->m.planes[plane].data_offset >= + + if (b->m.planes[plane].data_offset > 0 && + b->m.planes[plane].data_offset >= b->m.planes[plane].bytesused) return -EINVAL; } @@ -383,7 +621,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) * case anyway. If num_users() returns more than 1, * we are not the only user of the plane's memory. */ - if (mem_priv && call_memop(q, num_users, mem_priv) > 1) + if (mem_priv && call_memop(vb, num_users, mem_priv) > 1) return true; } return false; @@ -443,7 +681,16 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) * Clear any buffer state related flags. */ b->flags &= ~V4L2_BUFFER_MASK_FLAGS; - b->flags |= q->timestamp_type; + b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK; + if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) != + V4L2_BUF_FLAG_TIMESTAMP_COPY) { + /* + * For non-COPY timestamps, drop timestamp source bits + * and obtain the timestamp source from the queue. + */ + b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + } switch (vb->state) { case VB2_BUF_STATE_QUEUED: @@ -459,6 +706,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) case VB2_BUF_STATE_PREPARED: b->flags |= V4L2_BUF_FLAG_PREPARED; break; + case VB2_BUF_STATE_PREPARING: case VB2_BUF_STATE_DEQUEUED: /* nothing */ break; @@ -487,12 +735,12 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) int ret; if (b->type != q->type) { - dprintk(1, "querybuf: wrong buffer type\n"); + dprintk(1, "wrong buffer type\n"); return -EINVAL; } if (b->index >= q->num_buffers) { - dprintk(1, "querybuf: buffer index out of range\n"); + dprintk(1, "buffer index out of range\n"); return -EINVAL; } vb = q->bufs[b->index]; @@ -552,12 +800,12 @@ static int __verify_memory_type(struct vb2_queue *q, { if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR && memory != V4L2_MEMORY_DMABUF) { - dprintk(1, "reqbufs: unsupported memory type\n"); + dprintk(1, "unsupported memory type\n"); return -EINVAL; } if (type != q->type) { - dprintk(1, "reqbufs: requested type is incorrect\n"); + dprintk(1, "requested type is incorrect\n"); return -EINVAL; } @@ -566,17 +814,17 @@ static int __verify_memory_type(struct vb2_queue *q, * are available. */ if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) { - dprintk(1, "reqbufs: MMAP for current setup unsupported\n"); + dprintk(1, "MMAP for current setup unsupported\n"); return -EINVAL; } if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) { - dprintk(1, "reqbufs: USERPTR for current setup unsupported\n"); + dprintk(1, "USERPTR for current setup unsupported\n"); return -EINVAL; } if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) { - dprintk(1, "reqbufs: DMABUF for current setup unsupported\n"); + dprintk(1, "DMABUF for current setup unsupported\n"); return -EINVAL; } @@ -585,8 +833,8 @@ static int __verify_memory_type(struct vb2_queue *q, * create_bufs is called with count == 0, but count == 0 should still * do the memory and type validation. */ - if (q->fileio) { - dprintk(1, "reqbufs: file io in progress\n"); + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); return -EBUSY; } return 0; @@ -621,7 +869,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) int ret; if (q->streaming) { - dprintk(1, "reqbufs: streaming active\n"); + dprintk(1, "streaming active\n"); return -EBUSY; } @@ -631,11 +879,19 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) * are not in use and can be freed. */ if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) { - dprintk(1, "reqbufs: memory in use, cannot free\n"); + dprintk(1, "memory in use, cannot free\n"); return -EBUSY; } - __vb2_queue_free(q, q->num_buffers); + /* + * Call queue_cancel to clean up any buffers in the PREPARED or + * QUEUED state which is possible if buffers were prepared or + * queued without ever calling STREAMON. + */ + __vb2_queue_cancel(q); + ret = __vb2_queue_free(q, q->num_buffers); + if (ret) + return ret; /* * In case of REQBUFS(0) return immediately without calling @@ -649,6 +905,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) * Make sure the requested values and current defaults are sane. */ num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME); + num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed); memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); q->memory = req->memory; @@ -663,18 +920,23 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) return ret; /* Finally, allocate buffers and video memory */ - ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes); - if (ret == 0) { - dprintk(1, "Memory allocation failed\n"); + allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes); + if (allocated_buffers == 0) { + dprintk(1, "memory allocation failed\n"); return -ENOMEM; } - allocated_buffers = ret; + /* + * There is no point in continuing if we can't allocate the minimum + * number of buffers needed by this vb2_queue. + */ + if (allocated_buffers < q->min_buffers_needed) + ret = -ENOMEM; /* * Check if driver can handle the allocated number of buffers. */ - if (allocated_buffers < num_buffers) { + if (!ret && allocated_buffers < num_buffers) { num_buffers = allocated_buffers; ret = call_qop(q, queue_setup, q, NULL, &num_buffers, @@ -692,6 +954,10 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) q->num_buffers = allocated_buffers; if (ret < 0) { + /* + * Note: __vb2_queue_free() will subtract 'allocated_buffers' + * from q->num_buffers. + */ __vb2_queue_free(q, allocated_buffers); return ret; } @@ -740,8 +1006,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create int ret; if (q->num_buffers == VIDEO_MAX_FRAME) { - dprintk(1, "%s(): maximum number of buffers already allocated\n", - __func__); + dprintk(1, "maximum number of buffers already allocated\n"); return -ENOBUFS; } @@ -763,20 +1028,18 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create return ret; /* Finally, allocate buffers and video memory */ - ret = __vb2_queue_alloc(q, create->memory, num_buffers, + allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers, num_planes); - if (ret == 0) { - dprintk(1, "Memory allocation failed\n"); + if (allocated_buffers == 0) { + dprintk(1, "memory allocation failed\n"); return -ENOMEM; } - allocated_buffers = ret; - /* * Check if driver can handle the so far allocated number of buffers. */ - if (ret < num_buffers) { - num_buffers = ret; + if (allocated_buffers < num_buffers) { + num_buffers = allocated_buffers; /* * q->num_buffers contains the total number of buffers, that the @@ -797,6 +1060,10 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create q->num_buffers += allocated_buffers; if (ret < 0) { + /* + * Note: __vb2_queue_free() will subtract 'allocated_buffers' + * from q->num_buffers. + */ __vb2_queue_free(q, allocated_buffers); return -ENOMEM; } @@ -838,12 +1105,10 @@ EXPORT_SYMBOL_GPL(vb2_create_bufs); */ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) { - struct vb2_queue *q = vb->vb2_queue; - if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) return NULL; - return call_memop(q, vaddr, vb->planes[plane_no].mem_priv); + return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv); } EXPORT_SYMBOL_GPL(vb2_plane_vaddr); @@ -861,12 +1126,10 @@ EXPORT_SYMBOL_GPL(vb2_plane_vaddr); */ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) { - struct vb2_queue *q = vb->vb2_queue; - if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) return NULL; - return call_memop(q, cookie, vb->planes[plane_no].mem_priv); + return call_ptr_memop(vb, cookie, vb->planes[plane_no].mem_priv); } EXPORT_SYMBOL_GPL(vb2_plane_cookie); @@ -874,13 +1137,20 @@ EXPORT_SYMBOL_GPL(vb2_plane_cookie); * vb2_buffer_done() - inform videobuf that an operation on a buffer is finished * @vb: vb2_buffer returned from the driver * @state: either VB2_BUF_STATE_DONE if the operation finished successfully - * or VB2_BUF_STATE_ERROR if the operation finished with an error + * or VB2_BUF_STATE_ERROR if the operation finished with an error. + * If start_streaming fails then it should return buffers with state + * VB2_BUF_STATE_QUEUED to put them back into the queue. * * This function should be called by the driver after a hardware operation on * a buffer is finished and the buffer may be returned to userspace. The driver * cannot use this buffer anymore until it is queued back to it by videobuf * by the means of buf_queue callback. Only buffers previously queued to the * driver by buf_queue can be passed to this function. + * + * While streaming a buffer can only be returned in state DONE or ERROR. + * The start_streaming op can also return them in case the DMA engine cannot + * be started for some reason. In that case the buffers should be returned with + * state QUEUED. */ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) { @@ -888,32 +1158,72 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) unsigned long flags; unsigned int plane; - if (vb->state != VB2_BUF_STATE_ACTIVE) + if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE)) return; - if (state != VB2_BUF_STATE_DONE && state != VB2_BUF_STATE_ERROR) - return; + if (!q->start_streaming_called) { + if (WARN_ON(state != VB2_BUF_STATE_QUEUED)) + state = VB2_BUF_STATE_QUEUED; + } else if (WARN_ON(state != VB2_BUF_STATE_DONE && + state != VB2_BUF_STATE_ERROR)) { + state = VB2_BUF_STATE_ERROR; + } - dprintk(4, "Done processing on buffer %d, state: %d\n", +#ifdef CONFIG_VIDEO_ADV_DEBUG + /* + * Although this is not a callback, it still does have to balance + * with the buf_queue op. So update this counter manually. + */ + vb->cnt_buf_done++; +#endif + dprintk(4, "done processing on buffer %d, state: %d\n", vb->v4l2_buf.index, state); /* sync buffers */ for (plane = 0; plane < vb->num_planes; ++plane) - call_memop(q, finish, vb->planes[plane].mem_priv); + call_void_memop(vb, finish, vb->planes[plane].mem_priv); /* Add the buffer to the done buffers list */ spin_lock_irqsave(&q->done_lock, flags); vb->state = state; - list_add_tail(&vb->done_entry, &q->done_list); - atomic_dec(&q->queued_count); + if (state != VB2_BUF_STATE_QUEUED) + list_add_tail(&vb->done_entry, &q->done_list); + atomic_dec(&q->owned_by_drv_count); spin_unlock_irqrestore(&q->done_lock, flags); + if (state == VB2_BUF_STATE_QUEUED) + return; + /* Inform any processes that may be waiting for buffers */ wake_up(&q->done_wq); } EXPORT_SYMBOL_GPL(vb2_buffer_done); /** + * vb2_discard_done() - discard all buffers marked as DONE + * @q: videobuf2 queue + * + * This function is intended to be used with suspend/resume operations. It + * discards all 'done' buffers as they would be too old to be requested after + * resume. + * + * Drivers must stop the hardware and synchronize with interrupt handlers and/or + * delayed works before calling this function to make sure no buffer will be + * touched by the driver and/or hardware. + */ +void vb2_discard_done(struct vb2_queue *q) +{ + struct vb2_buffer *vb; + unsigned long flags; + + spin_lock_irqsave(&q->done_lock, flags); + list_for_each_entry(vb, &q->done_list, done_entry) + vb->state = VB2_BUF_STATE_ERROR; + spin_unlock_irqrestore(&q->done_lock, flags); +} +EXPORT_SYMBOL_GPL(vb2_discard_done); + +/** * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a * v4l2_buffer by the userspace. The caller has already verified that struct * v4l2_buffer has a valid number of planes. @@ -926,15 +1236,30 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { /* Fill in driver-provided information for OUTPUT types */ if (V4L2_TYPE_IS_OUTPUT(b->type)) { + bool bytesused_is_used; + + /* Check if bytesused == 0 for all planes */ + for (plane = 0; plane < vb->num_planes; ++plane) + if (b->m.planes[plane].bytesused) + break; + bytesused_is_used = plane < vb->num_planes; + /* * Will have to go up to b->length when API starts * accepting variable number of planes. + * + * If bytesused_is_used is false, then fall back to the + * full buffer size. In that case userspace clearly + * never bothered to set it and it's a safe assumption + * that they really meant to use the full plane sizes. */ for (plane = 0; plane < vb->num_planes; ++plane) { - v4l2_planes[plane].bytesused = - b->m.planes[plane].bytesused; - v4l2_planes[plane].data_offset = - b->m.planes[plane].data_offset; + struct v4l2_plane *pdst = &v4l2_planes[plane]; + struct v4l2_plane *psrc = &b->m.planes[plane]; + + pdst->bytesused = bytesused_is_used ? + psrc->bytesused : psrc->length; + pdst->data_offset = psrc->data_offset; } } @@ -952,8 +1277,6 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b b->m.planes[plane].m.fd; v4l2_planes[plane].length = b->m.planes[plane].length; - v4l2_planes[plane].data_offset = - b->m.planes[plane].data_offset; } } } else { @@ -962,11 +1285,15 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b * so fill in relevant v4l2_buffer struct fields instead. * In videobuf we use our internal V4l2_planes struct for * single-planar buffers as well, for simplicity. + * + * If bytesused == 0, then fall back to the full buffer size + * as that's a sensible default. */ - if (V4L2_TYPE_IS_OUTPUT(b->type)) { - v4l2_planes[0].bytesused = b->bytesused; - v4l2_planes[0].data_offset = 0; - } + if (V4L2_TYPE_IS_OUTPUT(b->type)) + v4l2_planes[0].bytesused = + b->bytesused ? b->bytesused : b->length; + else + v4l2_planes[0].bytesused = 0; if (b->memory == V4L2_MEMORY_USERPTR) { v4l2_planes[0].m.userptr = b->m.userptr; @@ -976,14 +1303,43 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b if (b->memory == V4L2_MEMORY_DMABUF) { v4l2_planes[0].m.fd = b->m.fd; v4l2_planes[0].length = b->length; - v4l2_planes[0].data_offset = 0; } - } - vb->v4l2_buf.field = b->field; - vb->v4l2_buf.timestamp = b->timestamp; + /* Zero flags that the vb2 core handles */ vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS; + if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) != + V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) { + /* + * Non-COPY timestamps and non-OUTPUT queues will get + * their timestamp and timestamp source flags from the + * queue. + */ + vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + } + + if (V4L2_TYPE_IS_OUTPUT(b->type)) { + /* + * For output buffers mask out the timecode flag: + * this will be handled later in vb2_internal_qbuf(). + * The 'field' is valid metadata for this output buffer + * and so that needs to be copied here. + */ + vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE; + vb->v4l2_buf.field = b->field; + } else { + /* Zero any output buffer flags as this is a capture buffer */ + vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS; + } +} + +/** + * __qbuf_mmap() - handle qbuf of an MMAP buffer + */ +static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) +{ + __fill_vb2_buffer(vb, b, vb->v4l2_planes); + return call_vb_qop(vb, buf_prepare, vb); } /** @@ -997,7 +1353,9 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) unsigned int plane; int ret; int write = !V4L2_TYPE_IS_OUTPUT(q->type); + bool reacquired = vb->planes[0].mem_priv == NULL; + memset(planes, 0, sizeof(planes[0]) * vb->num_planes); /* Copy relevant information provided by the userspace */ __fill_vb2_buffer(vb, b, planes); @@ -1008,29 +1366,37 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) && vb->v4l2_planes[plane].length == planes[plane].length) continue; - dprintk(3, "qbuf: userspace address for plane %d changed, " + dprintk(3, "userspace address for plane %d changed, " "reacquiring memory\n", plane); /* Check if the provided plane buffer is large enough */ if (planes[plane].length < q->plane_sizes[plane]) { + dprintk(1, "provided buffer size %u is less than " + "setup size %u for plane %d\n", + planes[plane].length, + q->plane_sizes[plane], plane); ret = -EINVAL; goto err; } /* Release previously acquired memory if present */ - if (vb->planes[plane].mem_priv) - call_memop(q, put_userptr, vb->planes[plane].mem_priv); + if (vb->planes[plane].mem_priv) { + if (!reacquired) { + reacquired = true; + call_void_vb_qop(vb, buf_cleanup, vb); + } + call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv); + } vb->planes[plane].mem_priv = NULL; - vb->v4l2_planes[plane].m.userptr = 0; - vb->v4l2_planes[plane].length = 0; + memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); /* Acquire each plane's memory */ - mem_priv = call_memop(q, get_userptr, q->alloc_ctx[plane], + mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane], planes[plane].m.userptr, planes[plane].length, write); if (IS_ERR_OR_NULL(mem_priv)) { - dprintk(1, "qbuf: failed acquiring userspace " + dprintk(1, "failed acquiring userspace " "memory for plane %d\n", plane); ret = mem_priv ? PTR_ERR(mem_priv) : -EINVAL; goto err; @@ -1039,28 +1405,38 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) } /* - * Call driver-specific initialization on the newly acquired buffer, - * if provided. - */ - ret = call_qop(q, buf_init, vb); - if (ret) { - dprintk(1, "qbuf: buffer initialization failed\n"); - goto err; - } - - /* * Now that everything is in order, copy relevant information * provided by userspace. */ for (plane = 0; plane < vb->num_planes; ++plane) vb->v4l2_planes[plane] = planes[plane]; + if (reacquired) { + /* + * One or more planes changed, so we must call buf_init to do + * the driver-specific initialization on the newly acquired + * buffer, if provided. + */ + ret = call_vb_qop(vb, buf_init, vb); + if (ret) { + dprintk(1, "buffer initialization failed\n"); + goto err; + } + } + + ret = call_vb_qop(vb, buf_prepare, vb); + if (ret) { + dprintk(1, "buffer preparation failed\n"); + call_void_vb_qop(vb, buf_cleanup, vb); + goto err; + } + return 0; err: /* In case of errors, release planes that were already acquired */ for (plane = 0; plane < vb->num_planes; ++plane) { if (vb->planes[plane].mem_priv) - call_memop(q, put_userptr, vb->planes[plane].mem_priv); + call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv); vb->planes[plane].mem_priv = NULL; vb->v4l2_planes[plane].m.userptr = 0; vb->v4l2_planes[plane].length = 0; @@ -1070,15 +1446,6 @@ err: } /** - * __qbuf_mmap() - handle qbuf of an MMAP buffer - */ -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) -{ - __fill_vb2_buffer(vb, b, vb->v4l2_planes); - return 0; -} - -/** * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer */ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) @@ -1089,15 +1456,17 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) unsigned int plane; int ret; int write = !V4L2_TYPE_IS_OUTPUT(q->type); + bool reacquired = vb->planes[0].mem_priv == NULL; - /* Verify and copy relevant information provided by the userspace */ + memset(planes, 0, sizeof(planes[0]) * vb->num_planes); + /* Copy relevant information provided by the userspace */ __fill_vb2_buffer(vb, b, planes); for (plane = 0; plane < vb->num_planes; ++plane) { struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd); if (IS_ERR_OR_NULL(dbuf)) { - dprintk(1, "qbuf: invalid dmabuf fd for plane %d\n", + dprintk(1, "invalid dmabuf fd for plane %d\n", plane); ret = -EINVAL; goto err; @@ -1107,8 +1476,9 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) if (planes[plane].length == 0) planes[plane].length = dbuf->size; - if (planes[plane].length < planes[plane].data_offset + - q->plane_sizes[plane]) { + if (planes[plane].length < q->plane_sizes[plane]) { + dprintk(1, "invalid dmabuf length for plane %d\n", + plane); ret = -EINVAL; goto err; } @@ -1120,17 +1490,22 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) continue; } - dprintk(1, "qbuf: buffer for plane %d changed\n", plane); + dprintk(1, "buffer for plane %d changed\n", plane); + + if (!reacquired) { + reacquired = true; + call_void_vb_qop(vb, buf_cleanup, vb); + } /* Release previously acquired memory if present */ - __vb2_plane_dmabuf_put(q, &vb->planes[plane]); + __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); /* Acquire each plane's memory */ - mem_priv = call_memop(q, attach_dmabuf, q->alloc_ctx[plane], + mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane], dbuf, planes[plane].length, write); if (IS_ERR(mem_priv)) { - dprintk(1, "qbuf: failed to attach dmabuf\n"); + dprintk(1, "failed to attach dmabuf\n"); ret = PTR_ERR(mem_priv); dma_buf_put(dbuf); goto err; @@ -1145,9 +1520,9 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) * the buffer(s).. */ for (plane = 0; plane < vb->num_planes; ++plane) { - ret = call_memop(q, map_dmabuf, vb->planes[plane].mem_priv); + ret = call_memop(vb, map_dmabuf, vb->planes[plane].mem_priv); if (ret) { - dprintk(1, "qbuf: failed to map dmabuf for plane %d\n", + dprintk(1, "failed to map dmabuf for plane %d\n", plane); goto err; } @@ -1155,22 +1530,31 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) } /* - * Call driver-specific initialization on the newly acquired buffer, - * if provided. - */ - ret = call_qop(q, buf_init, vb); - if (ret) { - dprintk(1, "qbuf: buffer initialization failed\n"); - goto err; - } - - /* * Now that everything is in order, copy relevant information * provided by userspace. */ for (plane = 0; plane < vb->num_planes; ++plane) vb->v4l2_planes[plane] = planes[plane]; + if (reacquired) { + /* + * Call driver-specific initialization on the newly acquired buffer, + * if provided. + */ + ret = call_vb_qop(vb, buf_init, vb); + if (ret) { + dprintk(1, "buffer initialization failed\n"); + goto err; + } + } + + ret = call_vb_qop(vb, buf_prepare, vb); + if (ret) { + dprintk(1, "buffer preparation failed\n"); + call_void_vb_qop(vb, buf_cleanup, vb); + goto err; + } + return 0; err: /* In case of errors, release planes that were already acquired */ @@ -1188,30 +1572,70 @@ static void __enqueue_in_driver(struct vb2_buffer *vb) unsigned int plane; vb->state = VB2_BUF_STATE_ACTIVE; - atomic_inc(&q->queued_count); + atomic_inc(&q->owned_by_drv_count); /* sync buffers */ for (plane = 0; plane < vb->num_planes; ++plane) - call_memop(q, prepare, vb->planes[plane].mem_priv); + call_void_memop(vb, prepare, vb->planes[plane].mem_priv); - q->ops->buf_queue(vb); + call_void_vb_qop(vb, buf_queue, vb); } static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) { struct vb2_queue *q = vb->vb2_queue; + struct rw_semaphore *mmap_sem; int ret; ret = __verify_length(vb, b); - if (ret < 0) + if (ret < 0) { + dprintk(1, "plane parameters verification failed: %d\n", ret); return ret; + } + if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) { + /* + * If the format's field is ALTERNATE, then the buffer's field + * should be either TOP or BOTTOM, not ALTERNATE since that + * makes no sense. The driver has to know whether the + * buffer represents a top or a bottom field in order to + * program any DMA correctly. Using ALTERNATE is wrong, since + * that just says that it is either a top or a bottom field, + * but not which of the two it is. + */ + dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n"); + return -EINVAL; + } + + vb->state = VB2_BUF_STATE_PREPARING; + vb->v4l2_buf.timestamp.tv_sec = 0; + vb->v4l2_buf.timestamp.tv_usec = 0; + vb->v4l2_buf.sequence = 0; switch (q->memory) { case V4L2_MEMORY_MMAP: ret = __qbuf_mmap(vb, b); break; case V4L2_MEMORY_USERPTR: + /* + * In case of user pointer buffers vb2 allocators need to get + * direct access to userspace pages. This requires getting + * the mmap semaphore for read access in the current process + * structure. The same semaphore is taken before calling mmap + * operation, while both qbuf/prepare_buf and mmap are called + * by the driver or v4l2 core with the driver's lock held. + * To avoid an AB-BA deadlock (mmap_sem then driver's lock in + * mmap and driver's lock then mmap_sem in qbuf/prepare_buf), + * the videobuf2 core releases the driver's lock, takes + * mmap_sem and then takes the driver's lock again. + */ + mmap_sem = ¤t->mm->mmap_sem; + call_void_qop(q, wait_prepare, q); + down_read(mmap_sem); + call_void_qop(q, wait_finish, q); + ret = __qbuf_userptr(vb, b); + + up_read(mmap_sem); break; case V4L2_MEMORY_DMABUF: ret = __qbuf_dmabuf(vb, b); @@ -1221,109 +1645,38 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) ret = -EINVAL; } - if (!ret) - ret = call_qop(q, buf_prepare, vb); if (ret) - dprintk(1, "qbuf: buffer preparation failed: %d\n", ret); - else - vb->state = VB2_BUF_STATE_PREPARED; + dprintk(1, "buffer preparation failed: %d\n", ret); + vb->state = ret ? VB2_BUF_STATE_DEQUEUED : VB2_BUF_STATE_PREPARED; return ret; } static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, - const char *opname, - int (*handler)(struct vb2_queue *, - struct v4l2_buffer *, - struct vb2_buffer *)) + const char *opname) { - struct rw_semaphore *mmap_sem = NULL; - struct vb2_buffer *vb; - int ret; - - /* - * In case of user pointer buffers vb2 allocators need to get direct - * access to userspace pages. This requires getting the mmap semaphore - * for read access in the current process structure. The same semaphore - * is taken before calling mmap operation, while both qbuf/prepare_buf - * and mmap are called by the driver or v4l2 core with the driver's lock - * held. To avoid an AB-BA deadlock (mmap_sem then driver's lock in mmap - * and driver's lock then mmap_sem in qbuf/prepare_buf) the videobuf2 - * core releases the driver's lock, takes mmap_sem and then takes the - * driver's lock again. - * - * To avoid racing with other vb2 calls, which might be called after - * releasing the driver's lock, this operation is performed at the - * beginning of qbuf/prepare_buf processing. This way the queue status - * is consistent after getting the driver's lock back. - */ - if (q->memory == V4L2_MEMORY_USERPTR) { - mmap_sem = ¤t->mm->mmap_sem; - call_qop(q, wait_prepare, q); - down_read(mmap_sem); - call_qop(q, wait_finish, q); - } - - if (q->fileio) { - dprintk(1, "%s(): file io in progress\n", opname); - ret = -EBUSY; - goto unlock; - } - if (b->type != q->type) { - dprintk(1, "%s(): invalid buffer type\n", opname); - ret = -EINVAL; - goto unlock; + dprintk(1, "%s: invalid buffer type\n", opname); + return -EINVAL; } if (b->index >= q->num_buffers) { - dprintk(1, "%s(): buffer index out of range\n", opname); - ret = -EINVAL; - goto unlock; + dprintk(1, "%s: buffer index out of range\n", opname); + return -EINVAL; } - vb = q->bufs[b->index]; - if (NULL == vb) { + if (q->bufs[b->index] == NULL) { /* Should never happen */ - dprintk(1, "%s(): buffer is NULL\n", opname); - ret = -EINVAL; - goto unlock; + dprintk(1, "%s: buffer is NULL\n", opname); + return -EINVAL; } if (b->memory != q->memory) { - dprintk(1, "%s(): invalid memory type\n", opname); - ret = -EINVAL; - goto unlock; - } - - ret = __verify_planes_array(vb, b); - if (ret) - goto unlock; - - ret = handler(q, b, vb); - if (ret) - goto unlock; - - /* Fill buffer information for the userspace */ - __fill_v4l2_buffer(vb, b); - - dprintk(1, "%s() of buffer %d succeeded\n", opname, vb->v4l2_buf.index); -unlock: - if (mmap_sem) - up_read(mmap_sem); - return ret; -} - -static int __vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, - struct vb2_buffer *vb) -{ - if (vb->state != VB2_BUF_STATE_DEQUEUED) { - dprintk(1, "%s(): invalid buffer state %d\n", __func__, - vb->state); + dprintk(1, "%s: invalid memory type\n", opname); return -EINVAL; } - return __buf_prepare(vb, b); + return __verify_planes_array(q->bufs[b->index], b); } /** @@ -1343,24 +1696,108 @@ static int __vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, */ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) { - return vb2_queue_or_prepare_buf(q, b, "prepare_buf", __vb2_prepare_buf); + struct vb2_buffer *vb; + int ret; + + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + + ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf"); + if (ret) + return ret; + + vb = q->bufs[b->index]; + if (vb->state != VB2_BUF_STATE_DEQUEUED) { + dprintk(1, "invalid buffer state %d\n", + vb->state); + return -EINVAL; + } + + ret = __buf_prepare(vb, b); + if (!ret) { + /* Fill buffer information for the userspace */ + __fill_v4l2_buffer(vb, b); + + dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index); + } + return ret; } EXPORT_SYMBOL_GPL(vb2_prepare_buf); -static int __vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b, - struct vb2_buffer *vb) +/** + * vb2_start_streaming() - Attempt to start streaming. + * @q: videobuf2 queue + * + * Attempt to start streaming. When this function is called there must be + * at least q->min_buffers_needed buffers queued up (i.e. the minimum + * number of buffers required for the DMA engine to function). If the + * @start_streaming op fails it is supposed to return all the driver-owned + * buffers back to vb2 in state QUEUED. Check if that happened and if + * not warn and reclaim them forcefully. + */ +static int vb2_start_streaming(struct vb2_queue *q) { + struct vb2_buffer *vb; int ret; + /* + * If any buffers were queued before streamon, + * we can now pass them to driver for processing. + */ + list_for_each_entry(vb, &q->queued_list, queued_entry) + __enqueue_in_driver(vb); + + /* Tell the driver to start streaming */ + ret = call_qop(q, start_streaming, q, + atomic_read(&q->owned_by_drv_count)); + q->start_streaming_called = ret == 0; + if (!ret) + return 0; + + dprintk(1, "driver refused to start streaming\n"); + if (WARN_ON(atomic_read(&q->owned_by_drv_count))) { + unsigned i; + + /* + * Forcefully reclaim buffers if the driver did not + * correctly return them to vb2. + */ + for (i = 0; i < q->num_buffers; ++i) { + vb = q->bufs[i]; + if (vb->state == VB2_BUF_STATE_ACTIVE) + vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED); + } + /* Must be zero now */ + WARN_ON(atomic_read(&q->owned_by_drv_count)); + } + return ret; +} + +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) +{ + int ret = vb2_queue_or_prepare_buf(q, b, "qbuf"); + struct vb2_buffer *vb; + + if (ret) + return ret; + + vb = q->bufs[b->index]; + switch (vb->state) { case VB2_BUF_STATE_DEQUEUED: ret = __buf_prepare(vb, b); if (ret) return ret; + break; case VB2_BUF_STATE_PREPARED: break; + case VB2_BUF_STATE_PREPARING: + dprintk(1, "buffer still being prepared\n"); + return -EINVAL; default: - dprintk(1, "qbuf: buffer already in use\n"); + dprintk(1, "invalid buffer state %d\n", vb->state); return -EINVAL; } @@ -1369,15 +1806,45 @@ static int __vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b, * dequeued in dqbuf. */ list_add_tail(&vb->queued_entry, &q->queued_list); + q->queued_count++; vb->state = VB2_BUF_STATE_QUEUED; + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + /* + * For output buffers copy the timestamp if needed, + * and the timecode field and flag if needed. + */ + if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == + V4L2_BUF_FLAG_TIMESTAMP_COPY) + vb->v4l2_buf.timestamp = b->timestamp; + vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; + if (b->flags & V4L2_BUF_FLAG_TIMECODE) + vb->v4l2_buf.timecode = b->timecode; + } /* * If already streaming, give the buffer to driver for processing. * If not, the buffer will be given to driver on next streamon. */ - if (q->streaming) + if (q->start_streaming_called) __enqueue_in_driver(vb); + /* Fill buffer information for the userspace */ + __fill_v4l2_buffer(vb, b); + + /* + * If streamon has been called, and we haven't yet called + * start_streaming() since not enough buffers were queued, and + * we now have reached the minimum number of queued buffers, + * then we can finally call start_streaming(). + */ + if (q->streaming && !q->start_streaming_called && + q->queued_count >= q->min_buffers_needed) { + ret = vb2_start_streaming(q); + if (ret) + return ret; + } + + dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); return 0; } @@ -1400,7 +1867,12 @@ static int __vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b, */ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) { - return vb2_queue_or_prepare_buf(q, b, "qbuf", __vb2_qbuf); + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + + return vb2_internal_qbuf(q, b); } EXPORT_SYMBOL_GPL(vb2_qbuf); @@ -1425,7 +1897,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) int ret; if (!q->streaming) { - dprintk(1, "Streaming off, will not wait for buffers\n"); + dprintk(1, "streaming off, will not wait for buffers\n"); return -EINVAL; } @@ -1437,7 +1909,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) } if (nonblocking) { - dprintk(1, "Nonblocking and no buffers to dequeue, " + dprintk(1, "nonblocking and no buffers to dequeue, " "will not wait\n"); return -EAGAIN; } @@ -1447,12 +1919,12 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) * become ready or for streamoff. Driver's lock is released to * allow streamoff or qbuf to be called while waiting. */ - call_qop(q, wait_prepare, q); + call_void_qop(q, wait_prepare, q); /* * All locks have been released, it is safe to sleep now. */ - dprintk(3, "Will sleep waiting for buffers\n"); + dprintk(3, "will sleep waiting for buffers\n"); ret = wait_event_interruptible(q->done_wq, !list_empty(&q->done_list) || !q->streaming); @@ -1460,9 +1932,9 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) * We need to reevaluate both conditions again after reacquiring * the locks or return an error if one occurred. */ - call_qop(q, wait_finish, q); + call_void_qop(q, wait_finish, q); if (ret) { - dprintk(1, "Sleep was interrupted\n"); + dprintk(1, "sleep was interrupted\n"); return ret; } } @@ -1517,11 +1989,12 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb, int vb2_wait_for_all_buffers(struct vb2_queue *q) { if (!q->streaming) { - dprintk(1, "Streaming off, will not wait for buffers\n"); + dprintk(1, "streaming off, will not wait for buffers\n"); return -EINVAL; } - wait_event(q->done_wq, !atomic_read(&q->queued_count)); + if (q->start_streaming_called) + wait_event(q->done_wq, !atomic_read(&q->owned_by_drv_count)); return 0; } EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers); @@ -1545,72 +2018,43 @@ static void __vb2_dqbuf(struct vb2_buffer *vb) 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); + call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv); vb->planes[i].dbuf_mapped = 0; } } -/** - * vb2_dqbuf() - Dequeue a buffer to the userspace - * @q: videobuf2 queue - * @b: buffer structure passed from userspace to vidioc_dqbuf handler - * in driver - * @nonblocking: if true, this call will not sleep waiting for a buffer if no - * buffers ready for dequeuing are present. Normally the driver - * would be passing (file->f_flags & O_NONBLOCK) here - * - * Should be called from vidioc_dqbuf ioctl handler of a driver. - * This function: - * 1) verifies the passed buffer, - * 2) calls buf_finish callback in the driver (if provided), in which - * driver can perform any additional operations that may be required before - * returning the buffer to userspace, such as cache sync, - * 3) the buffer struct members are filled with relevant information for - * the userspace. - * - * The return values from this function are intended to be directly returned - * from vidioc_dqbuf handler in driver. - */ -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) { struct vb2_buffer *vb = NULL; int ret; - if (q->fileio) { - dprintk(1, "dqbuf: file io in progress\n"); - return -EBUSY; - } - if (b->type != q->type) { - dprintk(1, "dqbuf: invalid buffer type\n"); + dprintk(1, "invalid buffer type\n"); return -EINVAL; } ret = __vb2_get_done_vb(q, &vb, b, nonblocking); if (ret < 0) return ret; - ret = call_qop(q, buf_finish, vb); - if (ret) { - dprintk(1, "dqbuf: buffer finish failed\n"); - return ret; - } - switch (vb->state) { case VB2_BUF_STATE_DONE: - dprintk(3, "dqbuf: Returning done buffer\n"); + dprintk(3, "returning done buffer\n"); break; case VB2_BUF_STATE_ERROR: - dprintk(3, "dqbuf: Returning done buffer with errors\n"); + dprintk(3, "returning done buffer with errors\n"); break; default: - dprintk(1, "dqbuf: Invalid buffer state\n"); + dprintk(1, "invalid buffer state\n"); return -EINVAL; } + call_void_vb_qop(vb, buf_finish, vb); + /* Fill buffer information for the userspace */ __fill_v4l2_buffer(vb, b); /* Remove from videobuf queue */ list_del(&vb->queued_entry); + q->queued_count--; /* go back to dequeued state */ __vb2_dqbuf(vb); @@ -1619,6 +2063,36 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) return 0; } + +/** + * vb2_dqbuf() - Dequeue a buffer to the userspace + * @q: videobuf2 queue + * @b: buffer structure passed from userspace to vidioc_dqbuf handler + * in driver + * @nonblocking: if true, this call will not sleep waiting for a buffer if no + * buffers ready for dequeuing are present. Normally the driver + * would be passing (file->f_flags & O_NONBLOCK) here + * + * Should be called from vidioc_dqbuf ioctl handler of a driver. + * This function: + * 1) verifies the passed buffer, + * 2) calls buf_finish callback in the driver (if provided), in which + * driver can perform any additional operations that may be required before + * returning the buffer to userspace, such as cache sync, + * 3) the buffer struct members are filled with relevant information for + * the userspace. + * + * The return values from this function are intended to be directly returned + * from vidioc_dqbuf handler in driver. + */ +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) +{ + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + return vb2_internal_dqbuf(q, b, nonblocking); +} EXPORT_SYMBOL_GPL(vb2_dqbuf); /** @@ -1635,9 +2109,20 @@ static void __vb2_queue_cancel(struct vb2_queue *q) * Tell driver to stop all transactions and release all queued * buffers. */ - if (q->streaming) - call_qop(q, stop_streaming, q); + if (q->start_streaming_called) + call_void_qop(q, stop_streaming, q); + + if (WARN_ON(atomic_read(&q->owned_by_drv_count))) { + for (i = 0; i < q->num_buffers; ++i) + if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) + vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR); + /* Must be zero now */ + WARN_ON(atomic_read(&q->owned_by_drv_count)); + } + q->streaming = 0; + q->start_streaming_called = 0; + q->queued_count = 0; /* * Remove all buffers from videobuf's list... @@ -1648,14 +2133,70 @@ static void __vb2_queue_cancel(struct vb2_queue *q) * has not already dequeued before initiating cancel. */ INIT_LIST_HEAD(&q->done_list); - atomic_set(&q->queued_count, 0); + atomic_set(&q->owned_by_drv_count, 0); wake_up_all(&q->done_wq); /* * 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) { + struct vb2_buffer *vb = q->bufs[i]; + + if (vb->state != VB2_BUF_STATE_DEQUEUED) { + vb->state = VB2_BUF_STATE_PREPARED; + call_void_vb_qop(vb, buf_finish, vb); + } + __vb2_dqbuf(vb); + } +} + +static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type) +{ + int ret; + + if (type != q->type) { + dprintk(1, "invalid stream type\n"); + return -EINVAL; + } + + if (q->streaming) { + dprintk(3, "already streaming\n"); + return 0; + } + + if (!q->num_buffers) { + dprintk(1, "no buffers have been allocated\n"); + return -EINVAL; + } + + if (q->num_buffers < q->min_buffers_needed) { + dprintk(1, "need at least %u allocated buffers\n", + q->min_buffers_needed); + return -EINVAL; + } + + /* + * Tell driver to start streaming provided sufficient buffers + * are available. */ - for (i = 0; i < q->num_buffers; ++i) - __vb2_dqbuf(q->bufs[i]); + if (q->queued_count >= q->min_buffers_needed) { + ret = vb2_start_streaming(q); + if (ret) { + __vb2_queue_cancel(q); + return ret; + } + } + + q->streaming = 1; + + dprintk(3, "successful\n"); + return 0; } /** @@ -1673,48 +2214,35 @@ static void __vb2_queue_cancel(struct vb2_queue *q) */ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) { - struct vb2_buffer *vb; - int ret; - - if (q->fileio) { - dprintk(1, "streamon: file io in progress\n"); + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); return -EBUSY; } + return vb2_internal_streamon(q, type); +} +EXPORT_SYMBOL_GPL(vb2_streamon); +static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) +{ if (type != q->type) { - dprintk(1, "streamon: invalid stream type\n"); + dprintk(1, "invalid stream type\n"); return -EINVAL; } - if (q->streaming) { - dprintk(1, "streamon: already streaming\n"); - return -EBUSY; - } - - /* - * If any buffers were queued before streamon, - * we can now pass them to driver for processing. - */ - list_for_each_entry(vb, &q->queued_list, queued_entry) - __enqueue_in_driver(vb); - /* - * Let driver notice that streaming state has been enabled. + * Cancel will pause streaming and remove all buffers from the driver + * and videobuf, effectively returning control over them to userspace. + * + * Note that we do this even if q->streaming == 0: if you prepare or + * queue buffers, and then call streamoff without ever having called + * streamon, you would still expect those buffers to be returned to + * their normal dequeued state. */ - ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count)); - if (ret) { - dprintk(1, "streamon: driver refused to start streaming\n"); - __vb2_queue_cancel(q); - return ret; - } - - q->streaming = 1; + __vb2_queue_cancel(q); - dprintk(3, "Streamon successful\n"); + dprintk(3, "successful\n"); return 0; } -EXPORT_SYMBOL_GPL(vb2_streamon); - /** * vb2_streamoff - stop streaming @@ -1733,29 +2261,11 @@ EXPORT_SYMBOL_GPL(vb2_streamon); */ int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) { - if (q->fileio) { - dprintk(1, "streamoff: file io in progress\n"); + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); return -EBUSY; } - - if (type != q->type) { - dprintk(1, "streamoff: invalid stream type\n"); - return -EINVAL; - } - - if (!q->streaming) { - dprintk(1, "streamoff: not streaming\n"); - return -EINVAL; - } - - /* - * Cancel will pause streaming and remove all buffers from the driver - * and videobuf, effectively returning control over them to userspace. - */ - __vb2_queue_cancel(q); - - dprintk(3, "Streamoff successful\n"); - return 0; + return vb2_internal_streamoff(q, type); } EXPORT_SYMBOL_GPL(vb2_streamoff); @@ -1805,22 +2315,22 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) struct dma_buf *dbuf; if (q->memory != V4L2_MEMORY_MMAP) { - dprintk(1, "Queue is not currently set up for mmap\n"); + dprintk(1, "queue is not currently set up for mmap\n"); return -EINVAL; } if (!q->mem_ops->get_dmabuf) { - dprintk(1, "Queue does not support DMA buffer exporting\n"); + dprintk(1, "queue does not support DMA buffer exporting\n"); return -EINVAL; } - if (eb->flags & ~O_CLOEXEC) { - dprintk(1, "Queue does support only O_CLOEXEC flag\n"); + if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) { + dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n"); return -EINVAL; } if (eb->type != q->type) { - dprintk(1, "qbuf: invalid buffer type\n"); + dprintk(1, "invalid buffer type\n"); return -EINVAL; } @@ -1836,16 +2346,21 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) return -EINVAL; } + if (vb2_fileio_is_active(q)) { + dprintk(1, "expbuf: file io in progress\n"); + return -EBUSY; + } + vb_plane = &vb->planes[eb->plane]; - dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv); + dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE); if (IS_ERR_OR_NULL(dbuf)) { - dprintk(1, "Failed to export buffer %d, plane %d\n", + dprintk(1, "failed to export buffer %d, plane %d\n", eb->index, eb->plane); return -EINVAL; } - ret = dma_buf_fd(dbuf, eb->flags); + ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE); if (ret < 0) { dprintk(3, "buffer %d, plane %d failed to export (%d)\n", eb->index, eb->plane, ret); @@ -1884,12 +2399,12 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) { unsigned long off = vma->vm_pgoff << PAGE_SHIFT; struct vb2_buffer *vb; - unsigned int buffer, plane; + unsigned int buffer = 0, plane = 0; int ret; unsigned long length; if (q->memory != V4L2_MEMORY_MMAP) { - dprintk(1, "Queue is not currently set up for mmap\n"); + dprintk(1, "queue is not currently set up for mmap\n"); return -EINVAL; } @@ -1897,20 +2412,24 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) * Check memory area access mode. */ if (!(vma->vm_flags & VM_SHARED)) { - dprintk(1, "Invalid vma flags, VM_SHARED needed\n"); + dprintk(1, "invalid vma flags, VM_SHARED needed\n"); return -EINVAL; } if (V4L2_TYPE_IS_OUTPUT(q->type)) { if (!(vma->vm_flags & VM_WRITE)) { - dprintk(1, "Invalid vma flags, VM_WRITE needed\n"); + dprintk(1, "invalid vma flags, VM_WRITE needed\n"); return -EINVAL; } } else { if (!(vma->vm_flags & VM_READ)) { - dprintk(1, "Invalid vma flags, VM_READ needed\n"); + dprintk(1, "invalid vma flags, VM_READ needed\n"); return -EINVAL; } } + if (vb2_fileio_is_active(q)) { + dprintk(1, "mmap: file io in progress\n"); + return -EBUSY; + } /* * Find the plane corresponding to the offset passed by userspace. @@ -1933,11 +2452,11 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) return -EINVAL; } - ret = call_memop(q, mmap, vb->planes[plane].mem_priv, vma); + ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma); if (ret) return ret; - dprintk(3, "Buffer %d, plane %d successfully mapped\n", buffer, plane); + dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane); return 0; } EXPORT_SYMBOL_GPL(vb2_mmap); @@ -1955,7 +2474,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q, int ret; if (q->memory != V4L2_MEMORY_MMAP) { - dprintk(1, "Queue is not currently set up for mmap\n"); + dprintk(1, "queue is not currently set up for mmap\n"); return -EINVAL; } @@ -2020,7 +2539,7 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) /* * Start file I/O emulator only if streaming API has not been used yet. */ - if (q->num_buffers == 0 && q->fileio == NULL) { + if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) { if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && (req_events & (POLLIN | POLLRDNORM))) { if (__vb2_init_fileio(q, 1)) @@ -2088,11 +2607,14 @@ int vb2_queue_init(struct vb2_queue *q) WARN_ON(!q->io_modes) || WARN_ON(!q->ops->queue_setup) || WARN_ON(!q->ops->buf_queue) || - WARN_ON(q->timestamp_type & ~V4L2_BUF_FLAG_TIMESTAMP_MASK)) + WARN_ON(q->timestamp_flags & + ~(V4L2_BUF_FLAG_TIMESTAMP_MASK | + V4L2_BUF_FLAG_TSTAMP_SRC_MASK))) return -EINVAL; /* Warn that the driver should choose an appropriate timestamp type */ - WARN_ON(q->timestamp_type == V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN); + WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == + V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN); INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->done_list); @@ -2139,6 +2661,22 @@ struct vb2_fileio_buf { /** * struct vb2_fileio_data - queue context used by file io emulator * + * @cur_index: the index of the buffer currently being read from or + * written to. If equal to q->num_buffers then a new buffer + * must be dequeued. + * @initial_index: in the read() case all buffers are queued up immediately + * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles + * buffers. However, in the write() case no buffers are initially + * queued, instead whenever a buffer is full it is queued up by + * __vb2_perform_fileio(). Only once all available buffers have + * been queued up will __vb2_perform_fileio() start to dequeue + * buffers. This means that initially __vb2_perform_fileio() + * needs to know what buffer index to use when it is queuing up + * the buffers for the first time. That initial index is stored + * in this field. Once it is equal to q->num_buffers all + * available buffers have been queued and __vb2_perform_fileio() + * should start the normal dequeue/queue cycle. + * * vb2 provides a compatibility layer and emulator of file io (read and * write) calls on top of streaming API. For proper operation it required * this structure to save the driver state between each call of the read @@ -2146,9 +2684,11 @@ struct vb2_fileio_buf { */ struct vb2_fileio_data { struct v4l2_requestbuffers req; + struct v4l2_plane p; struct v4l2_buffer b; struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME]; - unsigned int index; + unsigned int cur_index; + unsigned int initial_index; unsigned int q_count; unsigned int dq_count; unsigned int flags; @@ -2168,9 +2708,9 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) /* * Sanity check */ - if ((read && !(q->io_modes & VB2_READ)) || - (!read && !(q->io_modes & VB2_WRITE))) - BUG(); + if (WARN_ON((read && !(q->io_modes & VB2_READ)) || + (!read && !(q->io_modes & VB2_WRITE)))) + return -EINVAL; /* * Check if device supports mapping buffers to kernel virtual space. @@ -2205,7 +2745,8 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) fileio->req.count = count; fileio->req.memory = V4L2_MEMORY_MMAP; fileio->req.type = q->type; - ret = vb2_reqbufs(q, &fileio->req); + q->fileio = fileio; + ret = __reqbufs(q, &fileio->req); if (ret) goto err_kfree; @@ -2234,38 +2775,51 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) * Read mode requires pre queuing of all buffers. */ if (read) { + bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type); + /* * Queue all buffers. */ for (i = 0; i < q->num_buffers; i++) { struct v4l2_buffer *b = &fileio->b; + memset(b, 0, sizeof(*b)); b->type = q->type; + if (is_multiplanar) { + memset(&fileio->p, 0, sizeof(fileio->p)); + b->m.planes = &fileio->p; + b->length = 1; + } b->memory = q->memory; b->index = i; - ret = vb2_qbuf(q, b); + ret = vb2_internal_qbuf(q, b); if (ret) goto err_reqbufs; fileio->bufs[i].queued = 1; } - /* - * Start streaming. + * All buffers have been queued, so mark that by setting + * initial_index to q->num_buffers */ - ret = vb2_streamon(q, q->type); - if (ret) - goto err_reqbufs; + fileio->initial_index = q->num_buffers; + fileio->cur_index = q->num_buffers; } - q->fileio = fileio; + /* + * Start streaming. + */ + ret = vb2_internal_streamon(q, q->type); + if (ret) + goto err_reqbufs; return ret; err_reqbufs: fileio->req.count = 0; - vb2_reqbufs(q, &fileio->req); + __reqbufs(q, &fileio->req); err_kfree: + q->fileio = NULL; kfree(fileio); return ret; } @@ -2279,13 +2833,8 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q) struct vb2_fileio_data *fileio = q->fileio; if (fileio) { - /* - * Hack fileio context to enable direct calls to vb2 ioctl - * interface. - */ + vb2_internal_streamoff(q, q->type); q->fileio = NULL; - - vb2_streamoff(q, q->type); fileio->req.count = 0; vb2_reqbufs(q, &fileio->req); kfree(fileio); @@ -2308,9 +2857,18 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ { struct vb2_fileio_data *fileio; struct vb2_fileio_buf *buf; + bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type); + /* + * When using write() to write data to an output video node the vb2 core + * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody + * else is able to provide this information with the write() operation. + */ + bool set_timestamp = !read && + (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == + V4L2_BUF_FLAG_TIMESTAMP_COPY; int ret, index; - dprintk(3, "file io: mode %s, offset %ld, count %zd, %sblocking\n", + dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n", read ? "read" : "write", (long)*ppos, count, nonblock ? "non" : ""); @@ -2320,48 +2878,48 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ /* * Initialize emulator on first call. */ - if (!q->fileio) { + if (!vb2_fileio_is_active(q)) { ret = __vb2_init_fileio(q, read); - dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); + dprintk(3, "vb2_init_fileio result: %d\n", ret); if (ret) return ret; } fileio = q->fileio; /* - * Hack fileio context to enable direct calls to vb2 ioctl interface. - * The pointer will be restored before returning from this function. - */ - q->fileio = NULL; - - index = fileio->index; - buf = &fileio->bufs[index]; - - /* * Check if we need to dequeue the buffer. */ - if (buf->queued) { - struct vb2_buffer *vb; - + index = fileio->cur_index; + if (index >= q->num_buffers) { /* * Call vb2_dqbuf to get buffer back. */ memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; - fileio->b.index = index; - ret = vb2_dqbuf(q, &fileio->b, nonblock); - dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); + if (is_multiplanar) { + memset(&fileio->p, 0, sizeof(fileio->p)); + fileio->b.m.planes = &fileio->p; + fileio->b.length = 1; + } + ret = vb2_internal_dqbuf(q, &fileio->b, nonblock); + dprintk(5, "vb2_dqbuf result: %d\n", ret); if (ret) - goto end; + return ret; fileio->dq_count += 1; + fileio->cur_index = index = fileio->b.index; + buf = &fileio->bufs[index]; + /* * Get number of bytes filled by the driver */ - vb = q->bufs[index]; - buf->size = vb2_get_plane_payload(vb, 0); + buf->pos = 0; buf->queued = 0; + buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0) + : vb2_plane_size(q->bufs[index], 0); + } else { + buf = &fileio->bufs[index]; } /* @@ -2375,16 +2933,15 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ /* * Transfer data to userspace. */ - dprintk(3, "file io: copying %zd bytes - buffer %d, offset %u\n", + dprintk(3, "copying %zd bytes - buffer %d, offset %u\n", count, index, buf->pos); if (read) ret = copy_to_user(data, buf->vaddr + buf->pos, count); else ret = copy_from_user(buf->vaddr + buf->pos, data, count); if (ret) { - dprintk(3, "file io: error copying data\n"); - ret = -EFAULT; - goto end; + dprintk(3, "error copying data\n"); + return -EFAULT; } /* @@ -2403,11 +2960,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ */ if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) && fileio->dq_count == 1) { - dprintk(3, "file io: read limit reached\n"); - /* - * Restore fileio pointer and release the context. - */ - q->fileio = fileio; + dprintk(3, "read limit reached\n"); return __vb2_cleanup_fileio(q); } @@ -2419,32 +2972,40 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ fileio->b.memory = q->memory; fileio->b.index = index; fileio->b.bytesused = buf->pos; - ret = vb2_qbuf(q, &fileio->b); - dprintk(5, "file io: vb2_dbuf result: %d\n", ret); + if (is_multiplanar) { + memset(&fileio->p, 0, sizeof(fileio->p)); + fileio->p.bytesused = buf->pos; + fileio->b.m.planes = &fileio->p; + fileio->b.length = 1; + } + if (set_timestamp) + v4l2_get_timestamp(&fileio->b.timestamp); + ret = vb2_internal_qbuf(q, &fileio->b); + dprintk(5, "vb2_dbuf result: %d\n", ret); if (ret) - goto end; + return ret; /* * Buffer has been queued, update the status */ buf->pos = 0; buf->queued = 1; - buf->size = q->bufs[0]->v4l2_planes[0].length; + buf->size = vb2_plane_size(q->bufs[index], 0); fileio->q_count += 1; - /* - * Switch to the next buffer + * If we are queuing up buffers for the first time, then + * increase initial_index by one. */ - fileio->index = (index + 1) % q->num_buffers; - + if (fileio->initial_index < q->num_buffers) + fileio->initial_index++; /* - * Start streaming if required. + * The next buffer to use is either a buffer that's going to be + * queued for the first time (initial_index < q->num_buffers) + * or it is equal to q->num_buffers, meaning that the next + * time we need to dequeue a buffer since we've now queued up + * all the 'first time' buffers. */ - if (!read && !q->streaming) { - ret = vb2_streamon(q, q->type); - if (ret) - goto end; - } + fileio->cur_index = fileio->initial_index; } /* @@ -2452,11 +3013,6 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ */ if (ret == 0) ret = count; -end: - /* - * Restore the fileio context and block vb2 ioctl interface. - */ - q->fileio = fileio; return ret; } @@ -2467,13 +3023,155 @@ size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, } EXPORT_SYMBOL_GPL(vb2_read); -size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count, +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count, loff_t *ppos, int nonblocking) { - return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 0); + return __vb2_perform_fileio(q, (char __user *) data, count, + ppos, nonblocking, 0); } EXPORT_SYMBOL_GPL(vb2_write); +struct vb2_threadio_data { + struct task_struct *thread; + vb2_thread_fnc fnc; + void *priv; + bool stop; +}; + +static int vb2_thread(void *data) +{ + struct vb2_queue *q = data; + struct vb2_threadio_data *threadio = q->threadio; + struct vb2_fileio_data *fileio = q->fileio; + bool set_timestamp = false; + int prequeue = 0; + int index = 0; + int ret = 0; + + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + prequeue = q->num_buffers; + set_timestamp = + (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == + V4L2_BUF_FLAG_TIMESTAMP_COPY; + } + + set_freezable(); + + for (;;) { + struct vb2_buffer *vb; + + /* + * Call vb2_dqbuf to get buffer back. + */ + memset(&fileio->b, 0, sizeof(fileio->b)); + fileio->b.type = q->type; + fileio->b.memory = q->memory; + if (prequeue) { + fileio->b.index = index++; + prequeue--; + } else { + call_void_qop(q, wait_finish, q); + ret = vb2_internal_dqbuf(q, &fileio->b, 0); + call_void_qop(q, wait_prepare, q); + dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); + } + if (threadio->stop) + break; + if (ret) + break; + try_to_freeze(); + + vb = q->bufs[fileio->b.index]; + if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR)) + ret = threadio->fnc(vb, threadio->priv); + if (ret) + break; + call_void_qop(q, wait_finish, q); + if (set_timestamp) + v4l2_get_timestamp(&fileio->b.timestamp); + ret = vb2_internal_qbuf(q, &fileio->b); + call_void_qop(q, wait_prepare, q); + if (ret) + break; + } + + /* Hmm, linux becomes *very* unhappy without this ... */ + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + return 0; +} + +/* + * This function should not be used for anything else but the videobuf2-dvb + * support. If you think you have another good use-case for this, then please + * contact the linux-media mailinglist first. + */ +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv, + const char *thread_name) +{ + struct vb2_threadio_data *threadio; + int ret = 0; + + if (q->threadio) + return -EBUSY; + if (vb2_is_busy(q)) + return -EBUSY; + if (WARN_ON(q->fileio)) + return -EBUSY; + + threadio = kzalloc(sizeof(*threadio), GFP_KERNEL); + if (threadio == NULL) + return -ENOMEM; + threadio->fnc = fnc; + threadio->priv = priv; + + ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type)); + dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); + if (ret) + goto nomem; + q->threadio = threadio; + threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name); + if (IS_ERR(threadio->thread)) { + ret = PTR_ERR(threadio->thread); + threadio->thread = NULL; + goto nothread; + } + return 0; + +nothread: + __vb2_cleanup_fileio(q); +nomem: + kfree(threadio); + return ret; +} +EXPORT_SYMBOL_GPL(vb2_thread_start); + +int vb2_thread_stop(struct vb2_queue *q) +{ + struct vb2_threadio_data *threadio = q->threadio; + struct vb2_fileio_data *fileio = q->fileio; + int err; + + if (threadio == NULL) + return 0; + call_void_qop(q, wait_finish, q); + threadio->stop = true; + vb2_internal_streamoff(q, q->type); + call_void_qop(q, wait_prepare, q); + q->fileio = NULL; + fileio->req.count = 0; + vb2_reqbufs(q, &fileio->req); + kfree(fileio); + err = kthread_stop(threadio->thread); + threadio->thread = NULL; + kfree(threadio); + q->fileio = NULL; + q->threadio = NULL; + return err; +} +EXPORT_SYMBOL_GPL(vb2_thread_stop); /* * The following functions are not part of the vb2 core API, but are helper @@ -2619,19 +3317,32 @@ int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) } EXPORT_SYMBOL_GPL(vb2_fop_mmap); -int vb2_fop_release(struct file *file) +int _vb2_fop_release(struct file *file, struct mutex *lock) { struct video_device *vdev = video_devdata(file); if (file->private_data == vdev->queue->owner) { + if (lock) + mutex_lock(lock); vb2_queue_release(vdev->queue); vdev->queue->owner = NULL; + if (lock) + mutex_unlock(lock); } return v4l2_fh_release(file); } +EXPORT_SYMBOL_GPL(_vb2_fop_release); + +int vb2_fop_release(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + + return _vb2_fop_release(file, lock); +} EXPORT_SYMBOL_GPL(vb2_fop_release); -ssize_t vb2_fop_write(struct file *file, char __user *buf, +ssize_t vb2_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct video_device *vdev = video_devdata(file); @@ -2687,7 +3398,7 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait) /* Try to be smart: only lock if polling might start fileio, otherwise locking will only introduce unwanted delays. */ - if (q->num_buffers == 0 && q->fileio == NULL) { + if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) { if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && (req_events & (POLLIN | POLLRDNORM))) must_lock = true; |
