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;  | 
