17952be9bSHans Verkuil /*
27952be9bSHans Verkuil  * videobuf2-core.c - video buffer 2 core framework
37952be9bSHans Verkuil  *
47952be9bSHans Verkuil  * Copyright (C) 2010 Samsung Electronics
57952be9bSHans Verkuil  *
67952be9bSHans Verkuil  * Author: Pawel Osciak <pawel@osciak.com>
77952be9bSHans Verkuil  *	   Marek Szyprowski <m.szyprowski@samsung.com>
87952be9bSHans Verkuil  *
97952be9bSHans Verkuil  * The vb2_thread implementation was based on code from videobuf-dvb.c:
107952be9bSHans Verkuil  *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
117952be9bSHans Verkuil  *
127952be9bSHans Verkuil  * This program is free software; you can redistribute it and/or modify
137952be9bSHans Verkuil  * it under the terms of the GNU General Public License as published by
147952be9bSHans Verkuil  * the Free Software Foundation.
157952be9bSHans Verkuil  */
167952be9bSHans Verkuil 
177952be9bSHans Verkuil #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
187952be9bSHans Verkuil 
197952be9bSHans Verkuil #include <linux/err.h>
207952be9bSHans Verkuil #include <linux/kernel.h>
217952be9bSHans Verkuil #include <linux/module.h>
227952be9bSHans Verkuil #include <linux/mm.h>
237952be9bSHans Verkuil #include <linux/poll.h>
247952be9bSHans Verkuil #include <linux/slab.h>
257952be9bSHans Verkuil #include <linux/sched.h>
267952be9bSHans Verkuil #include <linux/freezer.h>
277952be9bSHans Verkuil #include <linux/kthread.h>
287952be9bSHans Verkuil 
297952be9bSHans Verkuil #include <media/videobuf2-core.h>
307952be9bSHans Verkuil #include <media/v4l2-mc.h>
317952be9bSHans Verkuil 
327952be9bSHans Verkuil #include <trace/events/vb2.h>
337952be9bSHans Verkuil 
347952be9bSHans Verkuil static int debug;
357952be9bSHans Verkuil module_param(debug, int, 0644);
367952be9bSHans Verkuil 
37b820935bSLaurent Pinchart #define dprintk(q, level, fmt, arg...)					\
387952be9bSHans Verkuil 	do {								\
397952be9bSHans Verkuil 		if (debug >= level)					\
40b820935bSLaurent Pinchart 			pr_info("[%s] %s: " fmt, (q)->name, __func__,	\
41b820935bSLaurent Pinchart 				## arg);				\
427952be9bSHans Verkuil 	} while (0)
437952be9bSHans Verkuil 
447952be9bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
457952be9bSHans Verkuil 
467952be9bSHans Verkuil /*
477952be9bSHans Verkuil  * If advanced debugging is on, then count how often each op is called
487952be9bSHans Verkuil  * successfully, which can either be per-buffer or per-queue.
497952be9bSHans Verkuil  *
507952be9bSHans Verkuil  * This makes it easy to check that the 'init' and 'cleanup'
517952be9bSHans Verkuil  * (and variations thereof) stay balanced.
527952be9bSHans Verkuil  */
537952be9bSHans Verkuil 
547952be9bSHans Verkuil #define log_memop(vb, op)						\
55b820935bSLaurent Pinchart 	dprintk((vb)->vb2_queue, 2, "call_memop(%d, %s)%s\n",		\
56b820935bSLaurent Pinchart 		(vb)->index, #op,					\
577952be9bSHans Verkuil 		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
587952be9bSHans Verkuil 
597952be9bSHans Verkuil #define call_memop(vb, op, args...)					\
607952be9bSHans Verkuil ({									\
617952be9bSHans Verkuil 	struct vb2_queue *_q = (vb)->vb2_queue;				\
627952be9bSHans Verkuil 	int err;							\
637952be9bSHans Verkuil 									\
647952be9bSHans Verkuil 	log_memop(vb, op);						\
657952be9bSHans Verkuil 	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
667952be9bSHans Verkuil 	if (!err)							\
677952be9bSHans Verkuil 		(vb)->cnt_mem_ ## op++;					\
687952be9bSHans Verkuil 	err;								\
697952be9bSHans Verkuil })
707952be9bSHans Verkuil 
71a4b83debSSergey Senozhatsky #define call_ptr_memop(op, vb, args...)					\
727952be9bSHans Verkuil ({									\
737952be9bSHans Verkuil 	struct vb2_queue *_q = (vb)->vb2_queue;				\
747952be9bSHans Verkuil 	void *ptr;							\
757952be9bSHans Verkuil 									\
767952be9bSHans Verkuil 	log_memop(vb, op);						\
77a4b83debSSergey Senozhatsky 	ptr = _q->mem_ops->op ? _q->mem_ops->op(vb, args) : NULL;	\
787952be9bSHans Verkuil 	if (!IS_ERR_OR_NULL(ptr))					\
797952be9bSHans Verkuil 		(vb)->cnt_mem_ ## op++;					\
807952be9bSHans Verkuil 	ptr;								\
817952be9bSHans Verkuil })
827952be9bSHans Verkuil 
837952be9bSHans Verkuil #define call_void_memop(vb, op, args...)				\
847952be9bSHans Verkuil ({									\
857952be9bSHans Verkuil 	struct vb2_queue *_q = (vb)->vb2_queue;				\
867952be9bSHans Verkuil 									\
877952be9bSHans Verkuil 	log_memop(vb, op);						\
887952be9bSHans Verkuil 	if (_q->mem_ops->op)						\
897952be9bSHans Verkuil 		_q->mem_ops->op(args);					\
907952be9bSHans Verkuil 	(vb)->cnt_mem_ ## op++;						\
917952be9bSHans Verkuil })
927952be9bSHans Verkuil 
937952be9bSHans Verkuil #define log_qop(q, op)							\
94b820935bSLaurent Pinchart 	dprintk(q, 2, "call_qop(%s)%s\n", #op,				\
957952be9bSHans Verkuil 		(q)->ops->op ? "" : " (nop)")
967952be9bSHans Verkuil 
977952be9bSHans Verkuil #define call_qop(q, op, args...)					\
987952be9bSHans Verkuil ({									\
997952be9bSHans Verkuil 	int err;							\
1007952be9bSHans Verkuil 									\
1017952be9bSHans Verkuil 	log_qop(q, op);							\
1027952be9bSHans Verkuil 	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
1037952be9bSHans Verkuil 	if (!err)							\
1047952be9bSHans Verkuil 		(q)->cnt_ ## op++;					\
1057952be9bSHans Verkuil 	err;								\
1067952be9bSHans Verkuil })
1077952be9bSHans Verkuil 
1087952be9bSHans Verkuil #define call_void_qop(q, op, args...)					\
1097952be9bSHans Verkuil ({									\
1107952be9bSHans Verkuil 	log_qop(q, op);							\
1117952be9bSHans Verkuil 	if ((q)->ops->op)						\
1127952be9bSHans Verkuil 		(q)->ops->op(args);					\
1137952be9bSHans Verkuil 	(q)->cnt_ ## op++;						\
1147952be9bSHans Verkuil })
1157952be9bSHans Verkuil 
1167952be9bSHans Verkuil #define log_vb_qop(vb, op, args...)					\
117b820935bSLaurent Pinchart 	dprintk((vb)->vb2_queue, 2, "call_vb_qop(%d, %s)%s\n",		\
118b820935bSLaurent Pinchart 		(vb)->index, #op,					\
1197952be9bSHans Verkuil 		(vb)->vb2_queue->ops->op ? "" : " (nop)")
1207952be9bSHans Verkuil 
1217952be9bSHans Verkuil #define call_vb_qop(vb, op, args...)					\
1227952be9bSHans Verkuil ({									\
1237952be9bSHans Verkuil 	int err;							\
1247952be9bSHans Verkuil 									\
1257952be9bSHans Verkuil 	log_vb_qop(vb, op);						\
1267952be9bSHans Verkuil 	err = (vb)->vb2_queue->ops->op ?				\
1277952be9bSHans Verkuil 		(vb)->vb2_queue->ops->op(args) : 0;			\
1287952be9bSHans Verkuil 	if (!err)							\
1297952be9bSHans Verkuil 		(vb)->cnt_ ## op++;					\
1307952be9bSHans Verkuil 	err;								\
1317952be9bSHans Verkuil })
1327952be9bSHans Verkuil 
1337952be9bSHans Verkuil #define call_void_vb_qop(vb, op, args...)				\
1347952be9bSHans Verkuil ({									\
1357952be9bSHans Verkuil 	log_vb_qop(vb, op);						\
1367952be9bSHans Verkuil 	if ((vb)->vb2_queue->ops->op)					\
1377952be9bSHans Verkuil 		(vb)->vb2_queue->ops->op(args);				\
1387952be9bSHans Verkuil 	(vb)->cnt_ ## op++;						\
1397952be9bSHans Verkuil })
1407952be9bSHans Verkuil 
1417952be9bSHans Verkuil #else
1427952be9bSHans Verkuil 
1437952be9bSHans Verkuil #define call_memop(vb, op, args...)					\
1447952be9bSHans Verkuil 	((vb)->vb2_queue->mem_ops->op ?					\
1457952be9bSHans Verkuil 		(vb)->vb2_queue->mem_ops->op(args) : 0)
1467952be9bSHans Verkuil 
147a4b83debSSergey Senozhatsky #define call_ptr_memop(op, vb, args...)					\
1487952be9bSHans Verkuil 	((vb)->vb2_queue->mem_ops->op ?					\
149a4b83debSSergey Senozhatsky 		(vb)->vb2_queue->mem_ops->op(vb, args) : NULL)
1507952be9bSHans Verkuil 
1517952be9bSHans Verkuil #define call_void_memop(vb, op, args...)				\
1527952be9bSHans Verkuil 	do {								\
1537952be9bSHans Verkuil 		if ((vb)->vb2_queue->mem_ops->op)			\
1547952be9bSHans Verkuil 			(vb)->vb2_queue->mem_ops->op(args);		\
1557952be9bSHans Verkuil 	} while (0)
1567952be9bSHans Verkuil 
1577952be9bSHans Verkuil #define call_qop(q, op, args...)					\
1587952be9bSHans Verkuil 	((q)->ops->op ? (q)->ops->op(args) : 0)
1597952be9bSHans Verkuil 
1607952be9bSHans Verkuil #define call_void_qop(q, op, args...)					\
1617952be9bSHans Verkuil 	do {								\
1627952be9bSHans Verkuil 		if ((q)->ops->op)					\
1637952be9bSHans Verkuil 			(q)->ops->op(args);				\
1647952be9bSHans Verkuil 	} while (0)
1657952be9bSHans Verkuil 
1667952be9bSHans Verkuil #define call_vb_qop(vb, op, args...)					\
1677952be9bSHans Verkuil 	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
1687952be9bSHans Verkuil 
1697952be9bSHans Verkuil #define call_void_vb_qop(vb, op, args...)				\
1707952be9bSHans Verkuil 	do {								\
1717952be9bSHans Verkuil 		if ((vb)->vb2_queue->ops->op)				\
1727952be9bSHans Verkuil 			(vb)->vb2_queue->ops->op(args);			\
1737952be9bSHans Verkuil 	} while (0)
1747952be9bSHans Verkuil 
1757952be9bSHans Verkuil #endif
1767952be9bSHans Verkuil 
1777952be9bSHans Verkuil #define call_bufop(q, op, args...)					\
1787952be9bSHans Verkuil ({									\
1797952be9bSHans Verkuil 	int ret = 0;							\
1807952be9bSHans Verkuil 	if (q && q->buf_ops && q->buf_ops->op)				\
1817952be9bSHans Verkuil 		ret = q->buf_ops->op(args);				\
1827952be9bSHans Verkuil 	ret;								\
1837952be9bSHans Verkuil })
1847952be9bSHans Verkuil 
1857952be9bSHans Verkuil #define call_void_bufop(q, op, args...)					\
1867952be9bSHans Verkuil ({									\
1877952be9bSHans Verkuil 	if (q && q->buf_ops && q->buf_ops->op)				\
1887952be9bSHans Verkuil 		q->buf_ops->op(args);					\
1897952be9bSHans Verkuil })
1907952be9bSHans Verkuil 
1917952be9bSHans Verkuil static void __vb2_queue_cancel(struct vb2_queue *q);
1927952be9bSHans Verkuil static void __enqueue_in_driver(struct vb2_buffer *vb);
1937952be9bSHans Verkuil 
vb2_state_name(enum vb2_buffer_state s)194c89ee8edSEzequiel Garcia static const char *vb2_state_name(enum vb2_buffer_state s)
195c89ee8edSEzequiel Garcia {
196c89ee8edSEzequiel Garcia 	static const char * const state_names[] = {
197c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_DEQUEUED] = "dequeued",
198c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_IN_REQUEST] = "in request",
199c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_PREPARING] = "preparing",
200c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_QUEUED] = "queued",
201c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_ACTIVE] = "active",
202c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_DONE] = "done",
203c89ee8edSEzequiel Garcia 		[VB2_BUF_STATE_ERROR] = "error",
204c89ee8edSEzequiel Garcia 	};
205c89ee8edSEzequiel Garcia 
206c89ee8edSEzequiel Garcia 	if ((unsigned int)(s) < ARRAY_SIZE(state_names))
207c89ee8edSEzequiel Garcia 		return state_names[s];
208c89ee8edSEzequiel Garcia 	return "unknown";
209c89ee8edSEzequiel Garcia }
210c89ee8edSEzequiel Garcia 
2117952be9bSHans Verkuil /*
2127952be9bSHans Verkuil  * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
2137952be9bSHans Verkuil  */
__vb2_buf_mem_alloc(struct vb2_buffer * vb)2147952be9bSHans Verkuil static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
2157952be9bSHans Verkuil {
2167952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
2177952be9bSHans Verkuil 	void *mem_priv;
2187952be9bSHans Verkuil 	int plane;
2197952be9bSHans Verkuil 	int ret = -ENOMEM;
2207952be9bSHans Verkuil 
2217952be9bSHans Verkuil 	/*
2227952be9bSHans Verkuil 	 * Allocate memory for all planes in this buffer
2237952be9bSHans Verkuil 	 * NOTE: mmapped areas should be page aligned
2247952be9bSHans Verkuil 	 */
2257952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
226b29ecab1SSakari Ailus 		/* Memops alloc requires size to be page aligned. */
2277952be9bSHans Verkuil 		unsigned long size = PAGE_ALIGN(vb->planes[plane].length);
2287952be9bSHans Verkuil 
229defcdc5dSSakari Ailus 		/* Did it wrap around? */
230defcdc5dSSakari Ailus 		if (size < vb->planes[plane].length)
231defcdc5dSSakari Ailus 			goto free;
232defcdc5dSSakari Ailus 
233a4b83debSSergey Senozhatsky 		mem_priv = call_ptr_memop(alloc,
234a4b83debSSergey Senozhatsky 					  vb,
2357952be9bSHans Verkuil 					  q->alloc_devs[plane] ? : q->dev,
236a4b83debSSergey Senozhatsky 					  size);
2377952be9bSHans Verkuil 		if (IS_ERR_OR_NULL(mem_priv)) {
2387952be9bSHans Verkuil 			if (mem_priv)
2397952be9bSHans Verkuil 				ret = PTR_ERR(mem_priv);
2407952be9bSHans Verkuil 			goto free;
2417952be9bSHans Verkuil 		}
2427952be9bSHans Verkuil 
2437952be9bSHans Verkuil 		/* Associate allocator private data with this plane */
2447952be9bSHans Verkuil 		vb->planes[plane].mem_priv = mem_priv;
2457952be9bSHans Verkuil 	}
2467952be9bSHans Verkuil 
2477952be9bSHans Verkuil 	return 0;
2487952be9bSHans Verkuil free:
2497952be9bSHans Verkuil 	/* Free already allocated memory if one of the allocations failed */
2507952be9bSHans Verkuil 	for (; plane > 0; --plane) {
2517952be9bSHans Verkuil 		call_void_memop(vb, put, vb->planes[plane - 1].mem_priv);
2527952be9bSHans Verkuil 		vb->planes[plane - 1].mem_priv = NULL;
2537952be9bSHans Verkuil 	}
2547952be9bSHans Verkuil 
2557952be9bSHans Verkuil 	return ret;
2567952be9bSHans Verkuil }
2577952be9bSHans Verkuil 
2587952be9bSHans Verkuil /*
2597952be9bSHans Verkuil  * __vb2_buf_mem_free() - free memory of the given buffer
2607952be9bSHans Verkuil  */
__vb2_buf_mem_free(struct vb2_buffer * vb)2617952be9bSHans Verkuil static void __vb2_buf_mem_free(struct vb2_buffer *vb)
2627952be9bSHans Verkuil {
2637952be9bSHans Verkuil 	unsigned int plane;
2647952be9bSHans Verkuil 
2657952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
2667952be9bSHans Verkuil 		call_void_memop(vb, put, vb->planes[plane].mem_priv);
2677952be9bSHans Verkuil 		vb->planes[plane].mem_priv = NULL;
268b820935bSLaurent Pinchart 		dprintk(vb->vb2_queue, 3, "freed plane %d of buffer %d\n",
269b820935bSLaurent Pinchart 			plane, vb->index);
2707952be9bSHans Verkuil 	}
2717952be9bSHans Verkuil }
2727952be9bSHans Verkuil 
2737952be9bSHans Verkuil /*
2747952be9bSHans Verkuil  * __vb2_buf_userptr_put() - release userspace memory associated with
2757952be9bSHans Verkuil  * a USERPTR buffer
2767952be9bSHans Verkuil  */
__vb2_buf_userptr_put(struct vb2_buffer * vb)2777952be9bSHans Verkuil static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
2787952be9bSHans Verkuil {
2797952be9bSHans Verkuil 	unsigned int plane;
2807952be9bSHans Verkuil 
2817952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
2827952be9bSHans Verkuil 		if (vb->planes[plane].mem_priv)
2837952be9bSHans Verkuil 			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
2847952be9bSHans Verkuil 		vb->planes[plane].mem_priv = NULL;
2857952be9bSHans Verkuil 	}
2867952be9bSHans Verkuil }
2877952be9bSHans Verkuil 
2887952be9bSHans Verkuil /*
2897952be9bSHans Verkuil  * __vb2_plane_dmabuf_put() - release memory associated with
2907952be9bSHans Verkuil  * a DMABUF shared plane
2917952be9bSHans Verkuil  */
__vb2_plane_dmabuf_put(struct vb2_buffer * vb,struct vb2_plane * p)2927952be9bSHans Verkuil static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
2937952be9bSHans Verkuil {
2947952be9bSHans Verkuil 	if (!p->mem_priv)
2957952be9bSHans Verkuil 		return;
2967952be9bSHans Verkuil 
2977952be9bSHans Verkuil 	if (p->dbuf_mapped)
2987952be9bSHans Verkuil 		call_void_memop(vb, unmap_dmabuf, p->mem_priv);
2997952be9bSHans Verkuil 
3007952be9bSHans Verkuil 	call_void_memop(vb, detach_dmabuf, p->mem_priv);
3017952be9bSHans Verkuil 	dma_buf_put(p->dbuf);
3027952be9bSHans Verkuil 	p->mem_priv = NULL;
3037952be9bSHans Verkuil 	p->dbuf = NULL;
3047952be9bSHans Verkuil 	p->dbuf_mapped = 0;
3057952be9bSHans Verkuil }
3067952be9bSHans Verkuil 
3077952be9bSHans Verkuil /*
3087952be9bSHans Verkuil  * __vb2_buf_dmabuf_put() - release memory associated with
3097952be9bSHans Verkuil  * a DMABUF shared buffer
3107952be9bSHans Verkuil  */
__vb2_buf_dmabuf_put(struct vb2_buffer * vb)3117952be9bSHans Verkuil static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
3127952be9bSHans Verkuil {
3137952be9bSHans Verkuil 	unsigned int plane;
3147952be9bSHans Verkuil 
3157952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane)
3167952be9bSHans Verkuil 		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
3177952be9bSHans Verkuil }
3187952be9bSHans Verkuil 
3197952be9bSHans Verkuil /*
32038a417e8SSergey Senozhatsky  * __vb2_buf_mem_prepare() - call ->prepare() on buffer's private memory
32138a417e8SSergey Senozhatsky  * to sync caches
32238a417e8SSergey Senozhatsky  */
__vb2_buf_mem_prepare(struct vb2_buffer * vb)32338a417e8SSergey Senozhatsky static void __vb2_buf_mem_prepare(struct vb2_buffer *vb)
32438a417e8SSergey Senozhatsky {
32538a417e8SSergey Senozhatsky 	unsigned int plane;
32638a417e8SSergey Senozhatsky 
327093067edSSergey Senozhatsky 	if (vb->synced)
328093067edSSergey Senozhatsky 		return;
329093067edSSergey Senozhatsky 
33038a417e8SSergey Senozhatsky 	vb->synced = 1;
3314dbe7eabSSergey Senozhatsky 	for (plane = 0; plane < vb->num_planes; ++plane)
3324dbe7eabSSergey Senozhatsky 		call_void_memop(vb, prepare, vb->planes[plane].mem_priv);
33338a417e8SSergey Senozhatsky }
33438a417e8SSergey Senozhatsky 
33538a417e8SSergey Senozhatsky /*
33638a417e8SSergey Senozhatsky  * __vb2_buf_mem_finish() - call ->finish on buffer's private memory
33738a417e8SSergey Senozhatsky  * to sync caches
33838a417e8SSergey Senozhatsky  */
__vb2_buf_mem_finish(struct vb2_buffer * vb)33938a417e8SSergey Senozhatsky static void __vb2_buf_mem_finish(struct vb2_buffer *vb)
34038a417e8SSergey Senozhatsky {
34138a417e8SSergey Senozhatsky 	unsigned int plane;
34238a417e8SSergey Senozhatsky 
343093067edSSergey Senozhatsky 	if (!vb->synced)
344093067edSSergey Senozhatsky 		return;
345093067edSSergey Senozhatsky 
34638a417e8SSergey Senozhatsky 	vb->synced = 0;
3474dbe7eabSSergey Senozhatsky 	for (plane = 0; plane < vb->num_planes; ++plane)
3484dbe7eabSSergey Senozhatsky 		call_void_memop(vb, finish, vb->planes[plane].mem_priv);
34938a417e8SSergey Senozhatsky }
35038a417e8SSergey Senozhatsky 
35138a417e8SSergey Senozhatsky /*
3527952be9bSHans Verkuil  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
3537952be9bSHans Verkuil  * the buffer.
3547952be9bSHans Verkuil  */
__setup_offsets(struct vb2_buffer * vb)3557952be9bSHans Verkuil static void __setup_offsets(struct vb2_buffer *vb)
3567952be9bSHans Verkuil {
3577952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
3587952be9bSHans Verkuil 	unsigned int plane;
3597952be9bSHans Verkuil 	unsigned long off = 0;
3607952be9bSHans Verkuil 
3617952be9bSHans Verkuil 	if (vb->index) {
3627952be9bSHans Verkuil 		struct vb2_buffer *prev = q->bufs[vb->index - 1];
3637952be9bSHans Verkuil 		struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
3647952be9bSHans Verkuil 
3657952be9bSHans Verkuil 		off = PAGE_ALIGN(p->m.offset + p->length);
3667952be9bSHans Verkuil 	}
3677952be9bSHans Verkuil 
3687952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
3697952be9bSHans Verkuil 		vb->planes[plane].m.offset = off;
3707952be9bSHans Verkuil 
371b820935bSLaurent Pinchart 		dprintk(q, 3, "buffer %d, plane %d offset 0x%08lx\n",
3727952be9bSHans Verkuil 				vb->index, plane, off);
3737952be9bSHans Verkuil 
3747952be9bSHans Verkuil 		off += vb->planes[plane].length;
3757952be9bSHans Verkuil 		off = PAGE_ALIGN(off);
3767952be9bSHans Verkuil 	}
3777952be9bSHans Verkuil }
3787952be9bSHans Verkuil 
init_buffer_cache_hints(struct vb2_queue * q,struct vb2_buffer * vb)3790a12d652SSergey Senozhatsky static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
3800a12d652SSergey Senozhatsky {
3810a12d652SSergey Senozhatsky 	/*
3820a12d652SSergey Senozhatsky 	 * DMA exporter should take care of cache syncs, so we can avoid
3830a12d652SSergey Senozhatsky 	 * explicit ->prepare()/->finish() syncs. For other ->memory types
3840a12d652SSergey Senozhatsky 	 * we always need ->prepare() or/and ->finish() cache sync.
3850a12d652SSergey Senozhatsky 	 */
3860a12d652SSergey Senozhatsky 	if (q->memory == VB2_MEMORY_DMABUF) {
3870a12d652SSergey Senozhatsky 		vb->skip_cache_sync_on_finish = 1;
3880a12d652SSergey Senozhatsky 		vb->skip_cache_sync_on_prepare = 1;
3890a12d652SSergey Senozhatsky 		return;
3900a12d652SSergey Senozhatsky 	}
3910a12d652SSergey Senozhatsky 
3920a12d652SSergey Senozhatsky 	/*
3930a12d652SSergey Senozhatsky 	 * ->finish() cache sync can be avoided when queue direction is
3940a12d652SSergey Senozhatsky 	 * TO_DEVICE.
3950a12d652SSergey Senozhatsky 	 */
3960a12d652SSergey Senozhatsky 	if (q->dma_dir == DMA_TO_DEVICE)
3970a12d652SSergey Senozhatsky 		vb->skip_cache_sync_on_finish = 1;
3980a12d652SSergey Senozhatsky }
3990a12d652SSergey Senozhatsky 
4007952be9bSHans Verkuil /*
4013e947c36SHans Verkuil  * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
4027952be9bSHans Verkuil  * video buffer memory for all buffers/planes on the queue and initializes the
4037952be9bSHans Verkuil  * queue
4047952be9bSHans Verkuil  *
4057952be9bSHans Verkuil  * Returns the number of buffers successfully allocated.
4067952be9bSHans Verkuil  */
__vb2_queue_alloc(struct vb2_queue * q,enum vb2_memory memory,unsigned int num_buffers,unsigned int num_planes,const unsigned plane_sizes[VB2_MAX_PLANES])4077952be9bSHans Verkuil static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
4087952be9bSHans Verkuil 			     unsigned int num_buffers, unsigned int num_planes,
4097952be9bSHans Verkuil 			     const unsigned plane_sizes[VB2_MAX_PLANES])
4107952be9bSHans Verkuil {
4117952be9bSHans Verkuil 	unsigned int buffer, plane;
4127952be9bSHans Verkuil 	struct vb2_buffer *vb;
4137952be9bSHans Verkuil 	int ret;
4147952be9bSHans Verkuil 
4157952be9bSHans Verkuil 	/* Ensure that q->num_buffers+num_buffers is below VB2_MAX_FRAME */
4167952be9bSHans Verkuil 	num_buffers = min_t(unsigned int, num_buffers,
4177952be9bSHans Verkuil 			    VB2_MAX_FRAME - q->num_buffers);
4187952be9bSHans Verkuil 
4197952be9bSHans Verkuil 	for (buffer = 0; buffer < num_buffers; ++buffer) {
4203e947c36SHans Verkuil 		/* Allocate vb2 buffer structures */
4217952be9bSHans Verkuil 		vb = kzalloc(q->buf_struct_size, GFP_KERNEL);
4227952be9bSHans Verkuil 		if (!vb) {
423b820935bSLaurent Pinchart 			dprintk(q, 1, "memory alloc for buffer struct failed\n");
4247952be9bSHans Verkuil 			break;
4257952be9bSHans Verkuil 		}
4267952be9bSHans Verkuil 
4277952be9bSHans Verkuil 		vb->state = VB2_BUF_STATE_DEQUEUED;
4287952be9bSHans Verkuil 		vb->vb2_queue = q;
4297952be9bSHans Verkuil 		vb->num_planes = num_planes;
4307952be9bSHans Verkuil 		vb->index = q->num_buffers + buffer;
4317952be9bSHans Verkuil 		vb->type = q->type;
4327952be9bSHans Verkuil 		vb->memory = memory;
4330a12d652SSergey Senozhatsky 		init_buffer_cache_hints(q, vb);
4347952be9bSHans Verkuil 		for (plane = 0; plane < num_planes; ++plane) {
4357952be9bSHans Verkuil 			vb->planes[plane].length = plane_sizes[plane];
4367952be9bSHans Verkuil 			vb->planes[plane].min_length = plane_sizes[plane];
4377952be9bSHans Verkuil 		}
4388e013700SHans Verkuil 		call_void_bufop(q, init_buffer, vb);
4398e013700SHans Verkuil 
4407952be9bSHans Verkuil 		q->bufs[vb->index] = vb;
4417952be9bSHans Verkuil 
4427952be9bSHans Verkuil 		/* Allocate video buffer memory for the MMAP type */
4437952be9bSHans Verkuil 		if (memory == VB2_MEMORY_MMAP) {
4447952be9bSHans Verkuil 			ret = __vb2_buf_mem_alloc(vb);
4457952be9bSHans Verkuil 			if (ret) {
446b820935bSLaurent Pinchart 				dprintk(q, 1, "failed allocating memory for buffer %d\n",
4477952be9bSHans Verkuil 					buffer);
4487952be9bSHans Verkuil 				q->bufs[vb->index] = NULL;
4497952be9bSHans Verkuil 				kfree(vb);
4507952be9bSHans Verkuil 				break;
4517952be9bSHans Verkuil 			}
4527952be9bSHans Verkuil 			__setup_offsets(vb);
4537952be9bSHans Verkuil 			/*
4547952be9bSHans Verkuil 			 * Call the driver-provided buffer initialization
4557952be9bSHans Verkuil 			 * callback, if given. An error in initialization
4567952be9bSHans Verkuil 			 * results in queue setup failure.
4577952be9bSHans Verkuil 			 */
4587952be9bSHans Verkuil 			ret = call_vb_qop(vb, buf_init, vb);
4597952be9bSHans Verkuil 			if (ret) {
460b820935bSLaurent Pinchart 				dprintk(q, 1, "buffer %d %p initialization failed\n",
4617952be9bSHans Verkuil 					buffer, vb);
4627952be9bSHans Verkuil 				__vb2_buf_mem_free(vb);
4637952be9bSHans Verkuil 				q->bufs[vb->index] = NULL;
4647952be9bSHans Verkuil 				kfree(vb);
4657952be9bSHans Verkuil 				break;
4667952be9bSHans Verkuil 			}
4677952be9bSHans Verkuil 		}
4687952be9bSHans Verkuil 	}
4697952be9bSHans Verkuil 
470b820935bSLaurent Pinchart 	dprintk(q, 3, "allocated %d buffers, %d plane(s) each\n",
4717952be9bSHans Verkuil 		buffer, num_planes);
4727952be9bSHans Verkuil 
4737952be9bSHans Verkuil 	return buffer;
4747952be9bSHans Verkuil }
4757952be9bSHans Verkuil 
4767952be9bSHans Verkuil /*
4777952be9bSHans Verkuil  * __vb2_free_mem() - release all video buffer memory for a given queue
4787952be9bSHans Verkuil  */
__vb2_free_mem(struct vb2_queue * q,unsigned int buffers)4797952be9bSHans Verkuil static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
4807952be9bSHans Verkuil {
4817952be9bSHans Verkuil 	unsigned int buffer;
4827952be9bSHans Verkuil 	struct vb2_buffer *vb;
4837952be9bSHans Verkuil 
4847952be9bSHans Verkuil 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
4857952be9bSHans Verkuil 	     ++buffer) {
4867952be9bSHans Verkuil 		vb = q->bufs[buffer];
4877952be9bSHans Verkuil 		if (!vb)
4887952be9bSHans Verkuil 			continue;
4897952be9bSHans Verkuil 
4907952be9bSHans Verkuil 		/* Free MMAP buffers or release USERPTR buffers */
4917952be9bSHans Verkuil 		if (q->memory == VB2_MEMORY_MMAP)
4927952be9bSHans Verkuil 			__vb2_buf_mem_free(vb);
4937952be9bSHans Verkuil 		else if (q->memory == VB2_MEMORY_DMABUF)
4947952be9bSHans Verkuil 			__vb2_buf_dmabuf_put(vb);
4957952be9bSHans Verkuil 		else
4967952be9bSHans Verkuil 			__vb2_buf_userptr_put(vb);
4977952be9bSHans Verkuil 	}
4987952be9bSHans Verkuil }
4997952be9bSHans Verkuil 
5007952be9bSHans Verkuil /*
5017952be9bSHans Verkuil  * __vb2_queue_free() - free buffers at the end of the queue - video memory and
5027952be9bSHans Verkuil  * related information, if no buffers are left return the queue to an
5037952be9bSHans Verkuil  * uninitialized state. Might be called even if the queue has already been freed.
5047952be9bSHans Verkuil  */
__vb2_queue_free(struct vb2_queue * q,unsigned int buffers)50501cb370fSHans Verkuil static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
5067952be9bSHans Verkuil {
5077952be9bSHans Verkuil 	unsigned int buffer;
5087952be9bSHans Verkuil 
50901cb370fSHans Verkuil 	lockdep_assert_held(&q->mmap_lock);
5107952be9bSHans Verkuil 
5117952be9bSHans Verkuil 	/* Call driver-provided cleanup function for each buffer, if provided */
5127952be9bSHans Verkuil 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
5137952be9bSHans Verkuil 	     ++buffer) {
5147952be9bSHans Verkuil 		struct vb2_buffer *vb = q->bufs[buffer];
5157952be9bSHans Verkuil 
5167952be9bSHans Verkuil 		if (vb && vb->planes[0].mem_priv)
5177952be9bSHans Verkuil 			call_void_vb_qop(vb, buf_cleanup, vb);
5187952be9bSHans Verkuil 	}
5197952be9bSHans Verkuil 
5207952be9bSHans Verkuil 	/* Release video buffer memory */
5217952be9bSHans Verkuil 	__vb2_free_mem(q, buffers);
5227952be9bSHans Verkuil 
5237952be9bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
5247952be9bSHans Verkuil 	/*
5257952be9bSHans Verkuil 	 * Check that all the calls were balances during the life-time of this
5267952be9bSHans Verkuil 	 * queue. If not (or if the debug level is 1 or up), then dump the
5277952be9bSHans Verkuil 	 * counters to the kernel log.
5287952be9bSHans Verkuil 	 */
5297952be9bSHans Verkuil 	if (q->num_buffers) {
5307952be9bSHans Verkuil 		bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming ||
531a10b2153SHans Verkuil 				  q->cnt_prepare_streaming != q->cnt_unprepare_streaming ||
5327952be9bSHans Verkuil 				  q->cnt_wait_prepare != q->cnt_wait_finish;
5337952be9bSHans Verkuil 
5347952be9bSHans Verkuil 		if (unbalanced || debug) {
5357952be9bSHans Verkuil 			pr_info("counters for queue %p:%s\n", q,
5367952be9bSHans Verkuil 				unbalanced ? " UNBALANCED!" : "");
5377952be9bSHans Verkuil 			pr_info("     setup: %u start_streaming: %u stop_streaming: %u\n",
5387952be9bSHans Verkuil 				q->cnt_queue_setup, q->cnt_start_streaming,
5397952be9bSHans Verkuil 				q->cnt_stop_streaming);
540a10b2153SHans Verkuil 			pr_info("     prepare_streaming: %u unprepare_streaming: %u\n",
541a10b2153SHans Verkuil 				q->cnt_prepare_streaming, q->cnt_unprepare_streaming);
5427952be9bSHans Verkuil 			pr_info("     wait_prepare: %u wait_finish: %u\n",
5437952be9bSHans Verkuil 				q->cnt_wait_prepare, q->cnt_wait_finish);
5447952be9bSHans Verkuil 		}
5457952be9bSHans Verkuil 		q->cnt_queue_setup = 0;
5467952be9bSHans Verkuil 		q->cnt_wait_prepare = 0;
5477952be9bSHans Verkuil 		q->cnt_wait_finish = 0;
548a10b2153SHans Verkuil 		q->cnt_prepare_streaming = 0;
5497952be9bSHans Verkuil 		q->cnt_start_streaming = 0;
5507952be9bSHans Verkuil 		q->cnt_stop_streaming = 0;
551a10b2153SHans Verkuil 		q->cnt_unprepare_streaming = 0;
5527952be9bSHans Verkuil 	}
5537952be9bSHans Verkuil 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
5547952be9bSHans Verkuil 		struct vb2_buffer *vb = q->bufs[buffer];
5557952be9bSHans Verkuil 		bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
5567952be9bSHans Verkuil 				  vb->cnt_mem_prepare != vb->cnt_mem_finish ||
5577952be9bSHans Verkuil 				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
5587952be9bSHans Verkuil 				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
5597952be9bSHans Verkuil 				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
5607952be9bSHans Verkuil 				  vb->cnt_buf_queue != vb->cnt_buf_done ||
5617952be9bSHans Verkuil 				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
5627952be9bSHans Verkuil 				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
5637952be9bSHans Verkuil 
5647952be9bSHans Verkuil 		if (unbalanced || debug) {
5657952be9bSHans Verkuil 			pr_info("   counters for queue %p, buffer %d:%s\n",
5667952be9bSHans Verkuil 				q, buffer, unbalanced ? " UNBALANCED!" : "");
5677952be9bSHans Verkuil 			pr_info("     buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n",
5687952be9bSHans Verkuil 				vb->cnt_buf_init, vb->cnt_buf_cleanup,
5697952be9bSHans Verkuil 				vb->cnt_buf_prepare, vb->cnt_buf_finish);
57028d77c21SHans Verkuil 			pr_info("     buf_out_validate: %u buf_queue: %u buf_done: %u buf_request_complete: %u\n",
57128d77c21SHans Verkuil 				vb->cnt_buf_out_validate, vb->cnt_buf_queue,
57228d77c21SHans Verkuil 				vb->cnt_buf_done, vb->cnt_buf_request_complete);
5737952be9bSHans Verkuil 			pr_info("     alloc: %u put: %u prepare: %u finish: %u mmap: %u\n",
5747952be9bSHans Verkuil 				vb->cnt_mem_alloc, vb->cnt_mem_put,
5757952be9bSHans Verkuil 				vb->cnt_mem_prepare, vb->cnt_mem_finish,
5767952be9bSHans Verkuil 				vb->cnt_mem_mmap);
5777952be9bSHans Verkuil 			pr_info("     get_userptr: %u put_userptr: %u\n",
5787952be9bSHans Verkuil 				vb->cnt_mem_get_userptr, vb->cnt_mem_put_userptr);
5797952be9bSHans Verkuil 			pr_info("     attach_dmabuf: %u detach_dmabuf: %u map_dmabuf: %u unmap_dmabuf: %u\n",
5807952be9bSHans Verkuil 				vb->cnt_mem_attach_dmabuf, vb->cnt_mem_detach_dmabuf,
5817952be9bSHans Verkuil 				vb->cnt_mem_map_dmabuf, vb->cnt_mem_unmap_dmabuf);
5827952be9bSHans Verkuil 			pr_info("     get_dmabuf: %u num_users: %u vaddr: %u cookie: %u\n",
5837952be9bSHans Verkuil 				vb->cnt_mem_get_dmabuf,
5847952be9bSHans Verkuil 				vb->cnt_mem_num_users,
5857952be9bSHans Verkuil 				vb->cnt_mem_vaddr,
5867952be9bSHans Verkuil 				vb->cnt_mem_cookie);
5877952be9bSHans Verkuil 		}
5887952be9bSHans Verkuil 	}
5897952be9bSHans Verkuil #endif
5907952be9bSHans Verkuil 
5913e947c36SHans Verkuil 	/* Free vb2 buffers */
5927952be9bSHans Verkuil 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
5937952be9bSHans Verkuil 	     ++buffer) {
5947952be9bSHans Verkuil 		kfree(q->bufs[buffer]);
5957952be9bSHans Verkuil 		q->bufs[buffer] = NULL;
5967952be9bSHans Verkuil 	}
5977952be9bSHans Verkuil 
5987952be9bSHans Verkuil 	q->num_buffers -= buffers;
5997952be9bSHans Verkuil 	if (!q->num_buffers) {
6007952be9bSHans Verkuil 		q->memory = VB2_MEMORY_UNKNOWN;
6017952be9bSHans Verkuil 		INIT_LIST_HEAD(&q->queued_list);
6027952be9bSHans Verkuil 	}
6037952be9bSHans Verkuil }
6047952be9bSHans Verkuil 
vb2_buffer_in_use(struct vb2_queue * q,struct vb2_buffer * vb)6057952be9bSHans Verkuil bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
6067952be9bSHans Verkuil {
6077952be9bSHans Verkuil 	unsigned int plane;
6087952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
6097952be9bSHans Verkuil 		void *mem_priv = vb->planes[plane].mem_priv;
6107952be9bSHans Verkuil 		/*
6117952be9bSHans Verkuil 		 * If num_users() has not been provided, call_memop
6127952be9bSHans Verkuil 		 * will return 0, apparently nobody cares about this
6137952be9bSHans Verkuil 		 * case anyway. If num_users() returns more than 1,
6147952be9bSHans Verkuil 		 * we are not the only user of the plane's memory.
6157952be9bSHans Verkuil 		 */
6167952be9bSHans Verkuil 		if (mem_priv && call_memop(vb, num_users, mem_priv) > 1)
6177952be9bSHans Verkuil 			return true;
6187952be9bSHans Verkuil 	}
6197952be9bSHans Verkuil 	return false;
6207952be9bSHans Verkuil }
6217952be9bSHans Verkuil EXPORT_SYMBOL(vb2_buffer_in_use);
6227952be9bSHans Verkuil 
6237952be9bSHans Verkuil /*
6247952be9bSHans Verkuil  * __buffers_in_use() - return true if any buffers on the queue are in use and
6257952be9bSHans Verkuil  * the queue cannot be freed (by the means of REQBUFS(0)) call
6267952be9bSHans Verkuil  */
__buffers_in_use(struct vb2_queue * q)6277952be9bSHans Verkuil static bool __buffers_in_use(struct vb2_queue *q)
6287952be9bSHans Verkuil {
6297952be9bSHans Verkuil 	unsigned int buffer;
6307952be9bSHans Verkuil 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
6317952be9bSHans Verkuil 		if (vb2_buffer_in_use(q, q->bufs[buffer]))
6327952be9bSHans Verkuil 			return true;
6337952be9bSHans Verkuil 	}
6347952be9bSHans Verkuil 	return false;
6357952be9bSHans Verkuil }
6367952be9bSHans Verkuil 
vb2_core_querybuf(struct vb2_queue * q,unsigned int index,void * pb)6377952be9bSHans Verkuil void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
6387952be9bSHans Verkuil {
6397952be9bSHans Verkuil 	call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
6407952be9bSHans Verkuil }
6417952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_querybuf);
6427952be9bSHans Verkuil 
6437952be9bSHans Verkuil /*
6447952be9bSHans Verkuil  * __verify_userptr_ops() - verify that all memory operations required for
6457952be9bSHans Verkuil  * USERPTR queue type have been provided
6467952be9bSHans Verkuil  */
__verify_userptr_ops(struct vb2_queue * q)6477952be9bSHans Verkuil static int __verify_userptr_ops(struct vb2_queue *q)
6487952be9bSHans Verkuil {
6497952be9bSHans Verkuil 	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
6507952be9bSHans Verkuil 	    !q->mem_ops->put_userptr)
6517952be9bSHans Verkuil 		return -EINVAL;
6527952be9bSHans Verkuil 
6537952be9bSHans Verkuil 	return 0;
6547952be9bSHans Verkuil }
6557952be9bSHans Verkuil 
6567952be9bSHans Verkuil /*
6577952be9bSHans Verkuil  * __verify_mmap_ops() - verify that all memory operations required for
6587952be9bSHans Verkuil  * MMAP queue type have been provided
6597952be9bSHans Verkuil  */
__verify_mmap_ops(struct vb2_queue * q)6607952be9bSHans Verkuil static int __verify_mmap_ops(struct vb2_queue *q)
6617952be9bSHans Verkuil {
6627952be9bSHans Verkuil 	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
6637952be9bSHans Verkuil 	    !q->mem_ops->put || !q->mem_ops->mmap)
6647952be9bSHans Verkuil 		return -EINVAL;
6657952be9bSHans Verkuil 
6667952be9bSHans Verkuil 	return 0;
6677952be9bSHans Verkuil }
6687952be9bSHans Verkuil 
6697952be9bSHans Verkuil /*
6707952be9bSHans Verkuil  * __verify_dmabuf_ops() - verify that all memory operations required for
6717952be9bSHans Verkuil  * DMABUF queue type have been provided
6727952be9bSHans Verkuil  */
__verify_dmabuf_ops(struct vb2_queue * q)6737952be9bSHans Verkuil static int __verify_dmabuf_ops(struct vb2_queue *q)
6747952be9bSHans Verkuil {
6757952be9bSHans Verkuil 	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
6767952be9bSHans Verkuil 	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
6777952be9bSHans Verkuil 	    !q->mem_ops->unmap_dmabuf)
6787952be9bSHans Verkuil 		return -EINVAL;
6797952be9bSHans Verkuil 
6807952be9bSHans Verkuil 	return 0;
6817952be9bSHans Verkuil }
6827952be9bSHans Verkuil 
vb2_verify_memory_type(struct vb2_queue * q,enum vb2_memory memory,unsigned int type)6837952be9bSHans Verkuil int vb2_verify_memory_type(struct vb2_queue *q,
6847952be9bSHans Verkuil 		enum vb2_memory memory, unsigned int type)
6857952be9bSHans Verkuil {
6867952be9bSHans Verkuil 	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
6877952be9bSHans Verkuil 	    memory != VB2_MEMORY_DMABUF) {
688b820935bSLaurent Pinchart 		dprintk(q, 1, "unsupported memory type\n");
6897952be9bSHans Verkuil 		return -EINVAL;
6907952be9bSHans Verkuil 	}
6917952be9bSHans Verkuil 
6927952be9bSHans Verkuil 	if (type != q->type) {
693b820935bSLaurent Pinchart 		dprintk(q, 1, "requested type is incorrect\n");
6947952be9bSHans Verkuil 		return -EINVAL;
6957952be9bSHans Verkuil 	}
6967952be9bSHans Verkuil 
6977952be9bSHans Verkuil 	/*
6987952be9bSHans Verkuil 	 * Make sure all the required memory ops for given memory type
6997952be9bSHans Verkuil 	 * are available.
7007952be9bSHans Verkuil 	 */
7017952be9bSHans Verkuil 	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
702b820935bSLaurent Pinchart 		dprintk(q, 1, "MMAP for current setup unsupported\n");
7037952be9bSHans Verkuil 		return -EINVAL;
7047952be9bSHans Verkuil 	}
7057952be9bSHans Verkuil 
7067952be9bSHans Verkuil 	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
707b820935bSLaurent Pinchart 		dprintk(q, 1, "USERPTR for current setup unsupported\n");
7087952be9bSHans Verkuil 		return -EINVAL;
7097952be9bSHans Verkuil 	}
7107952be9bSHans Verkuil 
7117952be9bSHans Verkuil 	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
712b820935bSLaurent Pinchart 		dprintk(q, 1, "DMABUF for current setup unsupported\n");
7137952be9bSHans Verkuil 		return -EINVAL;
7147952be9bSHans Verkuil 	}
7157952be9bSHans Verkuil 
7167952be9bSHans Verkuil 	/*
7177952be9bSHans Verkuil 	 * Place the busy tests at the end: -EBUSY can be ignored when
7187952be9bSHans Verkuil 	 * create_bufs is called with count == 0, but count == 0 should still
7197952be9bSHans Verkuil 	 * do the memory and type validation.
7207952be9bSHans Verkuil 	 */
7217952be9bSHans Verkuil 	if (vb2_fileio_is_active(q)) {
722b820935bSLaurent Pinchart 		dprintk(q, 1, "file io in progress\n");
7237952be9bSHans Verkuil 		return -EBUSY;
7247952be9bSHans Verkuil 	}
7257952be9bSHans Verkuil 	return 0;
7267952be9bSHans Verkuil }
7277952be9bSHans Verkuil EXPORT_SYMBOL(vb2_verify_memory_type);
7287952be9bSHans Verkuil 
set_queue_coherency(struct vb2_queue * q,bool non_coherent_mem)729b00a9e59SSergey Senozhatsky static void set_queue_coherency(struct vb2_queue *q, bool non_coherent_mem)
730b00a9e59SSergey Senozhatsky {
731b00a9e59SSergey Senozhatsky 	q->non_coherent_mem = 0;
732b00a9e59SSergey Senozhatsky 
733b00a9e59SSergey Senozhatsky 	if (!vb2_queue_allows_cache_hints(q))
734b00a9e59SSergey Senozhatsky 		return;
735b00a9e59SSergey Senozhatsky 	q->non_coherent_mem = non_coherent_mem;
736b00a9e59SSergey Senozhatsky }
737b00a9e59SSergey Senozhatsky 
verify_coherency_flags(struct vb2_queue * q,bool non_coherent_mem)738b00a9e59SSergey Senozhatsky static bool verify_coherency_flags(struct vb2_queue *q, bool non_coherent_mem)
739b00a9e59SSergey Senozhatsky {
740b00a9e59SSergey Senozhatsky 	if (non_coherent_mem != q->non_coherent_mem) {
741b00a9e59SSergey Senozhatsky 		dprintk(q, 1, "memory coherency model mismatch\n");
742b00a9e59SSergey Senozhatsky 		return false;
743b00a9e59SSergey Senozhatsky 	}
744b00a9e59SSergey Senozhatsky 	return true;
745b00a9e59SSergey Senozhatsky }
746b00a9e59SSergey Senozhatsky 
vb2_core_reqbufs(struct vb2_queue * q,enum vb2_memory memory,unsigned int flags,unsigned int * count)7477952be9bSHans Verkuil int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
748b00a9e59SSergey Senozhatsky 		     unsigned int flags, unsigned int *count)
7497952be9bSHans Verkuil {
7507952be9bSHans Verkuil 	unsigned int num_buffers, allocated_buffers, num_planes = 0;
7517952be9bSHans Verkuil 	unsigned plane_sizes[VB2_MAX_PLANES] = { };
752c0acf9cfSSergey Senozhatsky 	bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
7538ee92410SJohan Fjeldtvedt 	unsigned int i;
7547952be9bSHans Verkuil 	int ret;
7557952be9bSHans Verkuil 
7567952be9bSHans Verkuil 	if (q->streaming) {
757b820935bSLaurent Pinchart 		dprintk(q, 1, "streaming active\n");
7587952be9bSHans Verkuil 		return -EBUSY;
7597952be9bSHans Verkuil 	}
7607952be9bSHans Verkuil 
761d65842f7SHans Verkuil 	if (q->waiting_in_dqbuf && *count) {
762b820935bSLaurent Pinchart 		dprintk(q, 1, "another dup()ped fd is waiting for a buffer\n");
763d65842f7SHans Verkuil 		return -EBUSY;
764d65842f7SHans Verkuil 	}
765d65842f7SHans Verkuil 
7667952be9bSHans Verkuil 	if (*count == 0 || q->num_buffers != 0 ||
767b00a9e59SSergey Senozhatsky 	    (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory) ||
768b00a9e59SSergey Senozhatsky 	    !verify_coherency_flags(q, non_coherent_mem)) {
7697952be9bSHans Verkuil 		/*
7707952be9bSHans Verkuil 		 * We already have buffers allocated, so first check if they
7717952be9bSHans Verkuil 		 * are not in use and can be freed.
7727952be9bSHans Verkuil 		 */
7737952be9bSHans Verkuil 		mutex_lock(&q->mmap_lock);
774d644cca5SJohn Sheu 		if (debug && q->memory == VB2_MEMORY_MMAP &&
775d644cca5SJohn Sheu 		    __buffers_in_use(q))
776b820935bSLaurent Pinchart 			dprintk(q, 1, "memory in use, orphaning buffers\n");
7777952be9bSHans Verkuil 
7787952be9bSHans Verkuil 		/*
77955028695SHans Verkuil 		 * Call queue_cancel to clean up any buffers in the
7807952be9bSHans Verkuil 		 * QUEUED state which is possible if buffers were prepared or
7817952be9bSHans Verkuil 		 * queued without ever calling STREAMON.
7827952be9bSHans Verkuil 		 */
7837952be9bSHans Verkuil 		__vb2_queue_cancel(q);
78401cb370fSHans Verkuil 		__vb2_queue_free(q, q->num_buffers);
7857952be9bSHans Verkuil 		mutex_unlock(&q->mmap_lock);
7867952be9bSHans Verkuil 
7877952be9bSHans Verkuil 		/*
7887952be9bSHans Verkuil 		 * In case of REQBUFS(0) return immediately without calling
7897952be9bSHans Verkuil 		 * driver's queue_setup() callback and allocating resources.
7907952be9bSHans Verkuil 		 */
7917952be9bSHans Verkuil 		if (*count == 0)
7927952be9bSHans Verkuil 			return 0;
7937952be9bSHans Verkuil 	}
7947952be9bSHans Verkuil 
7957952be9bSHans Verkuil 	/*
7967952be9bSHans Verkuil 	 * Make sure the requested values and current defaults are sane.
7977952be9bSHans Verkuil 	 */
7987952be9bSHans Verkuil 	WARN_ON(q->min_buffers_needed > VB2_MAX_FRAME);
7997952be9bSHans Verkuil 	num_buffers = max_t(unsigned int, *count, q->min_buffers_needed);
8007952be9bSHans Verkuil 	num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
8017952be9bSHans Verkuil 	memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
802098e5edcSHans Verkuil 	/*
803098e5edcSHans Verkuil 	 * Set this now to ensure that drivers see the correct q->memory value
804098e5edcSHans Verkuil 	 * in the queue_setup op.
805098e5edcSHans Verkuil 	 */
806098e5edcSHans Verkuil 	mutex_lock(&q->mmap_lock);
8077952be9bSHans Verkuil 	q->memory = memory;
808098e5edcSHans Verkuil 	mutex_unlock(&q->mmap_lock);
809b00a9e59SSergey Senozhatsky 	set_queue_coherency(q, non_coherent_mem);
8107952be9bSHans Verkuil 
8117952be9bSHans Verkuil 	/*
8127952be9bSHans Verkuil 	 * Ask the driver how many buffers and planes per buffer it requires.
8137952be9bSHans Verkuil 	 * Driver also sets the size and allocator context for each plane.
8147952be9bSHans Verkuil 	 */
8157952be9bSHans Verkuil 	ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
8167952be9bSHans Verkuil 		       plane_sizes, q->alloc_devs);
8177952be9bSHans Verkuil 	if (ret)
818098e5edcSHans Verkuil 		goto error;
8197952be9bSHans Verkuil 
8208ee92410SJohan Fjeldtvedt 	/* Check that driver has set sane values */
821098e5edcSHans Verkuil 	if (WARN_ON(!num_planes)) {
822098e5edcSHans Verkuil 		ret = -EINVAL;
823098e5edcSHans Verkuil 		goto error;
824098e5edcSHans Verkuil 	}
8258ee92410SJohan Fjeldtvedt 
8268ee92410SJohan Fjeldtvedt 	for (i = 0; i < num_planes; i++)
827098e5edcSHans Verkuil 		if (WARN_ON(!plane_sizes[i])) {
828098e5edcSHans Verkuil 			ret = -EINVAL;
829098e5edcSHans Verkuil 			goto error;
830098e5edcSHans Verkuil 		}
8318ee92410SJohan Fjeldtvedt 
8327952be9bSHans Verkuil 	/* Finally, allocate buffers and video memory */
8337952be9bSHans Verkuil 	allocated_buffers =
8347952be9bSHans Verkuil 		__vb2_queue_alloc(q, memory, num_buffers, num_planes, plane_sizes);
8357952be9bSHans Verkuil 	if (allocated_buffers == 0) {
836b820935bSLaurent Pinchart 		dprintk(q, 1, "memory allocation failed\n");
837098e5edcSHans Verkuil 		ret = -ENOMEM;
838098e5edcSHans Verkuil 		goto error;
8397952be9bSHans Verkuil 	}
8407952be9bSHans Verkuil 
8417952be9bSHans Verkuil 	/*
8427952be9bSHans Verkuil 	 * There is no point in continuing if we can't allocate the minimum
8437952be9bSHans Verkuil 	 * number of buffers needed by this vb2_queue.
8447952be9bSHans Verkuil 	 */
8457952be9bSHans Verkuil 	if (allocated_buffers < q->min_buffers_needed)
8467952be9bSHans Verkuil 		ret = -ENOMEM;
8477952be9bSHans Verkuil 
8487952be9bSHans Verkuil 	/*
8497952be9bSHans Verkuil 	 * Check if driver can handle the allocated number of buffers.
8507952be9bSHans Verkuil 	 */
8517952be9bSHans Verkuil 	if (!ret && allocated_buffers < num_buffers) {
8527952be9bSHans Verkuil 		num_buffers = allocated_buffers;
8537952be9bSHans Verkuil 		/*
8547952be9bSHans Verkuil 		 * num_planes is set by the previous queue_setup(), but since it
8557952be9bSHans Verkuil 		 * signals to queue_setup() whether it is called from create_bufs()
8567952be9bSHans Verkuil 		 * vs reqbufs() we zero it here to signal that queue_setup() is
8577952be9bSHans Verkuil 		 * called for the reqbufs() case.
8587952be9bSHans Verkuil 		 */
8597952be9bSHans Verkuil 		num_planes = 0;
8607952be9bSHans Verkuil 
8617952be9bSHans Verkuil 		ret = call_qop(q, queue_setup, q, &num_buffers,
8627952be9bSHans Verkuil 			       &num_planes, plane_sizes, q->alloc_devs);
8637952be9bSHans Verkuil 
8647952be9bSHans Verkuil 		if (!ret && allocated_buffers < num_buffers)
8657952be9bSHans Verkuil 			ret = -ENOMEM;
8667952be9bSHans Verkuil 
8677952be9bSHans Verkuil 		/*
8687952be9bSHans Verkuil 		 * Either the driver has accepted a smaller number of buffers,
8697952be9bSHans Verkuil 		 * or .queue_setup() returned an error
8707952be9bSHans Verkuil 		 */
8717952be9bSHans Verkuil 	}
8727952be9bSHans Verkuil 
8737952be9bSHans Verkuil 	mutex_lock(&q->mmap_lock);
8747952be9bSHans Verkuil 	q->num_buffers = allocated_buffers;
8757952be9bSHans Verkuil 
8767952be9bSHans Verkuil 	if (ret < 0) {
8777952be9bSHans Verkuil 		/*
8787952be9bSHans Verkuil 		 * Note: __vb2_queue_free() will subtract 'allocated_buffers'
879098e5edcSHans Verkuil 		 * from q->num_buffers and it will reset q->memory to
880098e5edcSHans Verkuil 		 * VB2_MEMORY_UNKNOWN.
8817952be9bSHans Verkuil 		 */
8827952be9bSHans Verkuil 		__vb2_queue_free(q, allocated_buffers);
8837952be9bSHans Verkuil 		mutex_unlock(&q->mmap_lock);
8847952be9bSHans Verkuil 		return ret;
8857952be9bSHans Verkuil 	}
8867952be9bSHans Verkuil 	mutex_unlock(&q->mmap_lock);
8877952be9bSHans Verkuil 
8887952be9bSHans Verkuil 	/*
8897952be9bSHans Verkuil 	 * Return the number of successfully allocated buffers
8907952be9bSHans Verkuil 	 * to the userspace.
8917952be9bSHans Verkuil 	 */
8927952be9bSHans Verkuil 	*count = allocated_buffers;
8937952be9bSHans Verkuil 	q->waiting_for_buffers = !q->is_output;
8947952be9bSHans Verkuil 
8957952be9bSHans Verkuil 	return 0;
896098e5edcSHans Verkuil 
897098e5edcSHans Verkuil error:
898098e5edcSHans Verkuil 	mutex_lock(&q->mmap_lock);
899098e5edcSHans Verkuil 	q->memory = VB2_MEMORY_UNKNOWN;
900098e5edcSHans Verkuil 	mutex_unlock(&q->mmap_lock);
901098e5edcSHans Verkuil 	return ret;
9027952be9bSHans Verkuil }
9037952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
9047952be9bSHans Verkuil 
vb2_core_create_bufs(struct vb2_queue * q,enum vb2_memory memory,unsigned int flags,unsigned int * count,unsigned int requested_planes,const unsigned int requested_sizes[])9057952be9bSHans Verkuil int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
906b00a9e59SSergey Senozhatsky 			 unsigned int flags, unsigned int *count,
9077b4b4555SSergey Senozhatsky 			 unsigned int requested_planes,
9087b4b4555SSergey Senozhatsky 			 const unsigned int requested_sizes[])
9097952be9bSHans Verkuil {
9107952be9bSHans Verkuil 	unsigned int num_planes = 0, num_buffers, allocated_buffers;
9117952be9bSHans Verkuil 	unsigned plane_sizes[VB2_MAX_PLANES] = { };
912c0acf9cfSSergey Senozhatsky 	bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
913098e5edcSHans Verkuil 	bool no_previous_buffers = !q->num_buffers;
9147952be9bSHans Verkuil 	int ret;
9157952be9bSHans Verkuil 
9167952be9bSHans Verkuil 	if (q->num_buffers == VB2_MAX_FRAME) {
917b820935bSLaurent Pinchart 		dprintk(q, 1, "maximum number of buffers already allocated\n");
9187952be9bSHans Verkuil 		return -ENOBUFS;
9197952be9bSHans Verkuil 	}
9207952be9bSHans Verkuil 
921098e5edcSHans Verkuil 	if (no_previous_buffers) {
922d65842f7SHans Verkuil 		if (q->waiting_in_dqbuf && *count) {
923b820935bSLaurent Pinchart 			dprintk(q, 1, "another dup()ped fd is waiting for a buffer\n");
924d65842f7SHans Verkuil 			return -EBUSY;
925d65842f7SHans Verkuil 		}
9267952be9bSHans Verkuil 		memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
927098e5edcSHans Verkuil 		/*
928098e5edcSHans Verkuil 		 * Set this now to ensure that drivers see the correct q->memory
929098e5edcSHans Verkuil 		 * value in the queue_setup op.
930098e5edcSHans Verkuil 		 */
931098e5edcSHans Verkuil 		mutex_lock(&q->mmap_lock);
9327952be9bSHans Verkuil 		q->memory = memory;
933098e5edcSHans Verkuil 		mutex_unlock(&q->mmap_lock);
9347952be9bSHans Verkuil 		q->waiting_for_buffers = !q->is_output;
935b00a9e59SSergey Senozhatsky 		set_queue_coherency(q, non_coherent_mem);
9367b4b4555SSergey Senozhatsky 	} else {
9377b4b4555SSergey Senozhatsky 		if (q->memory != memory) {
938b820935bSLaurent Pinchart 			dprintk(q, 1, "memory model mismatch\n");
93962dcb4f4SHans Verkuil 			return -EINVAL;
9407952be9bSHans Verkuil 		}
941b00a9e59SSergey Senozhatsky 		if (!verify_coherency_flags(q, non_coherent_mem))
942b00a9e59SSergey Senozhatsky 			return -EINVAL;
9437b4b4555SSergey Senozhatsky 	}
9447952be9bSHans Verkuil 
9457952be9bSHans Verkuil 	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
9467952be9bSHans Verkuil 
9477952be9bSHans Verkuil 	if (requested_planes && requested_sizes) {
9487952be9bSHans Verkuil 		num_planes = requested_planes;
9497952be9bSHans Verkuil 		memcpy(plane_sizes, requested_sizes, sizeof(plane_sizes));
9507952be9bSHans Verkuil 	}
9517952be9bSHans Verkuil 
9527952be9bSHans Verkuil 	/*
9537952be9bSHans Verkuil 	 * Ask the driver, whether the requested number of buffers, planes per
9547952be9bSHans Verkuil 	 * buffer and their sizes are acceptable
9557952be9bSHans Verkuil 	 */
9567952be9bSHans Verkuil 	ret = call_qop(q, queue_setup, q, &num_buffers,
9577952be9bSHans Verkuil 		       &num_planes, plane_sizes, q->alloc_devs);
9587952be9bSHans Verkuil 	if (ret)
959098e5edcSHans Verkuil 		goto error;
9607952be9bSHans Verkuil 
9617952be9bSHans Verkuil 	/* Finally, allocate buffers and video memory */
9627952be9bSHans Verkuil 	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
9637952be9bSHans Verkuil 				num_planes, plane_sizes);
9647952be9bSHans Verkuil 	if (allocated_buffers == 0) {
965b820935bSLaurent Pinchart 		dprintk(q, 1, "memory allocation failed\n");
966098e5edcSHans Verkuil 		ret = -ENOMEM;
967098e5edcSHans Verkuil 		goto error;
9687952be9bSHans Verkuil 	}
9697952be9bSHans Verkuil 
9707952be9bSHans Verkuil 	/*
9717952be9bSHans Verkuil 	 * Check if driver can handle the so far allocated number of buffers.
9727952be9bSHans Verkuil 	 */
9737952be9bSHans Verkuil 	if (allocated_buffers < num_buffers) {
9747952be9bSHans Verkuil 		num_buffers = allocated_buffers;
9757952be9bSHans Verkuil 
9767952be9bSHans Verkuil 		/*
9777952be9bSHans Verkuil 		 * q->num_buffers contains the total number of buffers, that the
9787952be9bSHans Verkuil 		 * queue driver has set up
9797952be9bSHans Verkuil 		 */
9807952be9bSHans Verkuil 		ret = call_qop(q, queue_setup, q, &num_buffers,
9817952be9bSHans Verkuil 			       &num_planes, plane_sizes, q->alloc_devs);
9827952be9bSHans Verkuil 
9837952be9bSHans Verkuil 		if (!ret && allocated_buffers < num_buffers)
9847952be9bSHans Verkuil 			ret = -ENOMEM;
9857952be9bSHans Verkuil 
9867952be9bSHans Verkuil 		/*
9877952be9bSHans Verkuil 		 * Either the driver has accepted a smaller number of buffers,
9887952be9bSHans Verkuil 		 * or .queue_setup() returned an error
9897952be9bSHans Verkuil 		 */
9907952be9bSHans Verkuil 	}
9917952be9bSHans Verkuil 
9927952be9bSHans Verkuil 	mutex_lock(&q->mmap_lock);
9937952be9bSHans Verkuil 	q->num_buffers += allocated_buffers;
9947952be9bSHans Verkuil 
9957952be9bSHans Verkuil 	if (ret < 0) {
9967952be9bSHans Verkuil 		/*
9977952be9bSHans Verkuil 		 * Note: __vb2_queue_free() will subtract 'allocated_buffers'
998098e5edcSHans Verkuil 		 * from q->num_buffers and it will reset q->memory to
999098e5edcSHans Verkuil 		 * VB2_MEMORY_UNKNOWN.
10007952be9bSHans Verkuil 		 */
10017952be9bSHans Verkuil 		__vb2_queue_free(q, allocated_buffers);
10027952be9bSHans Verkuil 		mutex_unlock(&q->mmap_lock);
10037952be9bSHans Verkuil 		return -ENOMEM;
10047952be9bSHans Verkuil 	}
10057952be9bSHans Verkuil 	mutex_unlock(&q->mmap_lock);
10067952be9bSHans Verkuil 
10077952be9bSHans Verkuil 	/*
10087952be9bSHans Verkuil 	 * Return the number of successfully allocated buffers
10097952be9bSHans Verkuil 	 * to the userspace.
10107952be9bSHans Verkuil 	 */
10117952be9bSHans Verkuil 	*count = allocated_buffers;
10127952be9bSHans Verkuil 
10137952be9bSHans Verkuil 	return 0;
1014098e5edcSHans Verkuil 
1015098e5edcSHans Verkuil error:
1016098e5edcSHans Verkuil 	if (no_previous_buffers) {
1017098e5edcSHans Verkuil 		mutex_lock(&q->mmap_lock);
1018098e5edcSHans Verkuil 		q->memory = VB2_MEMORY_UNKNOWN;
1019098e5edcSHans Verkuil 		mutex_unlock(&q->mmap_lock);
1020098e5edcSHans Verkuil 	}
1021098e5edcSHans Verkuil 	return ret;
10227952be9bSHans Verkuil }
10237952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
10247952be9bSHans Verkuil 
vb2_plane_vaddr(struct vb2_buffer * vb,unsigned int plane_no)10257952be9bSHans Verkuil void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
10267952be9bSHans Verkuil {
10277952be9bSHans Verkuil 	if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
10287952be9bSHans Verkuil 		return NULL;
10297952be9bSHans Verkuil 
1030a4b83debSSergey Senozhatsky 	return call_ptr_memop(vaddr, vb, vb->planes[plane_no].mem_priv);
10317952be9bSHans Verkuil 
10327952be9bSHans Verkuil }
10337952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
10347952be9bSHans Verkuil 
vb2_plane_cookie(struct vb2_buffer * vb,unsigned int plane_no)10357952be9bSHans Verkuil void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
10367952be9bSHans Verkuil {
10377952be9bSHans Verkuil 	if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
10387952be9bSHans Verkuil 		return NULL;
10397952be9bSHans Verkuil 
1040a4b83debSSergey Senozhatsky 	return call_ptr_memop(cookie, vb, vb->planes[plane_no].mem_priv);
10417952be9bSHans Verkuil }
10427952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_plane_cookie);
10437952be9bSHans Verkuil 
vb2_buffer_done(struct vb2_buffer * vb,enum vb2_buffer_state state)10447952be9bSHans Verkuil void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
10457952be9bSHans Verkuil {
10467952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
10477952be9bSHans Verkuil 	unsigned long flags;
10487952be9bSHans Verkuil 
10497952be9bSHans Verkuil 	if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))
10507952be9bSHans Verkuil 		return;
10517952be9bSHans Verkuil 
10527952be9bSHans Verkuil 	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
10537952be9bSHans Verkuil 		    state != VB2_BUF_STATE_ERROR &&
1054c6e4e2c4SHans Verkuil 		    state != VB2_BUF_STATE_QUEUED))
10557952be9bSHans Verkuil 		state = VB2_BUF_STATE_ERROR;
10567952be9bSHans Verkuil 
10577952be9bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
10587952be9bSHans Verkuil 	/*
10597952be9bSHans Verkuil 	 * Although this is not a callback, it still does have to balance
10607952be9bSHans Verkuil 	 * with the buf_queue op. So update this counter manually.
10617952be9bSHans Verkuil 	 */
10627952be9bSHans Verkuil 	vb->cnt_buf_done++;
10637952be9bSHans Verkuil #endif
1064c89ee8edSEzequiel Garcia 	dprintk(q, 4, "done processing on buffer %d, state: %s\n",
1065c89ee8edSEzequiel Garcia 		vb->index, vb2_state_name(state));
10667952be9bSHans Verkuil 
106738a417e8SSergey Senozhatsky 	if (state != VB2_BUF_STATE_QUEUED)
106838a417e8SSergey Senozhatsky 		__vb2_buf_mem_finish(vb);
10697952be9bSHans Verkuil 
10707952be9bSHans Verkuil 	spin_lock_irqsave(&q->done_lock, flags);
1071c6e4e2c4SHans Verkuil 	if (state == VB2_BUF_STATE_QUEUED) {
10727952be9bSHans Verkuil 		vb->state = VB2_BUF_STATE_QUEUED;
10737952be9bSHans Verkuil 	} else {
10747952be9bSHans Verkuil 		/* Add the buffer to the done buffers list */
10757952be9bSHans Verkuil 		list_add_tail(&vb->done_entry, &q->done_list);
10767952be9bSHans Verkuil 		vb->state = state;
10777952be9bSHans Verkuil 	}
10787952be9bSHans Verkuil 	atomic_dec(&q->owned_by_drv_count);
1079fd89e0bbSHans Verkuil 
1080dde6bdccSHans Verkuil 	if (state != VB2_BUF_STATE_QUEUED && vb->req_obj.req) {
1081fd89e0bbSHans Verkuil 		media_request_object_unbind(&vb->req_obj);
1082fd89e0bbSHans Verkuil 		media_request_object_put(&vb->req_obj);
1083fd89e0bbSHans Verkuil 	}
1084fd89e0bbSHans Verkuil 
10857952be9bSHans Verkuil 	spin_unlock_irqrestore(&q->done_lock, flags);
10867952be9bSHans Verkuil 
10877952be9bSHans Verkuil 	trace_vb2_buf_done(q, vb);
10887952be9bSHans Verkuil 
10897952be9bSHans Verkuil 	switch (state) {
10907952be9bSHans Verkuil 	case VB2_BUF_STATE_QUEUED:
10917952be9bSHans Verkuil 		return;
10927952be9bSHans Verkuil 	default:
10937952be9bSHans Verkuil 		/* Inform any processes that may be waiting for buffers */
10947952be9bSHans Verkuil 		wake_up(&q->done_wq);
10957952be9bSHans Verkuil 		break;
10967952be9bSHans Verkuil 	}
10977952be9bSHans Verkuil }
10987952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_buffer_done);
10997952be9bSHans Verkuil 
vb2_discard_done(struct vb2_queue * q)11007952be9bSHans Verkuil void vb2_discard_done(struct vb2_queue *q)
11017952be9bSHans Verkuil {
11027952be9bSHans Verkuil 	struct vb2_buffer *vb;
11037952be9bSHans Verkuil 	unsigned long flags;
11047952be9bSHans Verkuil 
11057952be9bSHans Verkuil 	spin_lock_irqsave(&q->done_lock, flags);
11067952be9bSHans Verkuil 	list_for_each_entry(vb, &q->done_list, done_entry)
11077952be9bSHans Verkuil 		vb->state = VB2_BUF_STATE_ERROR;
11087952be9bSHans Verkuil 	spin_unlock_irqrestore(&q->done_lock, flags);
11097952be9bSHans Verkuil }
11107952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_discard_done);
11117952be9bSHans Verkuil 
11127952be9bSHans Verkuil /*
11137952be9bSHans Verkuil  * __prepare_mmap() - prepare an MMAP buffer
11147952be9bSHans Verkuil  */
__prepare_mmap(struct vb2_buffer * vb)1115db6e8d57SHans Verkuil static int __prepare_mmap(struct vb2_buffer *vb)
11167952be9bSHans Verkuil {
11177952be9bSHans Verkuil 	int ret = 0;
11187952be9bSHans Verkuil 
11197952be9bSHans Verkuil 	ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1120db6e8d57SHans Verkuil 			 vb, vb->planes);
11217952be9bSHans Verkuil 	return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
11227952be9bSHans Verkuil }
11237952be9bSHans Verkuil 
11247952be9bSHans Verkuil /*
11257952be9bSHans Verkuil  * __prepare_userptr() - prepare a USERPTR buffer
11267952be9bSHans Verkuil  */
__prepare_userptr(struct vb2_buffer * vb)1127db6e8d57SHans Verkuil static int __prepare_userptr(struct vb2_buffer *vb)
11287952be9bSHans Verkuil {
11297952be9bSHans Verkuil 	struct vb2_plane planes[VB2_MAX_PLANES];
11307952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
11317952be9bSHans Verkuil 	void *mem_priv;
11327952be9bSHans Verkuil 	unsigned int plane;
11337952be9bSHans Verkuil 	int ret = 0;
11347952be9bSHans Verkuil 	bool reacquired = vb->planes[0].mem_priv == NULL;
11357952be9bSHans Verkuil 
11367952be9bSHans Verkuil 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
11377952be9bSHans Verkuil 	/* Copy relevant information provided by the userspace */
11387952be9bSHans Verkuil 	ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1139db6e8d57SHans Verkuil 			 vb, planes);
11407952be9bSHans Verkuil 	if (ret)
11417952be9bSHans Verkuil 		return ret;
11427952be9bSHans Verkuil 
11437952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
11447952be9bSHans Verkuil 		/* Skip the plane if already verified */
11457952be9bSHans Verkuil 		if (vb->planes[plane].m.userptr &&
11467952be9bSHans Verkuil 			vb->planes[plane].m.userptr == planes[plane].m.userptr
11477952be9bSHans Verkuil 			&& vb->planes[plane].length == planes[plane].length)
11487952be9bSHans Verkuil 			continue;
11497952be9bSHans Verkuil 
1150b820935bSLaurent Pinchart 		dprintk(q, 3, "userspace address for plane %d changed, reacquiring memory\n",
11517952be9bSHans Verkuil 			plane);
11527952be9bSHans Verkuil 
11537952be9bSHans Verkuil 		/* Check if the provided plane buffer is large enough */
11547952be9bSHans Verkuil 		if (planes[plane].length < vb->planes[plane].min_length) {
1155b820935bSLaurent Pinchart 			dprintk(q, 1, "provided buffer size %u is less than setup size %u for plane %d\n",
11567952be9bSHans Verkuil 						planes[plane].length,
11577952be9bSHans Verkuil 						vb->planes[plane].min_length,
11587952be9bSHans Verkuil 						plane);
11597952be9bSHans Verkuil 			ret = -EINVAL;
11607952be9bSHans Verkuil 			goto err;
11617952be9bSHans Verkuil 		}
11627952be9bSHans Verkuil 
11637952be9bSHans Verkuil 		/* Release previously acquired memory if present */
11647952be9bSHans Verkuil 		if (vb->planes[plane].mem_priv) {
11657952be9bSHans Verkuil 			if (!reacquired) {
11667952be9bSHans Verkuil 				reacquired = true;
11677e4e7162SHans Verkuil 				vb->copied_timestamp = 0;
11687952be9bSHans Verkuil 				call_void_vb_qop(vb, buf_cleanup, vb);
11697952be9bSHans Verkuil 			}
11707952be9bSHans Verkuil 			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
11717952be9bSHans Verkuil 		}
11727952be9bSHans Verkuil 
11737952be9bSHans Verkuil 		vb->planes[plane].mem_priv = NULL;
11747952be9bSHans Verkuil 		vb->planes[plane].bytesused = 0;
11757952be9bSHans Verkuil 		vb->planes[plane].length = 0;
11767952be9bSHans Verkuil 		vb->planes[plane].m.userptr = 0;
11777952be9bSHans Verkuil 		vb->planes[plane].data_offset = 0;
11787952be9bSHans Verkuil 
11797952be9bSHans Verkuil 		/* Acquire each plane's memory */
1180a4b83debSSergey Senozhatsky 		mem_priv = call_ptr_memop(get_userptr,
1181a4b83debSSergey Senozhatsky 					  vb,
11827952be9bSHans Verkuil 					  q->alloc_devs[plane] ? : q->dev,
11837952be9bSHans Verkuil 					  planes[plane].m.userptr,
1184a4b83debSSergey Senozhatsky 					  planes[plane].length);
11857952be9bSHans Verkuil 		if (IS_ERR(mem_priv)) {
1186b820935bSLaurent Pinchart 			dprintk(q, 1, "failed acquiring userspace memory for plane %d\n",
11877952be9bSHans Verkuil 				plane);
11887952be9bSHans Verkuil 			ret = PTR_ERR(mem_priv);
11897952be9bSHans Verkuil 			goto err;
11907952be9bSHans Verkuil 		}
11917952be9bSHans Verkuil 		vb->planes[plane].mem_priv = mem_priv;
11927952be9bSHans Verkuil 	}
11937952be9bSHans Verkuil 
11947952be9bSHans Verkuil 	/*
11957952be9bSHans Verkuil 	 * Now that everything is in order, copy relevant information
11967952be9bSHans Verkuil 	 * provided by userspace.
11977952be9bSHans Verkuil 	 */
11987952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
11997952be9bSHans Verkuil 		vb->planes[plane].bytesused = planes[plane].bytesused;
12007952be9bSHans Verkuil 		vb->planes[plane].length = planes[plane].length;
12017952be9bSHans Verkuil 		vb->planes[plane].m.userptr = planes[plane].m.userptr;
12027952be9bSHans Verkuil 		vb->planes[plane].data_offset = planes[plane].data_offset;
12037952be9bSHans Verkuil 	}
12047952be9bSHans Verkuil 
12057952be9bSHans Verkuil 	if (reacquired) {
12067952be9bSHans Verkuil 		/*
12077952be9bSHans Verkuil 		 * One or more planes changed, so we must call buf_init to do
12087952be9bSHans Verkuil 		 * the driver-specific initialization on the newly acquired
12097952be9bSHans Verkuil 		 * buffer, if provided.
12107952be9bSHans Verkuil 		 */
12117952be9bSHans Verkuil 		ret = call_vb_qop(vb, buf_init, vb);
12127952be9bSHans Verkuil 		if (ret) {
1213b820935bSLaurent Pinchart 			dprintk(q, 1, "buffer initialization failed\n");
12147952be9bSHans Verkuil 			goto err;
12157952be9bSHans Verkuil 		}
12167952be9bSHans Verkuil 	}
12177952be9bSHans Verkuil 
12187952be9bSHans Verkuil 	ret = call_vb_qop(vb, buf_prepare, vb);
12197952be9bSHans Verkuil 	if (ret) {
1220b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer preparation failed\n");
12217952be9bSHans Verkuil 		call_void_vb_qop(vb, buf_cleanup, vb);
12227952be9bSHans Verkuil 		goto err;
12237952be9bSHans Verkuil 	}
12247952be9bSHans Verkuil 
12257952be9bSHans Verkuil 	return 0;
12267952be9bSHans Verkuil err:
12277952be9bSHans Verkuil 	/* In case of errors, release planes that were already acquired */
12287952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
12297952be9bSHans Verkuil 		if (vb->planes[plane].mem_priv)
12307952be9bSHans Verkuil 			call_void_memop(vb, put_userptr,
12317952be9bSHans Verkuil 				vb->planes[plane].mem_priv);
12327952be9bSHans Verkuil 		vb->planes[plane].mem_priv = NULL;
12337952be9bSHans Verkuil 		vb->planes[plane].m.userptr = 0;
12347952be9bSHans Verkuil 		vb->planes[plane].length = 0;
12357952be9bSHans Verkuil 	}
12367952be9bSHans Verkuil 
12377952be9bSHans Verkuil 	return ret;
12387952be9bSHans Verkuil }
12397952be9bSHans Verkuil 
12407952be9bSHans Verkuil /*
12417952be9bSHans Verkuil  * __prepare_dmabuf() - prepare a DMABUF buffer
12427952be9bSHans Verkuil  */
__prepare_dmabuf(struct vb2_buffer * vb)1243db6e8d57SHans Verkuil static int __prepare_dmabuf(struct vb2_buffer *vb)
12447952be9bSHans Verkuil {
12457952be9bSHans Verkuil 	struct vb2_plane planes[VB2_MAX_PLANES];
12467952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
12477952be9bSHans Verkuil 	void *mem_priv;
12487952be9bSHans Verkuil 	unsigned int plane;
12497952be9bSHans Verkuil 	int ret = 0;
12507952be9bSHans Verkuil 	bool reacquired = vb->planes[0].mem_priv == NULL;
12517952be9bSHans Verkuil 
12527952be9bSHans Verkuil 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
12537952be9bSHans Verkuil 	/* Copy relevant information provided by the userspace */
12547952be9bSHans Verkuil 	ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1255db6e8d57SHans Verkuil 			 vb, planes);
12567952be9bSHans Verkuil 	if (ret)
12577952be9bSHans Verkuil 		return ret;
12587952be9bSHans Verkuil 
12597952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
12607952be9bSHans Verkuil 		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
12617952be9bSHans Verkuil 
12627952be9bSHans Verkuil 		if (IS_ERR_OR_NULL(dbuf)) {
1263b820935bSLaurent Pinchart 			dprintk(q, 1, "invalid dmabuf fd for plane %d\n",
12647952be9bSHans Verkuil 				plane);
12657952be9bSHans Verkuil 			ret = -EINVAL;
12667952be9bSHans Verkuil 			goto err;
12677952be9bSHans Verkuil 		}
12687952be9bSHans Verkuil 
12697952be9bSHans Verkuil 		/* use DMABUF size if length is not provided */
12707952be9bSHans Verkuil 		if (planes[plane].length == 0)
12717952be9bSHans Verkuil 			planes[plane].length = dbuf->size;
12727952be9bSHans Verkuil 
12737952be9bSHans Verkuil 		if (planes[plane].length < vb->planes[plane].min_length) {
1274b820935bSLaurent Pinchart 			dprintk(q, 1, "invalid dmabuf length %u for plane %d, minimum length %u\n",
12757952be9bSHans Verkuil 				planes[plane].length, plane,
12767952be9bSHans Verkuil 				vb->planes[plane].min_length);
12777952be9bSHans Verkuil 			dma_buf_put(dbuf);
12787952be9bSHans Verkuil 			ret = -EINVAL;
12797952be9bSHans Verkuil 			goto err;
12807952be9bSHans Verkuil 		}
12817952be9bSHans Verkuil 
12827952be9bSHans Verkuil 		/* Skip the plane if already verified */
12837952be9bSHans Verkuil 		if (dbuf == vb->planes[plane].dbuf &&
12847952be9bSHans Verkuil 			vb->planes[plane].length == planes[plane].length) {
12857952be9bSHans Verkuil 			dma_buf_put(dbuf);
12867952be9bSHans Verkuil 			continue;
12877952be9bSHans Verkuil 		}
12887952be9bSHans Verkuil 
1289b820935bSLaurent Pinchart 		dprintk(q, 3, "buffer for plane %d changed\n", plane);
12907952be9bSHans Verkuil 
12917952be9bSHans Verkuil 		if (!reacquired) {
12927952be9bSHans Verkuil 			reacquired = true;
12937e4e7162SHans Verkuil 			vb->copied_timestamp = 0;
12947952be9bSHans Verkuil 			call_void_vb_qop(vb, buf_cleanup, vb);
12957952be9bSHans Verkuil 		}
12967952be9bSHans Verkuil 
12977952be9bSHans Verkuil 		/* Release previously acquired memory if present */
12987952be9bSHans Verkuil 		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
12997952be9bSHans Verkuil 		vb->planes[plane].bytesused = 0;
13007952be9bSHans Verkuil 		vb->planes[plane].length = 0;
13017952be9bSHans Verkuil 		vb->planes[plane].m.fd = 0;
13027952be9bSHans Verkuil 		vb->planes[plane].data_offset = 0;
13037952be9bSHans Verkuil 
13047952be9bSHans Verkuil 		/* Acquire each plane's memory */
1305a4b83debSSergey Senozhatsky 		mem_priv = call_ptr_memop(attach_dmabuf,
1306a4b83debSSergey Senozhatsky 					  vb,
13077952be9bSHans Verkuil 					  q->alloc_devs[plane] ? : q->dev,
1308a4b83debSSergey Senozhatsky 					  dbuf,
1309a4b83debSSergey Senozhatsky 					  planes[plane].length);
13107952be9bSHans Verkuil 		if (IS_ERR(mem_priv)) {
1311b820935bSLaurent Pinchart 			dprintk(q, 1, "failed to attach dmabuf\n");
13127952be9bSHans Verkuil 			ret = PTR_ERR(mem_priv);
13137952be9bSHans Verkuil 			dma_buf_put(dbuf);
13147952be9bSHans Verkuil 			goto err;
13157952be9bSHans Verkuil 		}
13167952be9bSHans Verkuil 
13177952be9bSHans Verkuil 		vb->planes[plane].dbuf = dbuf;
13187952be9bSHans Verkuil 		vb->planes[plane].mem_priv = mem_priv;
13197952be9bSHans Verkuil 	}
13207952be9bSHans Verkuil 
13217952be9bSHans Verkuil 	/*
13227952be9bSHans Verkuil 	 * This pins the buffer(s) with dma_buf_map_attachment()). It's done
13237952be9bSHans Verkuil 	 * here instead just before the DMA, while queueing the buffer(s) so
13247952be9bSHans Verkuil 	 * userspace knows sooner rather than later if the dma-buf map fails.
13257952be9bSHans Verkuil 	 */
13267952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
13272cc1802fSPawel Osciak 		if (vb->planes[plane].dbuf_mapped)
13282cc1802fSPawel Osciak 			continue;
13292cc1802fSPawel Osciak 
13307952be9bSHans Verkuil 		ret = call_memop(vb, map_dmabuf, vb->planes[plane].mem_priv);
13317952be9bSHans Verkuil 		if (ret) {
1332b820935bSLaurent Pinchart 			dprintk(q, 1, "failed to map dmabuf for plane %d\n",
13337952be9bSHans Verkuil 				plane);
13347952be9bSHans Verkuil 			goto err;
13357952be9bSHans Verkuil 		}
13367952be9bSHans Verkuil 		vb->planes[plane].dbuf_mapped = 1;
13377952be9bSHans Verkuil 	}
13387952be9bSHans Verkuil 
13397952be9bSHans Verkuil 	/*
13407952be9bSHans Verkuil 	 * Now that everything is in order, copy relevant information
13417952be9bSHans Verkuil 	 * provided by userspace.
13427952be9bSHans Verkuil 	 */
13437952be9bSHans Verkuil 	for (plane = 0; plane < vb->num_planes; ++plane) {
13447952be9bSHans Verkuil 		vb->planes[plane].bytesused = planes[plane].bytesused;
13457952be9bSHans Verkuil 		vb->planes[plane].length = planes[plane].length;
13467952be9bSHans Verkuil 		vb->planes[plane].m.fd = planes[plane].m.fd;
13477952be9bSHans Verkuil 		vb->planes[plane].data_offset = planes[plane].data_offset;
13487952be9bSHans Verkuil 	}
13497952be9bSHans Verkuil 
13507952be9bSHans Verkuil 	if (reacquired) {
13517952be9bSHans Verkuil 		/*
13527952be9bSHans Verkuil 		 * Call driver-specific initialization on the newly acquired buffer,
13537952be9bSHans Verkuil 		 * if provided.
13547952be9bSHans Verkuil 		 */
13557952be9bSHans Verkuil 		ret = call_vb_qop(vb, buf_init, vb);
13567952be9bSHans Verkuil 		if (ret) {
1357b820935bSLaurent Pinchart 			dprintk(q, 1, "buffer initialization failed\n");
13587952be9bSHans Verkuil 			goto err;
13597952be9bSHans Verkuil 		}
13607952be9bSHans Verkuil 	}
13617952be9bSHans Verkuil 
13627952be9bSHans Verkuil 	ret = call_vb_qop(vb, buf_prepare, vb);
13637952be9bSHans Verkuil 	if (ret) {
1364b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer preparation failed\n");
13657952be9bSHans Verkuil 		call_void_vb_qop(vb, buf_cleanup, vb);
13667952be9bSHans Verkuil 		goto err;
13677952be9bSHans Verkuil 	}
13687952be9bSHans Verkuil 
13697952be9bSHans Verkuil 	return 0;
13707952be9bSHans Verkuil err:
13717952be9bSHans Verkuil 	/* In case of errors, release planes that were already acquired */
13727952be9bSHans Verkuil 	__vb2_buf_dmabuf_put(vb);
13737952be9bSHans Verkuil 
13747952be9bSHans Verkuil 	return ret;
13757952be9bSHans Verkuil }
13767952be9bSHans Verkuil 
13777952be9bSHans Verkuil /*
13787952be9bSHans Verkuil  * __enqueue_in_driver() - enqueue a vb2_buffer in driver for processing
13797952be9bSHans Verkuil  */
__enqueue_in_driver(struct vb2_buffer * vb)13807952be9bSHans Verkuil static void __enqueue_in_driver(struct vb2_buffer *vb)
13817952be9bSHans Verkuil {
13827952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
13837952be9bSHans Verkuil 
13847952be9bSHans Verkuil 	vb->state = VB2_BUF_STATE_ACTIVE;
13857952be9bSHans Verkuil 	atomic_inc(&q->owned_by_drv_count);
13867952be9bSHans Verkuil 
13877952be9bSHans Verkuil 	trace_vb2_buf_queue(q, vb);
13887952be9bSHans Verkuil 
13897952be9bSHans Verkuil 	call_void_vb_qop(vb, buf_queue, vb);
13907952be9bSHans Verkuil }
13917952be9bSHans Verkuil 
__buf_prepare(struct vb2_buffer * vb)1392db6e8d57SHans Verkuil static int __buf_prepare(struct vb2_buffer *vb)
13937952be9bSHans Verkuil {
13947952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
139555028695SHans Verkuil 	enum vb2_buffer_state orig_state = vb->state;
13967952be9bSHans Verkuil 	int ret;
13977952be9bSHans Verkuil 
13987952be9bSHans Verkuil 	if (q->error) {
1399b820935bSLaurent Pinchart 		dprintk(q, 1, "fatal error occurred on queue\n");
14007952be9bSHans Verkuil 		return -EIO;
14017952be9bSHans Verkuil 	}
14027952be9bSHans Verkuil 
140355028695SHans Verkuil 	if (vb->prepared)
140455028695SHans Verkuil 		return 0;
140555028695SHans Verkuil 	WARN_ON(vb->synced);
140655028695SHans Verkuil 
140728d77c21SHans Verkuil 	if (q->is_output) {
140828d77c21SHans Verkuil 		ret = call_vb_qop(vb, buf_out_validate, vb);
140928d77c21SHans Verkuil 		if (ret) {
1410b820935bSLaurent Pinchart 			dprintk(q, 1, "buffer validation failed\n");
141128d77c21SHans Verkuil 			return ret;
141228d77c21SHans Verkuil 		}
141328d77c21SHans Verkuil 	}
141428d77c21SHans Verkuil 
14157952be9bSHans Verkuil 	vb->state = VB2_BUF_STATE_PREPARING;
14167952be9bSHans Verkuil 
14177952be9bSHans Verkuil 	switch (q->memory) {
14187952be9bSHans Verkuil 	case VB2_MEMORY_MMAP:
1419db6e8d57SHans Verkuil 		ret = __prepare_mmap(vb);
14207952be9bSHans Verkuil 		break;
14217952be9bSHans Verkuil 	case VB2_MEMORY_USERPTR:
1422db6e8d57SHans Verkuil 		ret = __prepare_userptr(vb);
14237952be9bSHans Verkuil 		break;
14247952be9bSHans Verkuil 	case VB2_MEMORY_DMABUF:
1425db6e8d57SHans Verkuil 		ret = __prepare_dmabuf(vb);
14267952be9bSHans Verkuil 		break;
14277952be9bSHans Verkuil 	default:
14287952be9bSHans Verkuil 		WARN(1, "Invalid queue type\n");
14297952be9bSHans Verkuil 		ret = -EINVAL;
143055028695SHans Verkuil 		break;
14317952be9bSHans Verkuil 	}
14327952be9bSHans Verkuil 
14337952be9bSHans Verkuil 	if (ret) {
1434b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer preparation failed: %d\n", ret);
143555028695SHans Verkuil 		vb->state = orig_state;
14367952be9bSHans Verkuil 		return ret;
14377952be9bSHans Verkuil 	}
14387952be9bSHans Verkuil 
143938a417e8SSergey Senozhatsky 	__vb2_buf_mem_prepare(vb);
1440cfc77408SHans Verkuil 	vb->prepared = 1;
144155028695SHans Verkuil 	vb->state = orig_state;
14427952be9bSHans Verkuil 
14437952be9bSHans Verkuil 	return 0;
14447952be9bSHans Verkuil }
14457952be9bSHans Verkuil 
vb2_req_prepare(struct media_request_object * obj)1446fd89e0bbSHans Verkuil static int vb2_req_prepare(struct media_request_object *obj)
1447fd89e0bbSHans Verkuil {
1448fd89e0bbSHans Verkuil 	struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
1449fd89e0bbSHans Verkuil 	int ret;
1450fd89e0bbSHans Verkuil 
1451fd89e0bbSHans Verkuil 	if (WARN_ON(vb->state != VB2_BUF_STATE_IN_REQUEST))
1452fd89e0bbSHans Verkuil 		return -EINVAL;
1453fd89e0bbSHans Verkuil 
1454fd89e0bbSHans Verkuil 	mutex_lock(vb->vb2_queue->lock);
1455fd89e0bbSHans Verkuil 	ret = __buf_prepare(vb);
1456fd89e0bbSHans Verkuil 	mutex_unlock(vb->vb2_queue->lock);
1457fd89e0bbSHans Verkuil 	return ret;
1458fd89e0bbSHans Verkuil }
1459fd89e0bbSHans Verkuil 
1460fd89e0bbSHans Verkuil static void __vb2_dqbuf(struct vb2_buffer *vb);
1461fd89e0bbSHans Verkuil 
vb2_req_unprepare(struct media_request_object * obj)1462fd89e0bbSHans Verkuil static void vb2_req_unprepare(struct media_request_object *obj)
1463fd89e0bbSHans Verkuil {
1464fd89e0bbSHans Verkuil 	struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
1465fd89e0bbSHans Verkuil 
1466fd89e0bbSHans Verkuil 	mutex_lock(vb->vb2_queue->lock);
1467fd89e0bbSHans Verkuil 	__vb2_dqbuf(vb);
1468fd89e0bbSHans Verkuil 	vb->state = VB2_BUF_STATE_IN_REQUEST;
1469fd89e0bbSHans Verkuil 	mutex_unlock(vb->vb2_queue->lock);
1470fd89e0bbSHans Verkuil 	WARN_ON(!vb->req_obj.req);
1471fd89e0bbSHans Verkuil }
1472fd89e0bbSHans Verkuil 
1473fd89e0bbSHans Verkuil int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
1474fd89e0bbSHans Verkuil 		  struct media_request *req);
1475fd89e0bbSHans Verkuil 
vb2_req_queue(struct media_request_object * obj)1476fd89e0bbSHans Verkuil static void vb2_req_queue(struct media_request_object *obj)
1477fd89e0bbSHans Verkuil {
1478fd89e0bbSHans Verkuil 	struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
14799015fcc2SHans Verkuil 	int err;
1480fd89e0bbSHans Verkuil 
1481fd89e0bbSHans Verkuil 	mutex_lock(vb->vb2_queue->lock);
14829015fcc2SHans Verkuil 	/*
14839015fcc2SHans Verkuil 	 * There is no method to propagate an error from vb2_core_qbuf(),
14849015fcc2SHans Verkuil 	 * so if this returns a non-0 value, then WARN.
14859015fcc2SHans Verkuil 	 *
14869015fcc2SHans Verkuil 	 * The only exception is -EIO which is returned if q->error is
14879015fcc2SHans Verkuil 	 * set. We just ignore that, and expect this will be caught the
14889015fcc2SHans Verkuil 	 * next time vb2_req_prepare() is called.
14899015fcc2SHans Verkuil 	 */
14909015fcc2SHans Verkuil 	err = vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL);
14919015fcc2SHans Verkuil 	WARN_ON_ONCE(err && err != -EIO);
1492fd89e0bbSHans Verkuil 	mutex_unlock(vb->vb2_queue->lock);
1493fd89e0bbSHans Verkuil }
1494fd89e0bbSHans Verkuil 
vb2_req_unbind(struct media_request_object * obj)1495394dc588SHans Verkuil static void vb2_req_unbind(struct media_request_object *obj)
1496394dc588SHans Verkuil {
1497394dc588SHans Verkuil 	struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
1498394dc588SHans Verkuil 
1499394dc588SHans Verkuil 	if (vb->state == VB2_BUF_STATE_IN_REQUEST)
1500394dc588SHans Verkuil 		call_void_bufop(vb->vb2_queue, init_buffer, vb);
1501394dc588SHans Verkuil }
1502394dc588SHans Verkuil 
vb2_req_release(struct media_request_object * obj)1503fd89e0bbSHans Verkuil static void vb2_req_release(struct media_request_object *obj)
1504fd89e0bbSHans Verkuil {
1505fd89e0bbSHans Verkuil 	struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
1506fd89e0bbSHans Verkuil 
15076093d300SHans Verkuil 	if (vb->state == VB2_BUF_STATE_IN_REQUEST) {
1508fd89e0bbSHans Verkuil 		vb->state = VB2_BUF_STATE_DEQUEUED;
15096093d300SHans Verkuil 		if (vb->request)
15106093d300SHans Verkuil 			media_request_put(vb->request);
15116093d300SHans Verkuil 		vb->request = NULL;
15126093d300SHans Verkuil 	}
1513fd89e0bbSHans Verkuil }
1514fd89e0bbSHans Verkuil 
1515fd89e0bbSHans Verkuil static const struct media_request_object_ops vb2_core_req_ops = {
1516fd89e0bbSHans Verkuil 	.prepare = vb2_req_prepare,
1517fd89e0bbSHans Verkuil 	.unprepare = vb2_req_unprepare,
1518fd89e0bbSHans Verkuil 	.queue = vb2_req_queue,
1519394dc588SHans Verkuil 	.unbind = vb2_req_unbind,
1520fd89e0bbSHans Verkuil 	.release = vb2_req_release,
1521fd89e0bbSHans Verkuil };
1522fd89e0bbSHans Verkuil 
vb2_request_object_is_buffer(struct media_request_object * obj)1523c07aa48eSHans Verkuil bool vb2_request_object_is_buffer(struct media_request_object *obj)
1524c07aa48eSHans Verkuil {
1525c07aa48eSHans Verkuil 	return obj->ops == &vb2_core_req_ops;
1526c07aa48eSHans Verkuil }
1527c07aa48eSHans Verkuil EXPORT_SYMBOL_GPL(vb2_request_object_is_buffer);
1528c07aa48eSHans Verkuil 
vb2_request_buffer_cnt(struct media_request * req)1529515c5a73SPaul Kocialkowski unsigned int vb2_request_buffer_cnt(struct media_request *req)
1530c07aa48eSHans Verkuil {
1531c07aa48eSHans Verkuil 	struct media_request_object *obj;
1532c07aa48eSHans Verkuil 	unsigned long flags;
1533515c5a73SPaul Kocialkowski 	unsigned int buffer_cnt = 0;
1534c07aa48eSHans Verkuil 
1535c07aa48eSHans Verkuil 	spin_lock_irqsave(&req->lock, flags);
1536515c5a73SPaul Kocialkowski 	list_for_each_entry(obj, &req->objects, list)
1537515c5a73SPaul Kocialkowski 		if (vb2_request_object_is_buffer(obj))
1538515c5a73SPaul Kocialkowski 			buffer_cnt++;
1539c07aa48eSHans Verkuil 	spin_unlock_irqrestore(&req->lock, flags);
1540515c5a73SPaul Kocialkowski 
1541515c5a73SPaul Kocialkowski 	return buffer_cnt;
1542c07aa48eSHans Verkuil }
1543515c5a73SPaul Kocialkowski EXPORT_SYMBOL_GPL(vb2_request_buffer_cnt);
1544c07aa48eSHans Verkuil 
vb2_core_prepare_buf(struct vb2_queue * q,unsigned int index,void * pb)15457952be9bSHans Verkuil int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
15467952be9bSHans Verkuil {
15477952be9bSHans Verkuil 	struct vb2_buffer *vb;
15487952be9bSHans Verkuil 	int ret;
15497952be9bSHans Verkuil 
15507952be9bSHans Verkuil 	vb = q->bufs[index];
15517952be9bSHans Verkuil 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
1552c89ee8edSEzequiel Garcia 		dprintk(q, 1, "invalid buffer state %s\n",
1553c89ee8edSEzequiel Garcia 			vb2_state_name(vb->state));
15547952be9bSHans Verkuil 		return -EINVAL;
15557952be9bSHans Verkuil 	}
155655028695SHans Verkuil 	if (vb->prepared) {
1557b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer already prepared\n");
155855028695SHans Verkuil 		return -EINVAL;
155955028695SHans Verkuil 	}
15607952be9bSHans Verkuil 
1561db6e8d57SHans Verkuil 	ret = __buf_prepare(vb);
15627952be9bSHans Verkuil 	if (ret)
15637952be9bSHans Verkuil 		return ret;
15647952be9bSHans Verkuil 
15657952be9bSHans Verkuil 	/* Fill buffer information for the userspace */
15667952be9bSHans Verkuil 	call_void_bufop(q, fill_user_buffer, vb, pb);
15677952be9bSHans Verkuil 
1568b820935bSLaurent Pinchart 	dprintk(q, 2, "prepare of buffer %d succeeded\n", vb->index);
15697952be9bSHans Verkuil 
1570fd89e0bbSHans Verkuil 	return 0;
15717952be9bSHans Verkuil }
15727952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
15737952be9bSHans Verkuil 
15747952be9bSHans Verkuil /*
15757952be9bSHans Verkuil  * vb2_start_streaming() - Attempt to start streaming.
15767952be9bSHans Verkuil  * @q:		videobuf2 queue
15777952be9bSHans Verkuil  *
15787952be9bSHans Verkuil  * Attempt to start streaming. When this function is called there must be
15797952be9bSHans Verkuil  * at least q->min_buffers_needed buffers queued up (i.e. the minimum
15807952be9bSHans Verkuil  * number of buffers required for the DMA engine to function). If the
15817952be9bSHans Verkuil  * @start_streaming op fails it is supposed to return all the driver-owned
15827952be9bSHans Verkuil  * buffers back to vb2 in state QUEUED. Check if that happened and if
15837952be9bSHans Verkuil  * not warn and reclaim them forcefully.
15847952be9bSHans Verkuil  */
vb2_start_streaming(struct vb2_queue * q)15857952be9bSHans Verkuil static int vb2_start_streaming(struct vb2_queue *q)
15867952be9bSHans Verkuil {
15877952be9bSHans Verkuil 	struct vb2_buffer *vb;
15887952be9bSHans Verkuil 	int ret;
15897952be9bSHans Verkuil 
15907952be9bSHans Verkuil 	/*
15917952be9bSHans Verkuil 	 * If any buffers were queued before streamon,
15927952be9bSHans Verkuil 	 * we can now pass them to driver for processing.
15937952be9bSHans Verkuil 	 */
15947952be9bSHans Verkuil 	list_for_each_entry(vb, &q->queued_list, queued_entry)
15957952be9bSHans Verkuil 		__enqueue_in_driver(vb);
15967952be9bSHans Verkuil 
15977952be9bSHans Verkuil 	/* Tell the driver to start streaming */
15987952be9bSHans Verkuil 	q->start_streaming_called = 1;
15997952be9bSHans Verkuil 	ret = call_qop(q, start_streaming, q,
16007952be9bSHans Verkuil 		       atomic_read(&q->owned_by_drv_count));
16017952be9bSHans Verkuil 	if (!ret)
16027952be9bSHans Verkuil 		return 0;
16037952be9bSHans Verkuil 
16047952be9bSHans Verkuil 	q->start_streaming_called = 0;
16057952be9bSHans Verkuil 
1606b820935bSLaurent Pinchart 	dprintk(q, 1, "driver refused to start streaming\n");
16077952be9bSHans Verkuil 	/*
16087952be9bSHans Verkuil 	 * If you see this warning, then the driver isn't cleaning up properly
16097952be9bSHans Verkuil 	 * after a failed start_streaming(). See the start_streaming()
16107952be9bSHans Verkuil 	 * documentation in videobuf2-core.h for more information how buffers
16117952be9bSHans Verkuil 	 * should be returned to vb2 in start_streaming().
16127952be9bSHans Verkuil 	 */
16137952be9bSHans Verkuil 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
16147952be9bSHans Verkuil 		unsigned i;
16157952be9bSHans Verkuil 
16167952be9bSHans Verkuil 		/*
16177952be9bSHans Verkuil 		 * Forcefully reclaim buffers if the driver did not
16187952be9bSHans Verkuil 		 * correctly return them to vb2.
16197952be9bSHans Verkuil 		 */
16207952be9bSHans Verkuil 		for (i = 0; i < q->num_buffers; ++i) {
16217952be9bSHans Verkuil 			vb = q->bufs[i];
16227952be9bSHans Verkuil 			if (vb->state == VB2_BUF_STATE_ACTIVE)
16237952be9bSHans Verkuil 				vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
16247952be9bSHans Verkuil 		}
16257952be9bSHans Verkuil 		/* Must be zero now */
16267952be9bSHans Verkuil 		WARN_ON(atomic_read(&q->owned_by_drv_count));
16277952be9bSHans Verkuil 	}
16287952be9bSHans Verkuil 	/*
16297952be9bSHans Verkuil 	 * If done_list is not empty, then start_streaming() didn't call
16307952be9bSHans Verkuil 	 * vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED) but STATE_ERROR or
16317952be9bSHans Verkuil 	 * STATE_DONE.
16327952be9bSHans Verkuil 	 */
16337952be9bSHans Verkuil 	WARN_ON(!list_empty(&q->done_list));
16347952be9bSHans Verkuil 	return ret;
16357952be9bSHans Verkuil }
16367952be9bSHans Verkuil 
vb2_core_qbuf(struct vb2_queue * q,unsigned int index,void * pb,struct media_request * req)1637fd89e0bbSHans Verkuil int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
1638fd89e0bbSHans Verkuil 		  struct media_request *req)
16397952be9bSHans Verkuil {
16407952be9bSHans Verkuil 	struct vb2_buffer *vb;
1641c592b469SHans Verkuil 	enum vb2_buffer_state orig_state;
16427952be9bSHans Verkuil 	int ret;
16437952be9bSHans Verkuil 
1644b509d733SHans Verkuil 	if (q->error) {
1645b820935bSLaurent Pinchart 		dprintk(q, 1, "fatal error occurred on queue\n");
1646b509d733SHans Verkuil 		return -EIO;
1647b509d733SHans Verkuil 	}
1648b509d733SHans Verkuil 
16497952be9bSHans Verkuil 	vb = q->bufs[index];
16507952be9bSHans Verkuil 
165190675d39SHans Verkuil 	if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
165290675d39SHans Verkuil 	    q->requires_requests) {
1653b820935bSLaurent Pinchart 		dprintk(q, 1, "qbuf requires a request\n");
165490675d39SHans Verkuil 		return -EBADR;
165590675d39SHans Verkuil 	}
165690675d39SHans Verkuil 
165761add367SHans Verkuil 	if ((req && q->uses_qbuf) ||
165861add367SHans Verkuil 	    (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
165961add367SHans Verkuil 	     q->uses_requests)) {
1660b820935bSLaurent Pinchart 		dprintk(q, 1, "queue in wrong mode (qbuf vs requests)\n");
166115cd442eSHans Verkuil 		return -EBUSY;
166261add367SHans Verkuil 	}
166361add367SHans Verkuil 
1664fd89e0bbSHans Verkuil 	if (req) {
1665fd89e0bbSHans Verkuil 		int ret;
1666fd89e0bbSHans Verkuil 
166761add367SHans Verkuil 		q->uses_requests = 1;
1668fd89e0bbSHans Verkuil 		if (vb->state != VB2_BUF_STATE_DEQUEUED) {
1669b820935bSLaurent Pinchart 			dprintk(q, 1, "buffer %d not in dequeued state\n",
1670fd89e0bbSHans Verkuil 				vb->index);
1671fd89e0bbSHans Verkuil 			return -EINVAL;
1672fd89e0bbSHans Verkuil 		}
1673fd89e0bbSHans Verkuil 
167428d77c21SHans Verkuil 		if (q->is_output && !vb->prepared) {
167528d77c21SHans Verkuil 			ret = call_vb_qop(vb, buf_out_validate, vb);
167628d77c21SHans Verkuil 			if (ret) {
1677b820935bSLaurent Pinchart 				dprintk(q, 1, "buffer validation failed\n");
167828d77c21SHans Verkuil 				return ret;
167928d77c21SHans Verkuil 			}
168028d77c21SHans Verkuil 		}
168128d77c21SHans Verkuil 
1682fd89e0bbSHans Verkuil 		media_request_object_init(&vb->req_obj);
1683fd89e0bbSHans Verkuil 
1684fd89e0bbSHans Verkuil 		/* Make sure the request is in a safe state for updating. */
1685fd89e0bbSHans Verkuil 		ret = media_request_lock_for_update(req);
16867952be9bSHans Verkuil 		if (ret)
16877952be9bSHans Verkuil 			return ret;
1688fd89e0bbSHans Verkuil 		ret = media_request_object_bind(req, &vb2_core_req_ops,
1689fd89e0bbSHans Verkuil 						q, true, &vb->req_obj);
1690fd89e0bbSHans Verkuil 		media_request_unlock_for_update(req);
1691fd89e0bbSHans Verkuil 		if (ret)
1692fd89e0bbSHans Verkuil 			return ret;
1693fd89e0bbSHans Verkuil 
1694fd89e0bbSHans Verkuil 		vb->state = VB2_BUF_STATE_IN_REQUEST;
16956093d300SHans Verkuil 
16966093d300SHans Verkuil 		/*
16976093d300SHans Verkuil 		 * Increment the refcount and store the request.
16986093d300SHans Verkuil 		 * The request refcount is decremented again when the
16996093d300SHans Verkuil 		 * buffer is dequeued. This is to prevent vb2_buffer_done()
17006093d300SHans Verkuil 		 * from freeing the request from interrupt context, which can
17016093d300SHans Verkuil 		 * happen if the application closed the request fd after
17026093d300SHans Verkuil 		 * queueing the request.
17036093d300SHans Verkuil 		 */
17046093d300SHans Verkuil 		media_request_get(req);
17056093d300SHans Verkuil 		vb->request = req;
17066093d300SHans Verkuil 
1707fd89e0bbSHans Verkuil 		/* Fill buffer information for the userspace */
1708394dc588SHans Verkuil 		if (pb) {
1709394dc588SHans Verkuil 			call_void_bufop(q, copy_timestamp, vb, pb);
1710fd89e0bbSHans Verkuil 			call_void_bufop(q, fill_user_buffer, vb, pb);
1711394dc588SHans Verkuil 		}
1712fd89e0bbSHans Verkuil 
1713b820935bSLaurent Pinchart 		dprintk(q, 2, "qbuf of buffer %d succeeded\n", vb->index);
1714fd89e0bbSHans Verkuil 		return 0;
1715fd89e0bbSHans Verkuil 	}
1716fd89e0bbSHans Verkuil 
171761add367SHans Verkuil 	if (vb->state != VB2_BUF_STATE_IN_REQUEST)
171861add367SHans Verkuil 		q->uses_qbuf = 1;
171961add367SHans Verkuil 
17207952be9bSHans Verkuil 	switch (vb->state) {
17217952be9bSHans Verkuil 	case VB2_BUF_STATE_DEQUEUED:
1722fd89e0bbSHans Verkuil 	case VB2_BUF_STATE_IN_REQUEST:
172355028695SHans Verkuil 		if (!vb->prepared) {
1724db6e8d57SHans Verkuil 			ret = __buf_prepare(vb);
17257952be9bSHans Verkuil 			if (ret)
17267952be9bSHans Verkuil 				return ret;
172755028695SHans Verkuil 		}
17287952be9bSHans Verkuil 		break;
17297952be9bSHans Verkuil 	case VB2_BUF_STATE_PREPARING:
1730b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer still being prepared\n");
17317952be9bSHans Verkuil 		return -EINVAL;
17327952be9bSHans Verkuil 	default:
1733c89ee8edSEzequiel Garcia 		dprintk(q, 1, "invalid buffer state %s\n",
1734c89ee8edSEzequiel Garcia 			vb2_state_name(vb->state));
17357952be9bSHans Verkuil 		return -EINVAL;
17367952be9bSHans Verkuil 	}
17377952be9bSHans Verkuil 
17387952be9bSHans Verkuil 	/*
17397952be9bSHans Verkuil 	 * Add to the queued buffers list, a buffer will stay on it until
17407952be9bSHans Verkuil 	 * dequeued in dqbuf.
17417952be9bSHans Verkuil 	 */
1742c592b469SHans Verkuil 	orig_state = vb->state;
17437952be9bSHans Verkuil 	list_add_tail(&vb->queued_entry, &q->queued_list);
17447952be9bSHans Verkuil 	q->queued_count++;
17457952be9bSHans Verkuil 	q->waiting_for_buffers = false;
17467952be9bSHans Verkuil 	vb->state = VB2_BUF_STATE_QUEUED;
17477952be9bSHans Verkuil 
17487952be9bSHans Verkuil 	if (pb)
17497952be9bSHans Verkuil 		call_void_bufop(q, copy_timestamp, vb, pb);
17507952be9bSHans Verkuil 
17517952be9bSHans Verkuil 	trace_vb2_qbuf(q, vb);
17527952be9bSHans Verkuil 
17537952be9bSHans Verkuil 	/*
17547952be9bSHans Verkuil 	 * If already streaming, give the buffer to driver for processing.
17557952be9bSHans Verkuil 	 * If not, the buffer will be given to driver on next streamon.
17567952be9bSHans Verkuil 	 */
17577952be9bSHans Verkuil 	if (q->start_streaming_called)
17587952be9bSHans Verkuil 		__enqueue_in_driver(vb);
17597952be9bSHans Verkuil 
17607952be9bSHans Verkuil 	/* Fill buffer information for the userspace */
17617952be9bSHans Verkuil 	if (pb)
17627952be9bSHans Verkuil 		call_void_bufop(q, fill_user_buffer, vb, pb);
17637952be9bSHans Verkuil 
17647952be9bSHans Verkuil 	/*
17657952be9bSHans Verkuil 	 * If streamon has been called, and we haven't yet called
17667952be9bSHans Verkuil 	 * start_streaming() since not enough buffers were queued, and
17677952be9bSHans Verkuil 	 * we now have reached the minimum number of queued buffers,
17687952be9bSHans Verkuil 	 * then we can finally call start_streaming().
17697952be9bSHans Verkuil 	 */
17707952be9bSHans Verkuil 	if (q->streaming && !q->start_streaming_called &&
17717952be9bSHans Verkuil 	    q->queued_count >= q->min_buffers_needed) {
17727952be9bSHans Verkuil 		ret = vb2_start_streaming(q);
1773c592b469SHans Verkuil 		if (ret) {
1774c592b469SHans Verkuil 			/*
1775c592b469SHans Verkuil 			 * Since vb2_core_qbuf will return with an error,
1776c592b469SHans Verkuil 			 * we should return it to state DEQUEUED since
1777c592b469SHans Verkuil 			 * the error indicates that the buffer wasn't queued.
1778c592b469SHans Verkuil 			 */
1779c592b469SHans Verkuil 			list_del(&vb->queued_entry);
1780c592b469SHans Verkuil 			q->queued_count--;
1781c592b469SHans Verkuil 			vb->state = orig_state;
17827952be9bSHans Verkuil 			return ret;
17837952be9bSHans Verkuil 		}
1784c592b469SHans Verkuil 	}
17857952be9bSHans Verkuil 
1786b820935bSLaurent Pinchart 	dprintk(q, 2, "qbuf of buffer %d succeeded\n", vb->index);
17877952be9bSHans Verkuil 	return 0;
17887952be9bSHans Verkuil }
17897952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_qbuf);
17907952be9bSHans Verkuil 
17917952be9bSHans Verkuil /*
17927952be9bSHans Verkuil  * __vb2_wait_for_done_vb() - wait for a buffer to become available
17937952be9bSHans Verkuil  * for dequeuing
17947952be9bSHans Verkuil  *
17957952be9bSHans Verkuil  * Will sleep if required for nonblocking == false.
17967952be9bSHans Verkuil  */
__vb2_wait_for_done_vb(struct vb2_queue * q,int nonblocking)17977952be9bSHans Verkuil static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
17987952be9bSHans Verkuil {
17997952be9bSHans Verkuil 	/*
18007952be9bSHans Verkuil 	 * All operations on vb_done_list are performed under done_lock
18017952be9bSHans Verkuil 	 * spinlock protection. However, buffers may be removed from
18027952be9bSHans Verkuil 	 * it and returned to userspace only while holding both driver's
18037952be9bSHans Verkuil 	 * lock and the done_lock spinlock. Thus we can be sure that as
18047952be9bSHans Verkuil 	 * long as we hold the driver's lock, the list will remain not
18057952be9bSHans Verkuil 	 * empty if list_empty() check succeeds.
18067952be9bSHans Verkuil 	 */
18077952be9bSHans Verkuil 
18087952be9bSHans Verkuil 	for (;;) {
18097952be9bSHans Verkuil 		int ret;
18107952be9bSHans Verkuil 
1811d65842f7SHans Verkuil 		if (q->waiting_in_dqbuf) {
1812b820935bSLaurent Pinchart 			dprintk(q, 1, "another dup()ped fd is waiting for a buffer\n");
1813d65842f7SHans Verkuil 			return -EBUSY;
1814d65842f7SHans Verkuil 		}
1815d65842f7SHans Verkuil 
18167952be9bSHans Verkuil 		if (!q->streaming) {
1817b820935bSLaurent Pinchart 			dprintk(q, 1, "streaming off, will not wait for buffers\n");
18187952be9bSHans Verkuil 			return -EINVAL;
18197952be9bSHans Verkuil 		}
18207952be9bSHans Verkuil 
18217952be9bSHans Verkuil 		if (q->error) {
1822b820935bSLaurent Pinchart 			dprintk(q, 1, "Queue in error state, will not wait for buffers\n");
18237952be9bSHans Verkuil 			return -EIO;
18247952be9bSHans Verkuil 		}
18257952be9bSHans Verkuil 
18267952be9bSHans Verkuil 		if (q->last_buffer_dequeued) {
1827b820935bSLaurent Pinchart 			dprintk(q, 3, "last buffer dequeued already, will not wait for buffers\n");
18287952be9bSHans Verkuil 			return -EPIPE;
18297952be9bSHans Verkuil 		}
18307952be9bSHans Verkuil 
18317952be9bSHans Verkuil 		if (!list_empty(&q->done_list)) {
18327952be9bSHans Verkuil 			/*
18337952be9bSHans Verkuil 			 * Found a buffer that we were waiting for.
18347952be9bSHans Verkuil 			 */
18357952be9bSHans Verkuil 			break;
18367952be9bSHans Verkuil 		}
18377952be9bSHans Verkuil 
18387952be9bSHans Verkuil 		if (nonblocking) {
1839b820935bSLaurent Pinchart 			dprintk(q, 3, "nonblocking and no buffers to dequeue, will not wait\n");
18407952be9bSHans Verkuil 			return -EAGAIN;
18417952be9bSHans Verkuil 		}
18427952be9bSHans Verkuil 
1843d65842f7SHans Verkuil 		q->waiting_in_dqbuf = 1;
18447952be9bSHans Verkuil 		/*
18457952be9bSHans Verkuil 		 * We are streaming and blocking, wait for another buffer to
18467952be9bSHans Verkuil 		 * become ready or for streamoff. Driver's lock is released to
18477952be9bSHans Verkuil 		 * allow streamoff or qbuf to be called while waiting.
18487952be9bSHans Verkuil 		 */
18497952be9bSHans Verkuil 		call_void_qop(q, wait_prepare, q);
18507952be9bSHans Verkuil 
18517952be9bSHans Verkuil 		/*
18527952be9bSHans Verkuil 		 * All locks have been released, it is safe to sleep now.
18537952be9bSHans Verkuil 		 */
1854b820935bSLaurent Pinchart 		dprintk(q, 3, "will sleep waiting for buffers\n");
18557952be9bSHans Verkuil 		ret = wait_event_interruptible(q->done_wq,
18567952be9bSHans Verkuil 				!list_empty(&q->done_list) || !q->streaming ||
18577952be9bSHans Verkuil 				q->error);
18587952be9bSHans Verkuil 
18597952be9bSHans Verkuil 		/*
18607952be9bSHans Verkuil 		 * We need to reevaluate both conditions again after reacquiring
18617952be9bSHans Verkuil 		 * the locks or return an error if one occurred.
18627952be9bSHans Verkuil 		 */
18637952be9bSHans Verkuil 		call_void_qop(q, wait_finish, q);
1864d65842f7SHans Verkuil 		q->waiting_in_dqbuf = 0;
18657952be9bSHans Verkuil 		if (ret) {
1866b820935bSLaurent Pinchart 			dprintk(q, 1, "sleep was interrupted\n");
18677952be9bSHans Verkuil 			return ret;
18687952be9bSHans Verkuil 		}
18697952be9bSHans Verkuil 	}
18707952be9bSHans Verkuil 	return 0;
18717952be9bSHans Verkuil }
18727952be9bSHans Verkuil 
18737952be9bSHans Verkuil /*
18747952be9bSHans Verkuil  * __vb2_get_done_vb() - get a buffer ready for dequeuing
18757952be9bSHans Verkuil  *
18767952be9bSHans Verkuil  * Will sleep if required for nonblocking == false.
18777952be9bSHans Verkuil  */
__vb2_get_done_vb(struct vb2_queue * q,struct vb2_buffer ** vb,void * pb,int nonblocking)18787952be9bSHans Verkuil static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
18797952be9bSHans Verkuil 			     void *pb, int nonblocking)
18807952be9bSHans Verkuil {
18817952be9bSHans Verkuil 	unsigned long flags;
18827952be9bSHans Verkuil 	int ret = 0;
18837952be9bSHans Verkuil 
18847952be9bSHans Verkuil 	/*
18857952be9bSHans Verkuil 	 * Wait for at least one buffer to become available on the done_list.
18867952be9bSHans Verkuil 	 */
18877952be9bSHans Verkuil 	ret = __vb2_wait_for_done_vb(q, nonblocking);
18887952be9bSHans Verkuil 	if (ret)
18897952be9bSHans Verkuil 		return ret;
18907952be9bSHans Verkuil 
18917952be9bSHans Verkuil 	/*
18927952be9bSHans Verkuil 	 * Driver's lock has been held since we last verified that done_list
18937952be9bSHans Verkuil 	 * is not empty, so no need for another list_empty(done_list) check.
18947952be9bSHans Verkuil 	 */
18957952be9bSHans Verkuil 	spin_lock_irqsave(&q->done_lock, flags);
18967952be9bSHans Verkuil 	*vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
18977952be9bSHans Verkuil 	/*
18987952be9bSHans Verkuil 	 * Only remove the buffer from done_list if all planes can be
18997952be9bSHans Verkuil 	 * handled. Some cases such as V4L2 file I/O and DVB have pb
19007952be9bSHans Verkuil 	 * == NULL; skip the check then as there's nothing to verify.
19017952be9bSHans Verkuil 	 */
19027952be9bSHans Verkuil 	if (pb)
19037952be9bSHans Verkuil 		ret = call_bufop(q, verify_planes_array, *vb, pb);
19047952be9bSHans Verkuil 	if (!ret)
19057952be9bSHans Verkuil 		list_del(&(*vb)->done_entry);
19067952be9bSHans Verkuil 	spin_unlock_irqrestore(&q->done_lock, flags);
19077952be9bSHans Verkuil 
19087952be9bSHans Verkuil 	return ret;
19097952be9bSHans Verkuil }
19107952be9bSHans Verkuil 
vb2_wait_for_all_buffers(struct vb2_queue * q)19117952be9bSHans Verkuil int vb2_wait_for_all_buffers(struct vb2_queue *q)
19127952be9bSHans Verkuil {
19137952be9bSHans Verkuil 	if (!q->streaming) {
1914b820935bSLaurent Pinchart 		dprintk(q, 1, "streaming off, will not wait for buffers\n");
19157952be9bSHans Verkuil 		return -EINVAL;
19167952be9bSHans Verkuil 	}
19177952be9bSHans Verkuil 
19187952be9bSHans Verkuil 	if (q->start_streaming_called)
19197952be9bSHans Verkuil 		wait_event(q->done_wq, !atomic_read(&q->owned_by_drv_count));
19207952be9bSHans Verkuil 	return 0;
19217952be9bSHans Verkuil }
19227952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
19237952be9bSHans Verkuil 
19247952be9bSHans Verkuil /*
19257952be9bSHans Verkuil  * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state
19267952be9bSHans Verkuil  */
__vb2_dqbuf(struct vb2_buffer * vb)19277952be9bSHans Verkuil static void __vb2_dqbuf(struct vb2_buffer *vb)
19287952be9bSHans Verkuil {
19297952be9bSHans Verkuil 	struct vb2_queue *q = vb->vb2_queue;
19307952be9bSHans Verkuil 
19317952be9bSHans Verkuil 	/* nothing to do if the buffer is already dequeued */
19327952be9bSHans Verkuil 	if (vb->state == VB2_BUF_STATE_DEQUEUED)
19337952be9bSHans Verkuil 		return;
19347952be9bSHans Verkuil 
19357952be9bSHans Verkuil 	vb->state = VB2_BUF_STATE_DEQUEUED;
19367952be9bSHans Verkuil 
1937fd89e0bbSHans Verkuil 	call_void_bufop(q, init_buffer, vb);
19387952be9bSHans Verkuil }
19397952be9bSHans Verkuil 
vb2_core_dqbuf(struct vb2_queue * q,unsigned int * pindex,void * pb,bool nonblocking)19407952be9bSHans Verkuil int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
19417952be9bSHans Verkuil 		   bool nonblocking)
19427952be9bSHans Verkuil {
19437952be9bSHans Verkuil 	struct vb2_buffer *vb = NULL;
19447952be9bSHans Verkuil 	int ret;
19457952be9bSHans Verkuil 
19467952be9bSHans Verkuil 	ret = __vb2_get_done_vb(q, &vb, pb, nonblocking);
19477952be9bSHans Verkuil 	if (ret < 0)
19487952be9bSHans Verkuil 		return ret;
19497952be9bSHans Verkuil 
19507952be9bSHans Verkuil 	switch (vb->state) {
19517952be9bSHans Verkuil 	case VB2_BUF_STATE_DONE:
1952b820935bSLaurent Pinchart 		dprintk(q, 3, "returning done buffer\n");
19537952be9bSHans Verkuil 		break;
19547952be9bSHans Verkuil 	case VB2_BUF_STATE_ERROR:
1955b820935bSLaurent Pinchart 		dprintk(q, 3, "returning done buffer with errors\n");
19567952be9bSHans Verkuil 		break;
19577952be9bSHans Verkuil 	default:
1958c89ee8edSEzequiel Garcia 		dprintk(q, 1, "invalid buffer state %s\n",
1959c89ee8edSEzequiel Garcia 			vb2_state_name(vb->state));
19607952be9bSHans Verkuil 		return -EINVAL;
19617952be9bSHans Verkuil 	}
19627952be9bSHans Verkuil 
19637952be9bSHans Verkuil 	call_void_vb_qop(vb, buf_finish, vb);
1964cfc77408SHans Verkuil 	vb->prepared = 0;
19657952be9bSHans Verkuil 
19667952be9bSHans Verkuil 	if (pindex)
19677952be9bSHans Verkuil 		*pindex = vb->index;
19687952be9bSHans Verkuil 
19697952be9bSHans Verkuil 	/* Fill buffer information for the userspace */
19707952be9bSHans Verkuil 	if (pb)
19717952be9bSHans Verkuil 		call_void_bufop(q, fill_user_buffer, vb, pb);
19727952be9bSHans Verkuil 
19733e947c36SHans Verkuil 	/* Remove from vb2 queue */
19747952be9bSHans Verkuil 	list_del(&vb->queued_entry);
19757952be9bSHans Verkuil 	q->queued_count--;
19767952be9bSHans Verkuil 
19777952be9bSHans Verkuil 	trace_vb2_dqbuf(q, vb);
19787952be9bSHans Verkuil 
19797952be9bSHans Verkuil 	/* go back to dequeued state */
19807952be9bSHans Verkuil 	__vb2_dqbuf(vb);
19817952be9bSHans Verkuil 
19826093d300SHans Verkuil 	if (WARN_ON(vb->req_obj.req)) {
19836093d300SHans Verkuil 		media_request_object_unbind(&vb->req_obj);
19846093d300SHans Verkuil 		media_request_object_put(&vb->req_obj);
19856093d300SHans Verkuil 	}
19866093d300SHans Verkuil 	if (vb->request)
19876093d300SHans Verkuil 		media_request_put(vb->request);
19886093d300SHans Verkuil 	vb->request = NULL;
19896093d300SHans Verkuil 
1990c89ee8edSEzequiel Garcia 	dprintk(q, 2, "dqbuf of buffer %d, state: %s\n",
1991c89ee8edSEzequiel Garcia 		vb->index, vb2_state_name(vb->state));
19927952be9bSHans Verkuil 
19937952be9bSHans Verkuil 	return 0;
19947952be9bSHans Verkuil 
19957952be9bSHans Verkuil }
19967952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
19977952be9bSHans Verkuil 
19987952be9bSHans Verkuil /*
19997952be9bSHans Verkuil  * __vb2_queue_cancel() - cancel and stop (pause) streaming
20007952be9bSHans Verkuil  *
20017952be9bSHans Verkuil  * Removes all queued buffers from driver's queue and all buffers queued by
20023e947c36SHans Verkuil  * userspace from vb2's queue. Returns to state after reqbufs.
20037952be9bSHans Verkuil  */
__vb2_queue_cancel(struct vb2_queue * q)20047952be9bSHans Verkuil static void __vb2_queue_cancel(struct vb2_queue *q)
20057952be9bSHans Verkuil {
20067952be9bSHans Verkuil 	unsigned int i;
20077952be9bSHans Verkuil 
20087952be9bSHans Verkuil 	/*
20097952be9bSHans Verkuil 	 * Tell driver to stop all transactions and release all queued
20107952be9bSHans Verkuil 	 * buffers.
20117952be9bSHans Verkuil 	 */
20127952be9bSHans Verkuil 	if (q->start_streaming_called)
20137952be9bSHans Verkuil 		call_void_qop(q, stop_streaming, q);
20147952be9bSHans Verkuil 
2015a10b2153SHans Verkuil 	if (q->streaming)
2016a10b2153SHans Verkuil 		call_void_qop(q, unprepare_streaming, q);
2017a10b2153SHans Verkuil 
20187952be9bSHans Verkuil 	/*
20197952be9bSHans Verkuil 	 * If you see this warning, then the driver isn't cleaning up properly
20207952be9bSHans Verkuil 	 * in stop_streaming(). See the stop_streaming() documentation in
20217952be9bSHans Verkuil 	 * videobuf2-core.h for more information how buffers should be returned
20227952be9bSHans Verkuil 	 * to vb2 in stop_streaming().
20237952be9bSHans Verkuil 	 */
20247952be9bSHans Verkuil 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
20257952be9bSHans Verkuil 		for (i = 0; i < q->num_buffers; ++i)
20267952be9bSHans Verkuil 			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
20277952be9bSHans Verkuil 				pr_warn("driver bug: stop_streaming operation is leaving buf %p in active state\n",
20287952be9bSHans Verkuil 					q->bufs[i]);
20297952be9bSHans Verkuil 				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
20307952be9bSHans Verkuil 			}
20317952be9bSHans Verkuil 		/* Must be zero now */
20327952be9bSHans Verkuil 		WARN_ON(atomic_read(&q->owned_by_drv_count));
20337952be9bSHans Verkuil 	}
20347952be9bSHans Verkuil 
20357952be9bSHans Verkuil 	q->streaming = 0;
20367952be9bSHans Verkuil 	q->start_streaming_called = 0;
20377952be9bSHans Verkuil 	q->queued_count = 0;
20387952be9bSHans Verkuil 	q->error = 0;
203961add367SHans Verkuil 	q->uses_requests = 0;
204061add367SHans Verkuil 	q->uses_qbuf = 0;
20417952be9bSHans Verkuil 
20427952be9bSHans Verkuil 	/*
20433e947c36SHans Verkuil 	 * Remove all buffers from vb2's list...
20447952be9bSHans Verkuil 	 */
20457952be9bSHans Verkuil 	INIT_LIST_HEAD(&q->queued_list);
20467952be9bSHans Verkuil 	/*
20477952be9bSHans Verkuil 	 * ...and done list; userspace will not receive any buffers it
20487952be9bSHans Verkuil 	 * has not already dequeued before initiating cancel.
20497952be9bSHans Verkuil 	 */
20507952be9bSHans Verkuil 	INIT_LIST_HEAD(&q->done_list);
20517952be9bSHans Verkuil 	atomic_set(&q->owned_by_drv_count, 0);
20527952be9bSHans Verkuil 	wake_up_all(&q->done_wq);
20537952be9bSHans Verkuil 
20547952be9bSHans Verkuil 	/*
20557952be9bSHans Verkuil 	 * Reinitialize all buffers for next use.
20567952be9bSHans Verkuil 	 * Make sure to call buf_finish for any queued buffers. Normally
20577952be9bSHans Verkuil 	 * that's done in dqbuf, but that's not going to happen when we
20587952be9bSHans Verkuil 	 * cancel the whole queue. Note: this code belongs here, not in
20597952be9bSHans Verkuil 	 * __vb2_dqbuf() since in vb2_core_dqbuf() there is a critical
20607952be9bSHans Verkuil 	 * call to __fill_user_buffer() after buf_finish(). That order can't
20617952be9bSHans Verkuil 	 * be changed, so we can't move the buf_finish() to __vb2_dqbuf().
20627952be9bSHans Verkuil 	 */
20637952be9bSHans Verkuil 	for (i = 0; i < q->num_buffers; ++i) {
20647952be9bSHans Verkuil 		struct vb2_buffer *vb = q->bufs[i];
2065fd89e0bbSHans Verkuil 		struct media_request *req = vb->req_obj.req;
20667952be9bSHans Verkuil 
2067fd89e0bbSHans Verkuil 		/*
2068fd89e0bbSHans Verkuil 		 * If a request is associated with this buffer, then
2069fd89e0bbSHans Verkuil 		 * call buf_request_cancel() to give the driver to complete()
2070fd89e0bbSHans Verkuil 		 * related request objects. Otherwise those objects would
2071fd89e0bbSHans Verkuil 		 * never complete.
2072fd89e0bbSHans Verkuil 		 */
2073fd89e0bbSHans Verkuil 		if (req) {
2074fd89e0bbSHans Verkuil 			enum media_request_state state;
2075fd89e0bbSHans Verkuil 			unsigned long flags;
2076fd89e0bbSHans Verkuil 
2077fd89e0bbSHans Verkuil 			spin_lock_irqsave(&req->lock, flags);
2078fd89e0bbSHans Verkuil 			state = req->state;
2079fd89e0bbSHans Verkuil 			spin_unlock_irqrestore(&req->lock, flags);
2080fd89e0bbSHans Verkuil 
2081fd89e0bbSHans Verkuil 			if (state == MEDIA_REQUEST_STATE_QUEUED)
2082fd89e0bbSHans Verkuil 				call_void_vb_qop(vb, buf_request_complete, vb);
2083fd89e0bbSHans Verkuil 		}
20847952be9bSHans Verkuil 
208538a417e8SSergey Senozhatsky 		__vb2_buf_mem_finish(vb);
208603703ed1SSakari Ailus 
208755028695SHans Verkuil 		if (vb->prepared) {
20887952be9bSHans Verkuil 			call_void_vb_qop(vb, buf_finish, vb);
2089cfc77408SHans Verkuil 			vb->prepared = 0;
20907952be9bSHans Verkuil 		}
20917952be9bSHans Verkuil 		__vb2_dqbuf(vb);
20926093d300SHans Verkuil 
20936093d300SHans Verkuil 		if (vb->req_obj.req) {
20946093d300SHans Verkuil 			media_request_object_unbind(&vb->req_obj);
20956093d300SHans Verkuil 			media_request_object_put(&vb->req_obj);
20966093d300SHans Verkuil 		}
20976093d300SHans Verkuil 		if (vb->request)
20986093d300SHans Verkuil 			media_request_put(vb->request);
20996093d300SHans Verkuil 		vb->request = NULL;
21007e4e7162SHans Verkuil 		vb->copied_timestamp = 0;
21017952be9bSHans Verkuil 	}
21027952be9bSHans Verkuil }
21037952be9bSHans Verkuil 
vb2_core_streamon(struct vb2_queue * q,unsigned int type)21047952be9bSHans Verkuil int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
21057952be9bSHans Verkuil {
21067952be9bSHans Verkuil 	int ret;
21077952be9bSHans Verkuil 
21087952be9bSHans Verkuil 	if (type != q->type) {
2109b820935bSLaurent Pinchart 		dprintk(q, 1, "invalid stream type\n");
21107952be9bSHans Verkuil 		return -EINVAL;
21117952be9bSHans Verkuil 	}
21127952be9bSHans Verkuil 
21137952be9bSHans Verkuil 	if (q->streaming) {
2114b820935bSLaurent Pinchart 		dprintk(q, 3, "already streaming\n");
21157952be9bSHans Verkuil 		return 0;
21167952be9bSHans Verkuil 	}
21177952be9bSHans Verkuil 
21187952be9bSHans Verkuil 	if (!q->num_buffers) {
2119b820935bSLaurent Pinchart 		dprintk(q, 1, "no buffers have been allocated\n");
21207952be9bSHans Verkuil 		return -EINVAL;
21217952be9bSHans Verkuil 	}
21227952be9bSHans Verkuil 
21237952be9bSHans Verkuil 	if (q->num_buffers < q->min_buffers_needed) {
2124b820935bSLaurent Pinchart 		dprintk(q, 1, "need at least %u allocated buffers\n",
21257952be9bSHans Verkuil 				q->min_buffers_needed);
21267952be9bSHans Verkuil 		return -EINVAL;
21277952be9bSHans Verkuil 	}
21287952be9bSHans Verkuil 
2129a10b2153SHans Verkuil 	ret = call_qop(q, prepare_streaming, q);
2130a10b2153SHans Verkuil 	if (ret)
2131a10b2153SHans Verkuil 		return ret;
2132a10b2153SHans Verkuil 
21337952be9bSHans Verkuil 	/*
21347952be9bSHans Verkuil 	 * Tell driver to start streaming provided sufficient buffers
21357952be9bSHans Verkuil 	 * are available.
21367952be9bSHans Verkuil 	 */
21377952be9bSHans Verkuil 	if (q->queued_count >= q->min_buffers_needed) {
21387952be9bSHans Verkuil 		ret = vb2_start_streaming(q);
213904990215SHans Verkuil 		if (ret)
2140a10b2153SHans Verkuil 			goto unprepare;
21417952be9bSHans Verkuil 	}
21427952be9bSHans Verkuil 
214389c08aefSHans Verkuil 	q->streaming = 1;
214489c08aefSHans Verkuil 
2145b820935bSLaurent Pinchart 	dprintk(q, 3, "successful\n");
21467952be9bSHans Verkuil 	return 0;
2147a10b2153SHans Verkuil 
2148a10b2153SHans Verkuil unprepare:
2149a10b2153SHans Verkuil 	call_void_qop(q, unprepare_streaming, q);
2150a10b2153SHans Verkuil 	return ret;
21517952be9bSHans Verkuil }
21527952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_streamon);
21537952be9bSHans Verkuil 
vb2_queue_error(struct vb2_queue * q)21547952be9bSHans Verkuil void vb2_queue_error(struct vb2_queue *q)
21557952be9bSHans Verkuil {
21567952be9bSHans Verkuil 	q->error = 1;
21577952be9bSHans Verkuil 
21587952be9bSHans Verkuil 	wake_up_all(&q->done_wq);
21597952be9bSHans Verkuil }
21607952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_queue_error);
21617952be9bSHans Verkuil 
vb2_core_streamoff(struct vb2_queue * q,unsigned int type)21627952be9bSHans Verkuil int vb2_core_streamoff(struct vb2_queue *q, unsigned int type)
21637952be9bSHans Verkuil {
21647952be9bSHans Verkuil 	if (type != q->type) {
2165b820935bSLaurent Pinchart 		dprintk(q, 1, "invalid stream type\n");
21667952be9bSHans Verkuil 		return -EINVAL;
21677952be9bSHans Verkuil 	}
21687952be9bSHans Verkuil 
21697952be9bSHans Verkuil 	/*
21707952be9bSHans Verkuil 	 * Cancel will pause streaming and remove all buffers from the driver
21713e947c36SHans Verkuil 	 * and vb2, effectively returning control over them to userspace.
21727952be9bSHans Verkuil 	 *
21737952be9bSHans Verkuil 	 * Note that we do this even if q->streaming == 0: if you prepare or
21747952be9bSHans Verkuil 	 * queue buffers, and then call streamoff without ever having called
21757952be9bSHans Verkuil 	 * streamon, you would still expect those buffers to be returned to
21767952be9bSHans Verkuil 	 * their normal dequeued state.
21777952be9bSHans Verkuil 	 */
21787952be9bSHans Verkuil 	__vb2_queue_cancel(q);
21797952be9bSHans Verkuil 	q->waiting_for_buffers = !q->is_output;
21807952be9bSHans Verkuil 	q->last_buffer_dequeued = false;
21817952be9bSHans Verkuil 
2182b820935bSLaurent Pinchart 	dprintk(q, 3, "successful\n");
21837952be9bSHans Verkuil 	return 0;
21847952be9bSHans Verkuil }
21857952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_streamoff);
21867952be9bSHans Verkuil 
21877952be9bSHans Verkuil /*
21887952be9bSHans Verkuil  * __find_plane_by_offset() - find plane associated with the given offset off
21897952be9bSHans Verkuil  */
__find_plane_by_offset(struct vb2_queue * q,unsigned long off,unsigned int * _buffer,unsigned int * _plane)21907952be9bSHans Verkuil static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
21917952be9bSHans Verkuil 			unsigned int *_buffer, unsigned int *_plane)
21927952be9bSHans Verkuil {
21937952be9bSHans Verkuil 	struct vb2_buffer *vb;
21947952be9bSHans Verkuil 	unsigned int buffer, plane;
21957952be9bSHans Verkuil 
21967952be9bSHans Verkuil 	/*
2197098e5edcSHans Verkuil 	 * Sanity checks to ensure the lock is held, MEMORY_MMAP is
2198098e5edcSHans Verkuil 	 * used and fileio isn't active.
2199098e5edcSHans Verkuil 	 */
2200098e5edcSHans Verkuil 	lockdep_assert_held(&q->mmap_lock);
2201098e5edcSHans Verkuil 
2202098e5edcSHans Verkuil 	if (q->memory != VB2_MEMORY_MMAP) {
2203098e5edcSHans Verkuil 		dprintk(q, 1, "queue is not currently set up for mmap\n");
2204098e5edcSHans Verkuil 		return -EINVAL;
2205098e5edcSHans Verkuil 	}
2206098e5edcSHans Verkuil 
2207098e5edcSHans Verkuil 	if (vb2_fileio_is_active(q)) {
2208098e5edcSHans Verkuil 		dprintk(q, 1, "file io in progress\n");
2209098e5edcSHans Verkuil 		return -EBUSY;
2210098e5edcSHans Verkuil 	}
2211098e5edcSHans Verkuil 
2212098e5edcSHans Verkuil 	/*
22137952be9bSHans Verkuil 	 * Go over all buffers and their planes, comparing the given offset
22147952be9bSHans Verkuil 	 * with an offset assigned to each plane. If a match is found,
22157952be9bSHans Verkuil 	 * return its buffer and plane numbers.
22167952be9bSHans Verkuil 	 */
22177952be9bSHans Verkuil 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
22187952be9bSHans Verkuil 		vb = q->bufs[buffer];
22197952be9bSHans Verkuil 
22207952be9bSHans Verkuil 		for (plane = 0; plane < vb->num_planes; ++plane) {
22217952be9bSHans Verkuil 			if (vb->planes[plane].m.offset == off) {
22227952be9bSHans Verkuil 				*_buffer = buffer;
22237952be9bSHans Verkuil 				*_plane = plane;
22247952be9bSHans Verkuil 				return 0;
22257952be9bSHans Verkuil 			}
22267952be9bSHans Verkuil 		}
22277952be9bSHans Verkuil 	}
22287952be9bSHans Verkuil 
22297952be9bSHans Verkuil 	return -EINVAL;
22307952be9bSHans Verkuil }
22317952be9bSHans Verkuil 
vb2_core_expbuf(struct vb2_queue * q,int * fd,unsigned int type,unsigned int index,unsigned int plane,unsigned int flags)22327952be9bSHans Verkuil int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
22337952be9bSHans Verkuil 		unsigned int index, unsigned int plane, unsigned int flags)
22347952be9bSHans Verkuil {
22357952be9bSHans Verkuil 	struct vb2_buffer *vb = NULL;
22367952be9bSHans Verkuil 	struct vb2_plane *vb_plane;
22377952be9bSHans Verkuil 	int ret;
22387952be9bSHans Verkuil 	struct dma_buf *dbuf;
22397952be9bSHans Verkuil 
22407952be9bSHans Verkuil 	if (q->memory != VB2_MEMORY_MMAP) {
2241b820935bSLaurent Pinchart 		dprintk(q, 1, "queue is not currently set up for mmap\n");
22427952be9bSHans Verkuil 		return -EINVAL;
22437952be9bSHans Verkuil 	}
22447952be9bSHans Verkuil 
22457952be9bSHans Verkuil 	if (!q->mem_ops->get_dmabuf) {
2246b820935bSLaurent Pinchart 		dprintk(q, 1, "queue does not support DMA buffer exporting\n");
22477952be9bSHans Verkuil 		return -EINVAL;
22487952be9bSHans Verkuil 	}
22497952be9bSHans Verkuil 
22507952be9bSHans Verkuil 	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
2251b820935bSLaurent Pinchart 		dprintk(q, 1, "queue does support only O_CLOEXEC and access mode flags\n");
22527952be9bSHans Verkuil 		return -EINVAL;
22537952be9bSHans Verkuil 	}
22547952be9bSHans Verkuil 
22557952be9bSHans Verkuil 	if (type != q->type) {
2256b820935bSLaurent Pinchart 		dprintk(q, 1, "invalid buffer type\n");
22577952be9bSHans Verkuil 		return -EINVAL;
22587952be9bSHans Verkuil 	}
22597952be9bSHans Verkuil 
22607952be9bSHans Verkuil 	if (index >= q->num_buffers) {
2261b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer index out of range\n");
22627952be9bSHans Verkuil 		return -EINVAL;
22637952be9bSHans Verkuil 	}
22647952be9bSHans Verkuil 
22657952be9bSHans Verkuil 	vb = q->bufs[index];
22667952be9bSHans Verkuil 
22677952be9bSHans Verkuil 	if (plane >= vb->num_planes) {
2268b820935bSLaurent Pinchart 		dprintk(q, 1, "buffer plane out of range\n");
22697952be9bSHans Verkuil 		return -EINVAL;
22707952be9bSHans Verkuil 	}
22717952be9bSHans Verkuil 
22727952be9bSHans Verkuil 	if (vb2_fileio_is_active(q)) {
2273b820935bSLaurent Pinchart 		dprintk(q, 1, "expbuf: file io in progress\n");
22747952be9bSHans Verkuil 		return -EBUSY;
22757952be9bSHans Verkuil 	}
22767952be9bSHans Verkuil 
22777952be9bSHans Verkuil 	vb_plane = &vb->planes[plane];
22787952be9bSHans Verkuil 
2279a4b83debSSergey Senozhatsky 	dbuf = call_ptr_memop(get_dmabuf,
2280a4b83debSSergey Senozhatsky 			      vb,
2281a4b83debSSergey Senozhatsky 			      vb_plane->mem_priv,
22827952be9bSHans Verkuil 			      flags & O_ACCMODE);
22837952be9bSHans Verkuil 	if (IS_ERR_OR_NULL(dbuf)) {
2284b820935bSLaurent Pinchart 		dprintk(q, 1, "failed to export buffer %d, plane %d\n",
22857952be9bSHans Verkuil 			index, plane);
22867952be9bSHans Verkuil 		return -EINVAL;
22877952be9bSHans Verkuil 	}
22887952be9bSHans Verkuil 
22897952be9bSHans Verkuil 	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
22907952be9bSHans Verkuil 	if (ret < 0) {
2291b820935bSLaurent Pinchart 		dprintk(q, 3, "buffer %d, plane %d failed to export (%d)\n",
22927952be9bSHans Verkuil 			index, plane, ret);
22937952be9bSHans Verkuil 		dma_buf_put(dbuf);
22947952be9bSHans Verkuil 		return ret;
22957952be9bSHans Verkuil 	}
22967952be9bSHans Verkuil 
2297b820935bSLaurent Pinchart 	dprintk(q, 3, "buffer %d, plane %d exported as %d descriptor\n",
22987952be9bSHans Verkuil 		index, plane, ret);
22997952be9bSHans Verkuil 	*fd = ret;
23007952be9bSHans Verkuil 
23017952be9bSHans Verkuil 	return 0;
23027952be9bSHans Verkuil }
23037952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_expbuf);
23047952be9bSHans Verkuil 
vb2_mmap(struct vb2_queue * q,struct vm_area_struct * vma)23057952be9bSHans Verkuil int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
23067952be9bSHans Verkuil {
23077952be9bSHans Verkuil 	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
23087952be9bSHans Verkuil 	struct vb2_buffer *vb;
23097952be9bSHans Verkuil 	unsigned int buffer = 0, plane = 0;
23107952be9bSHans Verkuil 	int ret;
23117952be9bSHans Verkuil 	unsigned long length;
23127952be9bSHans Verkuil 
23137952be9bSHans Verkuil 	/*
23147952be9bSHans Verkuil 	 * Check memory area access mode.
23157952be9bSHans Verkuil 	 */
23167952be9bSHans Verkuil 	if (!(vma->vm_flags & VM_SHARED)) {
2317b820935bSLaurent Pinchart 		dprintk(q, 1, "invalid vma flags, VM_SHARED needed\n");
23187952be9bSHans Verkuil 		return -EINVAL;
23197952be9bSHans Verkuil 	}
23207952be9bSHans Verkuil 	if (q->is_output) {
23217952be9bSHans Verkuil 		if (!(vma->vm_flags & VM_WRITE)) {
2322b820935bSLaurent Pinchart 			dprintk(q, 1, "invalid vma flags, VM_WRITE needed\n");
23237952be9bSHans Verkuil 			return -EINVAL;
23247952be9bSHans Verkuil 		}
23257952be9bSHans Verkuil 	} else {
23267952be9bSHans Verkuil 		if (!(vma->vm_flags & VM_READ)) {
2327b820935bSLaurent Pinchart 			dprintk(q, 1, "invalid vma flags, VM_READ needed\n");
23287952be9bSHans Verkuil 			return -EINVAL;
23297952be9bSHans Verkuil 		}
23307952be9bSHans Verkuil 	}
2331cd26d1c4SHans Verkuil 
2332cd26d1c4SHans Verkuil 	mutex_lock(&q->mmap_lock);
2333cd26d1c4SHans Verkuil 
23347952be9bSHans Verkuil 	/*
2335098e5edcSHans Verkuil 	 * Find the plane corresponding to the offset passed by userspace. This
2336098e5edcSHans Verkuil 	 * will return an error if not MEMORY_MMAP or file I/O is in progress.
23377952be9bSHans Verkuil 	 */
23387952be9bSHans Verkuil 	ret = __find_plane_by_offset(q, off, &buffer, &plane);
23397952be9bSHans Verkuil 	if (ret)
2340cd26d1c4SHans Verkuil 		goto unlock;
23417952be9bSHans Verkuil 
23427952be9bSHans Verkuil 	vb = q->bufs[buffer];
23437952be9bSHans Verkuil 
23447952be9bSHans Verkuil 	/*
23457952be9bSHans Verkuil 	 * MMAP requires page_aligned buffers.
23467952be9bSHans Verkuil 	 * The buffer length was page_aligned at __vb2_buf_mem_alloc(),
23477952be9bSHans Verkuil 	 * so, we need to do the same here.
23487952be9bSHans Verkuil 	 */
23497952be9bSHans Verkuil 	length = PAGE_ALIGN(vb->planes[plane].length);
23507952be9bSHans Verkuil 	if (length < (vma->vm_end - vma->vm_start)) {
2351b820935bSLaurent Pinchart 		dprintk(q, 1,
23527952be9bSHans Verkuil 			"MMAP invalid, as it would overflow buffer length\n");
2353c06ef2e9SMauro Carvalho Chehab 		ret = -EINVAL;
2354c06ef2e9SMauro Carvalho Chehab 		goto unlock;
23557952be9bSHans Verkuil 	}
23567952be9bSHans Verkuil 
2357a17ae147SSouptick Joarder 	/*
2358a17ae147SSouptick Joarder 	 * vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
2359a17ae147SSouptick Joarder 	 * not as a in-buffer offset. We always want to mmap a whole buffer
2360a17ae147SSouptick Joarder 	 * from its beginning.
2361a17ae147SSouptick Joarder 	 */
2362a17ae147SSouptick Joarder 	vma->vm_pgoff = 0;
2363a17ae147SSouptick Joarder 
23647952be9bSHans Verkuil 	ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);
2365cd26d1c4SHans Verkuil 
2366cd26d1c4SHans Verkuil unlock:
23677952be9bSHans Verkuil 	mutex_unlock(&q->mmap_lock);
23687952be9bSHans Verkuil 	if (ret)
23697952be9bSHans Verkuil 		return ret;
23707952be9bSHans Verkuil 
2371b820935bSLaurent Pinchart 	dprintk(q, 3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
23727952be9bSHans Verkuil 	return 0;
23737952be9bSHans Verkuil }
23747952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_mmap);
23757952be9bSHans Verkuil 
23767952be9bSHans Verkuil #ifndef CONFIG_MMU
vb2_get_unmapped_area(struct vb2_queue * q,unsigned long addr,unsigned long len,unsigned long pgoff,unsigned long flags)23777952be9bSHans Verkuil unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
23787952be9bSHans Verkuil 				    unsigned long addr,
23797952be9bSHans Verkuil 				    unsigned long len,
23807952be9bSHans Verkuil 				    unsigned long pgoff,
23817952be9bSHans Verkuil 				    unsigned long flags)
23827952be9bSHans Verkuil {
23837952be9bSHans Verkuil 	unsigned long off = pgoff << PAGE_SHIFT;
23847952be9bSHans Verkuil 	struct vb2_buffer *vb;
23857952be9bSHans Verkuil 	unsigned int buffer, plane;
23867952be9bSHans Verkuil 	void *vaddr;
23877952be9bSHans Verkuil 	int ret;
23887952be9bSHans Verkuil 
2389098e5edcSHans Verkuil 	mutex_lock(&q->mmap_lock);
23907952be9bSHans Verkuil 
23917952be9bSHans Verkuil 	/*
2392098e5edcSHans Verkuil 	 * Find the plane corresponding to the offset passed by userspace. This
2393098e5edcSHans Verkuil 	 * will return an error if not MEMORY_MMAP or file I/O is in progress.
23947952be9bSHans Verkuil 	 */
23957952be9bSHans Verkuil 	ret = __find_plane_by_offset(q, off, &buffer, &plane);
23967952be9bSHans Verkuil 	if (ret)
2397098e5edcSHans Verkuil 		goto unlock;
23987952be9bSHans Verkuil 
23997952be9bSHans Verkuil 	vb = q->bufs[buffer];
24007952be9bSHans Verkuil 
24017952be9bSHans Verkuil 	vaddr = vb2_plane_vaddr(vb, plane);
2402098e5edcSHans Verkuil 	mutex_unlock(&q->mmap_lock);
24037952be9bSHans Verkuil 	return vaddr ? (unsigned long)vaddr : -EINVAL;
2404098e5edcSHans Verkuil 
2405098e5edcSHans Verkuil unlock:
2406098e5edcSHans Verkuil 	mutex_unlock(&q->mmap_lock);
2407098e5edcSHans Verkuil 	return ret;
24087952be9bSHans Verkuil }
24097952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
24107952be9bSHans Verkuil #endif
24117952be9bSHans Verkuil 
vb2_core_queue_init(struct vb2_queue * q)24127952be9bSHans Verkuil int vb2_core_queue_init(struct vb2_queue *q)
24137952be9bSHans Verkuil {
24147952be9bSHans Verkuil 	/*
24157952be9bSHans Verkuil 	 * Sanity check
24167952be9bSHans Verkuil 	 */
24177952be9bSHans Verkuil 	if (WARN_ON(!q)			  ||
24187952be9bSHans Verkuil 	    WARN_ON(!q->ops)		  ||
24197952be9bSHans Verkuil 	    WARN_ON(!q->mem_ops)	  ||
24207952be9bSHans Verkuil 	    WARN_ON(!q->type)		  ||
24217952be9bSHans Verkuil 	    WARN_ON(!q->io_modes)	  ||
24227952be9bSHans Verkuil 	    WARN_ON(!q->ops->queue_setup) ||
24237952be9bSHans Verkuil 	    WARN_ON(!q->ops->buf_queue))
24247952be9bSHans Verkuil 		return -EINVAL;
24257952be9bSHans Verkuil 
242690675d39SHans Verkuil 	if (WARN_ON(q->requires_requests && !q->supports_requests))
242790675d39SHans Verkuil 		return -EINVAL;
242890675d39SHans Verkuil 
24299015fcc2SHans Verkuil 	/*
24309015fcc2SHans Verkuil 	 * This combination is not allowed since a non-zero value of
24319015fcc2SHans Verkuil 	 * q->min_buffers_needed can cause vb2_core_qbuf() to fail if
24329015fcc2SHans Verkuil 	 * it has to call start_streaming(), and the Request API expects
24339015fcc2SHans Verkuil 	 * that queueing a request (and thus queueing a buffer contained
24349015fcc2SHans Verkuil 	 * in that request) will always succeed. There is no method of
24359015fcc2SHans Verkuil 	 * propagating an error back to userspace.
24369015fcc2SHans Verkuil 	 */
24379015fcc2SHans Verkuil 	if (WARN_ON(q->supports_requests && q->min_buffers_needed))
24389015fcc2SHans Verkuil 		return -EINVAL;
24399015fcc2SHans Verkuil 
24407952be9bSHans Verkuil 	INIT_LIST_HEAD(&q->queued_list);
24417952be9bSHans Verkuil 	INIT_LIST_HEAD(&q->done_list);
24427952be9bSHans Verkuil 	spin_lock_init(&q->done_lock);
24437952be9bSHans Verkuil 	mutex_init(&q->mmap_lock);
24447952be9bSHans Verkuil 	init_waitqueue_head(&q->done_wq);
24457952be9bSHans Verkuil 
24467952be9bSHans Verkuil 	q->memory = VB2_MEMORY_UNKNOWN;
24477952be9bSHans Verkuil 
24487952be9bSHans Verkuil 	if (q->buf_struct_size == 0)
24497952be9bSHans Verkuil 		q->buf_struct_size = sizeof(struct vb2_buffer);
24507952be9bSHans Verkuil 
24517952be9bSHans Verkuil 	if (q->bidirectional)
24527952be9bSHans Verkuil 		q->dma_dir = DMA_BIDIRECTIONAL;
24537952be9bSHans Verkuil 	else
24547952be9bSHans Verkuil 		q->dma_dir = q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
24557952be9bSHans Verkuil 
2456b820935bSLaurent Pinchart 	if (q->name[0] == '\0')
2457b820935bSLaurent Pinchart 		snprintf(q->name, sizeof(q->name), "%s-%p",
2458b820935bSLaurent Pinchart 			 q->is_output ? "out" : "cap", q);
2459b820935bSLaurent Pinchart 
24607952be9bSHans Verkuil 	return 0;
24617952be9bSHans Verkuil }
24627952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_queue_init);
24637952be9bSHans Verkuil 
24647952be9bSHans Verkuil static int __vb2_init_fileio(struct vb2_queue *q, int read);
24657952be9bSHans Verkuil static int __vb2_cleanup_fileio(struct vb2_queue *q);
vb2_core_queue_release(struct vb2_queue * q)24667952be9bSHans Verkuil void vb2_core_queue_release(struct vb2_queue *q)
24677952be9bSHans Verkuil {
24687952be9bSHans Verkuil 	__vb2_cleanup_fileio(q);
24697952be9bSHans Verkuil 	__vb2_queue_cancel(q);
24707952be9bSHans Verkuil 	mutex_lock(&q->mmap_lock);
24717952be9bSHans Verkuil 	__vb2_queue_free(q, q->num_buffers);
24727952be9bSHans Verkuil 	mutex_unlock(&q->mmap_lock);
24737952be9bSHans Verkuil }
24747952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_queue_release);
24757952be9bSHans Verkuil 
vb2_core_poll(struct vb2_queue * q,struct file * file,poll_table * wait)247668c5735eSLinus Torvalds __poll_t vb2_core_poll(struct vb2_queue *q, struct file *file,
24777952be9bSHans Verkuil 		poll_table *wait)
24787952be9bSHans Verkuil {
247968c5735eSLinus Torvalds 	__poll_t req_events = poll_requested_events(wait);
24807952be9bSHans Verkuil 	struct vb2_buffer *vb = NULL;
24817952be9bSHans Verkuil 	unsigned long flags;
24827952be9bSHans Verkuil 
2483575c52ccSAlexandre Courbot 	/*
2484575c52ccSAlexandre Courbot 	 * poll_wait() MUST be called on the first invocation on all the
2485575c52ccSAlexandre Courbot 	 * potential queues of interest, even if we are not interested in their
2486575c52ccSAlexandre Courbot 	 * events during this first call. Failure to do so will result in
2487575c52ccSAlexandre Courbot 	 * queue's events to be ignored because the poll_table won't be capable
2488575c52ccSAlexandre Courbot 	 * of adding new wait queues thereafter.
2489575c52ccSAlexandre Courbot 	 */
2490575c52ccSAlexandre Courbot 	poll_wait(file, &q->done_wq, wait);
2491575c52ccSAlexandre Courbot 
2492a9a08845SLinus Torvalds 	if (!q->is_output && !(req_events & (EPOLLIN | EPOLLRDNORM)))
24937952be9bSHans Verkuil 		return 0;
2494a9a08845SLinus Torvalds 	if (q->is_output && !(req_events & (EPOLLOUT | EPOLLWRNORM)))
24957952be9bSHans Verkuil 		return 0;
24967952be9bSHans Verkuil 
24977952be9bSHans Verkuil 	/*
24987952be9bSHans Verkuil 	 * Start file I/O emulator only if streaming API has not been used yet.
24997952be9bSHans Verkuil 	 */
25007952be9bSHans Verkuil 	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
25017952be9bSHans Verkuil 		if (!q->is_output && (q->io_modes & VB2_READ) &&
2502a9a08845SLinus Torvalds 				(req_events & (EPOLLIN | EPOLLRDNORM))) {
25037952be9bSHans Verkuil 			if (__vb2_init_fileio(q, 1))
2504a9a08845SLinus Torvalds 				return EPOLLERR;
25057952be9bSHans Verkuil 		}
25067952be9bSHans Verkuil 		if (q->is_output && (q->io_modes & VB2_WRITE) &&
2507a9a08845SLinus Torvalds 				(req_events & (EPOLLOUT | EPOLLWRNORM))) {
25087952be9bSHans Verkuil 			if (__vb2_init_fileio(q, 0))
2509a9a08845SLinus Torvalds 				return EPOLLERR;
25107952be9bSHans Verkuil 			/*
25117952be9bSHans Verkuil 			 * Write to OUTPUT queue can be done immediately.
25127952be9bSHans Verkuil 			 */
2513a9a08845SLinus Torvalds 			return EPOLLOUT | EPOLLWRNORM;
25147952be9bSHans Verkuil 		}
25157952be9bSHans Verkuil 	}
25167952be9bSHans Verkuil 
25177952be9bSHans Verkuil 	/*
25187952be9bSHans Verkuil 	 * There is nothing to wait for if the queue isn't streaming, or if the
25197952be9bSHans Verkuil 	 * error flag is set.
25207952be9bSHans Verkuil 	 */
25217952be9bSHans Verkuil 	if (!vb2_is_streaming(q) || q->error)
2522a9a08845SLinus Torvalds 		return EPOLLERR;
25237952be9bSHans Verkuil 
25247952be9bSHans Verkuil 	/*
25257952be9bSHans Verkuil 	 * If this quirk is set and QBUF hasn't been called yet then
2526a9a08845SLinus Torvalds 	 * return EPOLLERR as well. This only affects capture queues, output
25277952be9bSHans Verkuil 	 * queues will always initialize waiting_for_buffers to false.
25287952be9bSHans Verkuil 	 * This quirk is set by V4L2 for backwards compatibility reasons.
25297952be9bSHans Verkuil 	 */
25307952be9bSHans Verkuil 	if (q->quirk_poll_must_check_waiting_for_buffers &&
2531a9a08845SLinus Torvalds 	    q->waiting_for_buffers && (req_events & (EPOLLIN | EPOLLRDNORM)))
2532a9a08845SLinus Torvalds 		return EPOLLERR;
25337952be9bSHans Verkuil 
25347952be9bSHans Verkuil 	/*
25357952be9bSHans Verkuil 	 * For output streams you can call write() as long as there are fewer
25367952be9bSHans Verkuil 	 * buffers queued than there are buffers available.
25377952be9bSHans Verkuil 	 */
25387952be9bSHans Verkuil 	if (q->is_output && q->fileio && q->queued_count < q->num_buffers)
2539a9a08845SLinus Torvalds 		return EPOLLOUT | EPOLLWRNORM;
25407952be9bSHans Verkuil 
25417952be9bSHans Verkuil 	if (list_empty(&q->done_list)) {
25427952be9bSHans Verkuil 		/*
25437952be9bSHans Verkuil 		 * If the last buffer was dequeued from a capture queue,
25447952be9bSHans Verkuil 		 * return immediately. DQBUF will return -EPIPE.
25457952be9bSHans Verkuil 		 */
25467952be9bSHans Verkuil 		if (q->last_buffer_dequeued)
2547a9a08845SLinus Torvalds 			return EPOLLIN | EPOLLRDNORM;
25487952be9bSHans Verkuil 	}
25497952be9bSHans Verkuil 
25507952be9bSHans Verkuil 	/*
25517952be9bSHans Verkuil 	 * Take first buffer available for dequeuing.
25527952be9bSHans Verkuil 	 */
25537952be9bSHans Verkuil 	spin_lock_irqsave(&q->done_lock, flags);
25547952be9bSHans Verkuil 	if (!list_empty(&q->done_list))
25557952be9bSHans Verkuil 		vb = list_first_entry(&q->done_list, struct vb2_buffer,
25567952be9bSHans Verkuil 					done_entry);
25577952be9bSHans Verkuil 	spin_unlock_irqrestore(&q->done_lock, flags);
25587952be9bSHans Verkuil 
25597952be9bSHans Verkuil 	if (vb && (vb->state == VB2_BUF_STATE_DONE
25607952be9bSHans Verkuil 			|| vb->state == VB2_BUF_STATE_ERROR)) {
25617952be9bSHans Verkuil 		return (q->is_output) ?
2562a9a08845SLinus Torvalds 				EPOLLOUT | EPOLLWRNORM :
2563a9a08845SLinus Torvalds 				EPOLLIN | EPOLLRDNORM;
25647952be9bSHans Verkuil 	}
25657952be9bSHans Verkuil 	return 0;
25667952be9bSHans Verkuil }
25677952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_poll);
25687952be9bSHans Verkuil 
25697952be9bSHans Verkuil /*
25707952be9bSHans Verkuil  * struct vb2_fileio_buf - buffer context used by file io emulator
25717952be9bSHans Verkuil  *
25727952be9bSHans Verkuil  * vb2 provides a compatibility layer and emulator of file io (read and
25737952be9bSHans Verkuil  * write) calls on top of streaming API. This structure is used for
25747952be9bSHans Verkuil  * tracking context related to the buffers.
25757952be9bSHans Verkuil  */
25767952be9bSHans Verkuil struct vb2_fileio_buf {
25777952be9bSHans Verkuil 	void *vaddr;
25787952be9bSHans Verkuil 	unsigned int size;
25797952be9bSHans Verkuil 	unsigned int pos;
25807952be9bSHans Verkuil 	unsigned int queued:1;
25817952be9bSHans Verkuil };
25827952be9bSHans Verkuil 
25837952be9bSHans Verkuil /*
25847952be9bSHans Verkuil  * struct vb2_fileio_data - queue context used by file io emulator
25857952be9bSHans Verkuil  *
25867952be9bSHans Verkuil  * @cur_index:	the index of the buffer currently being read from or
25877952be9bSHans Verkuil  *		written to. If equal to q->num_buffers then a new buffer
25887952be9bSHans Verkuil  *		must be dequeued.
25897952be9bSHans Verkuil  * @initial_index: in the read() case all buffers are queued up immediately
25907952be9bSHans Verkuil  *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
25917952be9bSHans Verkuil  *		buffers. However, in the write() case no buffers are initially
25927952be9bSHans Verkuil  *		queued, instead whenever a buffer is full it is queued up by
25937952be9bSHans Verkuil  *		__vb2_perform_fileio(). Only once all available buffers have
25947952be9bSHans Verkuil  *		been queued up will __vb2_perform_fileio() start to dequeue
25957952be9bSHans Verkuil  *		buffers. This means that initially __vb2_perform_fileio()
25967952be9bSHans Verkuil  *		needs to know what buffer index to use when it is queuing up
25977952be9bSHans Verkuil  *		the buffers for the first time. That initial index is stored
25987952be9bSHans Verkuil  *		in this field. Once it is equal to q->num_buffers all
25997952be9bSHans Verkuil  *		available buffers have been queued and __vb2_perform_fileio()
26007952be9bSHans Verkuil  *		should start the normal dequeue/queue cycle.
26017952be9bSHans Verkuil  *
26027952be9bSHans Verkuil  * vb2 provides a compatibility layer and emulator of file io (read and
26037952be9bSHans Verkuil  * write) calls on top of streaming API. For proper operation it required
26047952be9bSHans Verkuil  * this structure to save the driver state between each call of the read
26057952be9bSHans Verkuil  * or write function.
26067952be9bSHans Verkuil  */
26077952be9bSHans Verkuil struct vb2_fileio_data {
26087952be9bSHans Verkuil 	unsigned int count;
26097952be9bSHans Verkuil 	unsigned int type;
26107952be9bSHans Verkuil 	unsigned int memory;
26117952be9bSHans Verkuil 	struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
26127952be9bSHans Verkuil 	unsigned int cur_index;
26137952be9bSHans Verkuil 	unsigned int initial_index;
26147952be9bSHans Verkuil 	unsigned int q_count;
26157952be9bSHans Verkuil 	unsigned int dq_count;
26167952be9bSHans Verkuil 	unsigned read_once:1;
26177952be9bSHans Verkuil 	unsigned write_immediately:1;
26187952be9bSHans Verkuil };
26197952be9bSHans Verkuil 
26207952be9bSHans Verkuil /*
26217952be9bSHans Verkuil  * __vb2_init_fileio() - initialize file io emulator
26227952be9bSHans Verkuil  * @q:		videobuf2 queue
26237952be9bSHans Verkuil  * @read:	mode selector (1 means read, 0 means write)
26247952be9bSHans Verkuil  */
__vb2_init_fileio(struct vb2_queue * q,int read)26257952be9bSHans Verkuil static int __vb2_init_fileio(struct vb2_queue *q, int read)
26267952be9bSHans Verkuil {
26277952be9bSHans Verkuil 	struct vb2_fileio_data *fileio;
26287952be9bSHans Verkuil 	int i, ret;
26297952be9bSHans Verkuil 	unsigned int count = 0;
26307952be9bSHans Verkuil 
26317952be9bSHans Verkuil 	/*
26327952be9bSHans Verkuil 	 * Sanity check
26337952be9bSHans Verkuil 	 */
26347952be9bSHans Verkuil 	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
26357952be9bSHans Verkuil 		    (!read && !(q->io_modes & VB2_WRITE))))
26367952be9bSHans Verkuil 		return -EINVAL;
26377952be9bSHans Verkuil 
26387952be9bSHans Verkuil 	/*
26397952be9bSHans Verkuil 	 * Check if device supports mapping buffers to kernel virtual space.
26407952be9bSHans Verkuil 	 */
26417952be9bSHans Verkuil 	if (!q->mem_ops->vaddr)
26427952be9bSHans Verkuil 		return -EBUSY;
26437952be9bSHans Verkuil 
26447952be9bSHans Verkuil 	/*
26457952be9bSHans Verkuil 	 * Check if streaming api has not been already activated.
26467952be9bSHans Verkuil 	 */
26477952be9bSHans Verkuil 	if (q->streaming || q->num_buffers > 0)
26487952be9bSHans Verkuil 		return -EBUSY;
26497952be9bSHans Verkuil 
26507952be9bSHans Verkuil 	/*
2651390a71e3SHans Verkuil 	 * Start with q->min_buffers_needed + 1, driver can increase it in
2652390a71e3SHans Verkuil 	 * queue_setup()
2653390a71e3SHans Verkuil 	 *
2654390a71e3SHans Verkuil 	 * 'min_buffers_needed' buffers need to be queued up before you
2655390a71e3SHans Verkuil 	 * can start streaming, plus 1 for userspace (or in this case,
2656390a71e3SHans Verkuil 	 * kernelspace) processing.
26577952be9bSHans Verkuil 	 */
2658390a71e3SHans Verkuil 	count = max(2, q->min_buffers_needed + 1);
26597952be9bSHans Verkuil 
2660b820935bSLaurent Pinchart 	dprintk(q, 3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
26617952be9bSHans Verkuil 		(read) ? "read" : "write", count, q->fileio_read_once,
26627952be9bSHans Verkuil 		q->fileio_write_immediately);
26637952be9bSHans Verkuil 
26647952be9bSHans Verkuil 	fileio = kzalloc(sizeof(*fileio), GFP_KERNEL);
26657952be9bSHans Verkuil 	if (fileio == NULL)
26667952be9bSHans Verkuil 		return -ENOMEM;
26677952be9bSHans Verkuil 
26687952be9bSHans Verkuil 	fileio->read_once = q->fileio_read_once;
26697952be9bSHans Verkuil 	fileio->write_immediately = q->fileio_write_immediately;
26707952be9bSHans Verkuil 
26717952be9bSHans Verkuil 	/*
26727952be9bSHans Verkuil 	 * Request buffers and use MMAP type to force driver
26737952be9bSHans Verkuil 	 * to allocate buffers by itself.
26747952be9bSHans Verkuil 	 */
26757952be9bSHans Verkuil 	fileio->count = count;
26767952be9bSHans Verkuil 	fileio->memory = VB2_MEMORY_MMAP;
26777952be9bSHans Verkuil 	fileio->type = q->type;
26787952be9bSHans Verkuil 	q->fileio = fileio;
2679b00a9e59SSergey Senozhatsky 	ret = vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
26807952be9bSHans Verkuil 	if (ret)
26817952be9bSHans Verkuil 		goto err_kfree;
26827952be9bSHans Verkuil 
26837952be9bSHans Verkuil 	/*
26847952be9bSHans Verkuil 	 * Check if plane_count is correct
26857952be9bSHans Verkuil 	 * (multiplane buffers are not supported).
26867952be9bSHans Verkuil 	 */
26877952be9bSHans Verkuil 	if (q->bufs[0]->num_planes != 1) {
26887952be9bSHans Verkuil 		ret = -EBUSY;
26897952be9bSHans Verkuil 		goto err_reqbufs;
26907952be9bSHans Verkuil 	}
26917952be9bSHans Verkuil 
26927952be9bSHans Verkuil 	/*
26937952be9bSHans Verkuil 	 * Get kernel address of each buffer.
26947952be9bSHans Verkuil 	 */
26957952be9bSHans Verkuil 	for (i = 0; i < q->num_buffers; i++) {
26967952be9bSHans Verkuil 		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
26977952be9bSHans Verkuil 		if (fileio->bufs[i].vaddr == NULL) {
26987952be9bSHans Verkuil 			ret = -EINVAL;
26997952be9bSHans Verkuil 			goto err_reqbufs;
27007952be9bSHans Verkuil 		}
27017952be9bSHans Verkuil 		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
27027952be9bSHans Verkuil 	}
27037952be9bSHans Verkuil 
27047952be9bSHans Verkuil 	/*
27057952be9bSHans Verkuil 	 * Read mode requires pre queuing of all buffers.
27067952be9bSHans Verkuil 	 */
27077952be9bSHans Verkuil 	if (read) {
27087952be9bSHans Verkuil 		/*
27097952be9bSHans Verkuil 		 * Queue all buffers.
27107952be9bSHans Verkuil 		 */
27117952be9bSHans Verkuil 		for (i = 0; i < q->num_buffers; i++) {
2712fd89e0bbSHans Verkuil 			ret = vb2_core_qbuf(q, i, NULL, NULL);
27137952be9bSHans Verkuil 			if (ret)
27147952be9bSHans Verkuil 				goto err_reqbufs;
27157952be9bSHans Verkuil 			fileio->bufs[i].queued = 1;
27167952be9bSHans Verkuil 		}
27177952be9bSHans Verkuil 		/*
27187952be9bSHans Verkuil 		 * All buffers have been queued, so mark that by setting
27197952be9bSHans Verkuil 		 * initial_index to q->num_buffers
27207952be9bSHans Verkuil 		 */
27217952be9bSHans Verkuil 		fileio->initial_index = q->num_buffers;
27227952be9bSHans Verkuil 		fileio->cur_index = q->num_buffers;
27237952be9bSHans Verkuil 	}
27247952be9bSHans Verkuil 
27257952be9bSHans Verkuil 	/*
27267952be9bSHans Verkuil 	 * Start streaming.
27277952be9bSHans Verkuil 	 */
27287952be9bSHans Verkuil 	ret = vb2_core_streamon(q, q->type);
27297952be9bSHans Verkuil 	if (ret)
27307952be9bSHans Verkuil 		goto err_reqbufs;
27317952be9bSHans Verkuil 
27327952be9bSHans Verkuil 	return ret;
27337952be9bSHans Verkuil 
27347952be9bSHans Verkuil err_reqbufs:
27357952be9bSHans Verkuil 	fileio->count = 0;
2736b00a9e59SSergey Senozhatsky 	vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
27377952be9bSHans Verkuil 
27387952be9bSHans Verkuil err_kfree:
27397952be9bSHans Verkuil 	q->fileio = NULL;
27407952be9bSHans Verkuil 	kfree(fileio);
27417952be9bSHans Verkuil 	return ret;
27427952be9bSHans Verkuil }
27437952be9bSHans Verkuil 
27447952be9bSHans Verkuil /*
27457952be9bSHans Verkuil  * __vb2_cleanup_fileio() - free resourced used by file io emulator
27467952be9bSHans Verkuil  * @q:		videobuf2 queue
27477952be9bSHans Verkuil  */
__vb2_cleanup_fileio(struct vb2_queue * q)27487952be9bSHans Verkuil static int __vb2_cleanup_fileio(struct vb2_queue *q)
27497952be9bSHans Verkuil {
27507952be9bSHans Verkuil 	struct vb2_fileio_data *fileio = q->fileio;
27517952be9bSHans Verkuil 
27527952be9bSHans Verkuil 	if (fileio) {
27537952be9bSHans Verkuil 		vb2_core_streamoff(q, q->type);
27547952be9bSHans Verkuil 		q->fileio = NULL;
27557952be9bSHans Verkuil 		fileio->count = 0;
2756b00a9e59SSergey Senozhatsky 		vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
27577952be9bSHans Verkuil 		kfree(fileio);
2758b820935bSLaurent Pinchart 		dprintk(q, 3, "file io emulator closed\n");
27597952be9bSHans Verkuil 	}
27607952be9bSHans Verkuil 	return 0;
27617952be9bSHans Verkuil }
27627952be9bSHans Verkuil 
27637952be9bSHans Verkuil /*
27647952be9bSHans Verkuil  * __vb2_perform_fileio() - perform a single file io (read or write) operation
27657952be9bSHans Verkuil  * @q:		videobuf2 queue
27667952be9bSHans Verkuil  * @data:	pointed to target userspace buffer
27677952be9bSHans Verkuil  * @count:	number of bytes to read or write
27687952be9bSHans Verkuil  * @ppos:	file handle position tracking pointer
27697952be9bSHans Verkuil  * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
27707952be9bSHans Verkuil  * @read:	access mode selector (1 means read, 0 means write)
27717952be9bSHans Verkuil  */
__vb2_perform_fileio(struct vb2_queue * q,char __user * data,size_t count,loff_t * ppos,int nonblock,int read)27727952be9bSHans Verkuil static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
27737952be9bSHans Verkuil 		loff_t *ppos, int nonblock, int read)
27747952be9bSHans Verkuil {
27757952be9bSHans Verkuil 	struct vb2_fileio_data *fileio;
27767952be9bSHans Verkuil 	struct vb2_fileio_buf *buf;
27777952be9bSHans Verkuil 	bool is_multiplanar = q->is_multiplanar;
27787952be9bSHans Verkuil 	/*
27797952be9bSHans Verkuil 	 * When using write() to write data to an output video node the vb2 core
27807952be9bSHans Verkuil 	 * should copy timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
27817952be9bSHans Verkuil 	 * else is able to provide this information with the write() operation.
27827952be9bSHans Verkuil 	 */
27837952be9bSHans Verkuil 	bool copy_timestamp = !read && q->copy_timestamp;
27847952be9bSHans Verkuil 	unsigned index;
27857952be9bSHans Verkuil 	int ret;
27867952be9bSHans Verkuil 
2787b820935bSLaurent Pinchart 	dprintk(q, 3, "mode %s, offset %ld, count %zd, %sblocking\n",
27887952be9bSHans Verkuil 		read ? "read" : "write", (long)*ppos, count,
27897952be9bSHans Verkuil 		nonblock ? "non" : "");
27907952be9bSHans Verkuil 
27917952be9bSHans Verkuil 	if (!data)
27927952be9bSHans Verkuil 		return -EINVAL;
27937952be9bSHans Verkuil 
2794d65842f7SHans Verkuil 	if (q->waiting_in_dqbuf) {
2795b820935bSLaurent Pinchart 		dprintk(q, 3, "another dup()ped fd is %s\n",
2796d65842f7SHans Verkuil 			read ? "reading" : "writing");
2797d65842f7SHans Verkuil 		return -EBUSY;
2798d65842f7SHans Verkuil 	}
2799d65842f7SHans Verkuil 
28007952be9bSHans Verkuil 	/*
28017952be9bSHans Verkuil 	 * Initialize emulator on first call.
28027952be9bSHans Verkuil 	 */
28037952be9bSHans Verkuil 	if (!vb2_fileio_is_active(q)) {
28047952be9bSHans Verkuil 		ret = __vb2_init_fileio(q, read);
2805b820935bSLaurent Pinchart 		dprintk(q, 3, "vb2_init_fileio result: %d\n", ret);
28067952be9bSHans Verkuil 		if (ret)
28077952be9bSHans Verkuil 			return ret;
28087952be9bSHans Verkuil 	}
28097952be9bSHans Verkuil 	fileio = q->fileio;
28107952be9bSHans Verkuil 
28117952be9bSHans Verkuil 	/*
28127952be9bSHans Verkuil 	 * Check if we need to dequeue the buffer.
28137952be9bSHans Verkuil 	 */
28147952be9bSHans Verkuil 	index = fileio->cur_index;
28157952be9bSHans Verkuil 	if (index >= q->num_buffers) {
28167952be9bSHans Verkuil 		struct vb2_buffer *b;
28177952be9bSHans Verkuil 
28187952be9bSHans Verkuil 		/*
28197952be9bSHans Verkuil 		 * Call vb2_dqbuf to get buffer back.
28207952be9bSHans Verkuil 		 */
28217952be9bSHans Verkuil 		ret = vb2_core_dqbuf(q, &index, NULL, nonblock);
2822b820935bSLaurent Pinchart 		dprintk(q, 5, "vb2_dqbuf result: %d\n", ret);
28237952be9bSHans Verkuil 		if (ret)
28247952be9bSHans Verkuil 			return ret;
28257952be9bSHans Verkuil 		fileio->dq_count += 1;
28267952be9bSHans Verkuil 
28277952be9bSHans Verkuil 		fileio->cur_index = index;
28287952be9bSHans Verkuil 		buf = &fileio->bufs[index];
28297952be9bSHans Verkuil 		b = q->bufs[index];
28307952be9bSHans Verkuil 
28317952be9bSHans Verkuil 		/*
28327952be9bSHans Verkuil 		 * Get number of bytes filled by the driver
28337952be9bSHans Verkuil 		 */
28347952be9bSHans Verkuil 		buf->pos = 0;
28357952be9bSHans Verkuil 		buf->queued = 0;
28367952be9bSHans Verkuil 		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
28377952be9bSHans Verkuil 				 : vb2_plane_size(q->bufs[index], 0);
28387952be9bSHans Verkuil 		/* Compensate for data_offset on read in the multiplanar case. */
28397952be9bSHans Verkuil 		if (is_multiplanar && read &&
28407952be9bSHans Verkuil 				b->planes[0].data_offset < buf->size) {
28417952be9bSHans Verkuil 			buf->pos = b->planes[0].data_offset;
28427952be9bSHans Verkuil 			buf->size -= buf->pos;
28437952be9bSHans Verkuil 		}
28447952be9bSHans Verkuil 	} else {
28457952be9bSHans Verkuil 		buf = &fileio->bufs[index];
28467952be9bSHans Verkuil 	}
28477952be9bSHans Verkuil 
28487952be9bSHans Verkuil 	/*
28497952be9bSHans Verkuil 	 * Limit count on last few bytes of the buffer.
28507952be9bSHans Verkuil 	 */
28517952be9bSHans Verkuil 	if (buf->pos + count > buf->size) {
28527952be9bSHans Verkuil 		count = buf->size - buf->pos;
2853b820935bSLaurent Pinchart 		dprintk(q, 5, "reducing read count: %zd\n", count);
28547952be9bSHans Verkuil 	}
28557952be9bSHans Verkuil 
28567952be9bSHans Verkuil 	/*
28577952be9bSHans Verkuil 	 * Transfer data to userspace.
28587952be9bSHans Verkuil 	 */
2859b820935bSLaurent Pinchart 	dprintk(q, 3, "copying %zd bytes - buffer %d, offset %u\n",
28607952be9bSHans Verkuil 		count, index, buf->pos);
28617952be9bSHans Verkuil 	if (read)
28627952be9bSHans Verkuil 		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
28637952be9bSHans Verkuil 	else
28647952be9bSHans Verkuil 		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
28657952be9bSHans Verkuil 	if (ret) {
2866b820935bSLaurent Pinchart 		dprintk(q, 3, "error copying data\n");
28677952be9bSHans Verkuil 		return -EFAULT;
28687952be9bSHans Verkuil 	}
28697952be9bSHans Verkuil 
28707952be9bSHans Verkuil 	/*
28717952be9bSHans Verkuil 	 * Update counters.
28727952be9bSHans Verkuil 	 */
28737952be9bSHans Verkuil 	buf->pos += count;
28747952be9bSHans Verkuil 	*ppos += count;
28757952be9bSHans Verkuil 
28767952be9bSHans Verkuil 	/*
28777952be9bSHans Verkuil 	 * Queue next buffer if required.
28787952be9bSHans Verkuil 	 */
28797952be9bSHans Verkuil 	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
28807952be9bSHans Verkuil 		struct vb2_buffer *b = q->bufs[index];
28817952be9bSHans Verkuil 
28827952be9bSHans Verkuil 		/*
28837952be9bSHans Verkuil 		 * Check if this is the last buffer to read.
28847952be9bSHans Verkuil 		 */
28857952be9bSHans Verkuil 		if (read && fileio->read_once && fileio->dq_count == 1) {
2886b820935bSLaurent Pinchart 			dprintk(q, 3, "read limit reached\n");
28877952be9bSHans Verkuil 			return __vb2_cleanup_fileio(q);
28887952be9bSHans Verkuil 		}
28897952be9bSHans Verkuil 
28907952be9bSHans Verkuil 		/*
28917952be9bSHans Verkuil 		 * Call vb2_qbuf and give buffer to the driver.
28927952be9bSHans Verkuil 		 */
28937952be9bSHans Verkuil 		b->planes[0].bytesused = buf->pos;
28947952be9bSHans Verkuil 
28957952be9bSHans Verkuil 		if (copy_timestamp)
28967952be9bSHans Verkuil 			b->timestamp = ktime_get_ns();
2897fd89e0bbSHans Verkuil 		ret = vb2_core_qbuf(q, index, NULL, NULL);
2898b820935bSLaurent Pinchart 		dprintk(q, 5, "vb2_dbuf result: %d\n", ret);
28997952be9bSHans Verkuil 		if (ret)
29007952be9bSHans Verkuil 			return ret;
29017952be9bSHans Verkuil 
29027952be9bSHans Verkuil 		/*
29037952be9bSHans Verkuil 		 * Buffer has been queued, update the status
29047952be9bSHans Verkuil 		 */
29057952be9bSHans Verkuil 		buf->pos = 0;
29067952be9bSHans Verkuil 		buf->queued = 1;
29077952be9bSHans Verkuil 		buf->size = vb2_plane_size(q->bufs[index], 0);
29087952be9bSHans Verkuil 		fileio->q_count += 1;
29097952be9bSHans Verkuil 		/*
29107952be9bSHans Verkuil 		 * If we are queuing up buffers for the first time, then
29117952be9bSHans Verkuil 		 * increase initial_index by one.
29127952be9bSHans Verkuil 		 */
29137952be9bSHans Verkuil 		if (fileio->initial_index < q->num_buffers)
29147952be9bSHans Verkuil 			fileio->initial_index++;
29157952be9bSHans Verkuil 		/*
29167952be9bSHans Verkuil 		 * The next buffer to use is either a buffer that's going to be
29177952be9bSHans Verkuil 		 * queued for the first time (initial_index < q->num_buffers)
29187952be9bSHans Verkuil 		 * or it is equal to q->num_buffers, meaning that the next
29197952be9bSHans Verkuil 		 * time we need to dequeue a buffer since we've now queued up
29207952be9bSHans Verkuil 		 * all the 'first time' buffers.
29217952be9bSHans Verkuil 		 */
29227952be9bSHans Verkuil 		fileio->cur_index = fileio->initial_index;
29237952be9bSHans Verkuil 	}
29247952be9bSHans Verkuil 
29257952be9bSHans Verkuil 	/*
29267952be9bSHans Verkuil 	 * Return proper number of bytes processed.
29277952be9bSHans Verkuil 	 */
29287952be9bSHans Verkuil 	if (ret == 0)
29297952be9bSHans Verkuil 		ret = count;
29307952be9bSHans Verkuil 	return ret;
29317952be9bSHans Verkuil }
29327952be9bSHans Verkuil 
vb2_read(struct vb2_queue * q,char __user * data,size_t count,loff_t * ppos,int nonblocking)29337952be9bSHans Verkuil size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
29347952be9bSHans Verkuil 		loff_t *ppos, int nonblocking)
29357952be9bSHans Verkuil {
29367952be9bSHans Verkuil 	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
29377952be9bSHans Verkuil }
29387952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_read);
29397952be9bSHans Verkuil 
vb2_write(struct vb2_queue * q,const char __user * data,size_t count,loff_t * ppos,int nonblocking)29407952be9bSHans Verkuil size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
29417952be9bSHans Verkuil 		loff_t *ppos, int nonblocking)
29427952be9bSHans Verkuil {
29437952be9bSHans Verkuil 	return __vb2_perform_fileio(q, (char __user *) data, count,
29447952be9bSHans Verkuil 							ppos, nonblocking, 0);
29457952be9bSHans Verkuil }
29467952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_write);
29477952be9bSHans Verkuil 
29487952be9bSHans Verkuil struct vb2_threadio_data {
29497952be9bSHans Verkuil 	struct task_struct *thread;
29507952be9bSHans Verkuil 	vb2_thread_fnc fnc;
29517952be9bSHans Verkuil 	void *priv;
29527952be9bSHans Verkuil 	bool stop;
29537952be9bSHans Verkuil };
29547952be9bSHans Verkuil 
vb2_thread(void * data)29557952be9bSHans Verkuil static int vb2_thread(void *data)
29567952be9bSHans Verkuil {
29577952be9bSHans Verkuil 	struct vb2_queue *q = data;
29587952be9bSHans Verkuil 	struct vb2_threadio_data *threadio = q->threadio;
29597952be9bSHans Verkuil 	bool copy_timestamp = false;
29607952be9bSHans Verkuil 	unsigned prequeue = 0;
29617952be9bSHans Verkuil 	unsigned index = 0;
29627952be9bSHans Verkuil 	int ret = 0;
29637952be9bSHans Verkuil 
29647952be9bSHans Verkuil 	if (q->is_output) {
29657952be9bSHans Verkuil 		prequeue = q->num_buffers;
29667952be9bSHans Verkuil 		copy_timestamp = q->copy_timestamp;
29677952be9bSHans Verkuil 	}
29687952be9bSHans Verkuil 
29697952be9bSHans Verkuil 	set_freezable();
29707952be9bSHans Verkuil 
29717952be9bSHans Verkuil 	for (;;) {
29727952be9bSHans Verkuil 		struct vb2_buffer *vb;
29737952be9bSHans Verkuil 
29747952be9bSHans Verkuil 		/*
29757952be9bSHans Verkuil 		 * Call vb2_dqbuf to get buffer back.
29767952be9bSHans Verkuil 		 */
29777952be9bSHans Verkuil 		if (prequeue) {
29787952be9bSHans Verkuil 			vb = q->bufs[index++];
29797952be9bSHans Verkuil 			prequeue--;
29807952be9bSHans Verkuil 		} else {
29817952be9bSHans Verkuil 			call_void_qop(q, wait_finish, q);
29827952be9bSHans Verkuil 			if (!threadio->stop)
29837952be9bSHans Verkuil 				ret = vb2_core_dqbuf(q, &index, NULL, 0);
29847952be9bSHans Verkuil 			call_void_qop(q, wait_prepare, q);
2985b820935bSLaurent Pinchart 			dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
29867952be9bSHans Verkuil 			if (!ret)
29877952be9bSHans Verkuil 				vb = q->bufs[index];
29887952be9bSHans Verkuil 		}
29897952be9bSHans Verkuil 		if (ret || threadio->stop)
29907952be9bSHans Verkuil 			break;
29917952be9bSHans Verkuil 		try_to_freeze();
29927952be9bSHans Verkuil 
29937952be9bSHans Verkuil 		if (vb->state != VB2_BUF_STATE_ERROR)
29947952be9bSHans Verkuil 			if (threadio->fnc(vb, threadio->priv))
29957952be9bSHans Verkuil 				break;
29967952be9bSHans Verkuil 		call_void_qop(q, wait_finish, q);
29977952be9bSHans Verkuil 		if (copy_timestamp)
29987952be9bSHans Verkuil 			vb->timestamp = ktime_get_ns();
29997952be9bSHans Verkuil 		if (!threadio->stop)
3000fd89e0bbSHans Verkuil 			ret = vb2_core_qbuf(q, vb->index, NULL, NULL);
30017952be9bSHans Verkuil 		call_void_qop(q, wait_prepare, q);
30027952be9bSHans Verkuil 		if (ret || threadio->stop)
30037952be9bSHans Verkuil 			break;
30047952be9bSHans Verkuil 	}
30057952be9bSHans Verkuil 
30067952be9bSHans Verkuil 	/* Hmm, linux becomes *very* unhappy without this ... */
30077952be9bSHans Verkuil 	while (!kthread_should_stop()) {
30087952be9bSHans Verkuil 		set_current_state(TASK_INTERRUPTIBLE);
30097952be9bSHans Verkuil 		schedule();
30107952be9bSHans Verkuil 	}
30117952be9bSHans Verkuil 	return 0;
30127952be9bSHans Verkuil }
30137952be9bSHans Verkuil 
30147952be9bSHans Verkuil /*
30157952be9bSHans Verkuil  * This function should not be used for anything else but the videobuf2-dvb
30167952be9bSHans Verkuil  * support. If you think you have another good use-case for this, then please
30177952be9bSHans Verkuil  * contact the linux-media mailinglist first.
30187952be9bSHans Verkuil  */
vb2_thread_start(struct vb2_queue * q,vb2_thread_fnc fnc,void * priv,const char * thread_name)30197952be9bSHans Verkuil int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
30207952be9bSHans Verkuil 		     const char *thread_name)
30217952be9bSHans Verkuil {
30227952be9bSHans Verkuil 	struct vb2_threadio_data *threadio;
30237952be9bSHans Verkuil 	int ret = 0;
30247952be9bSHans Verkuil 
30257952be9bSHans Verkuil 	if (q->threadio)
30267952be9bSHans Verkuil 		return -EBUSY;
30277952be9bSHans Verkuil 	if (vb2_is_busy(q))
30287952be9bSHans Verkuil 		return -EBUSY;
30297952be9bSHans Verkuil 	if (WARN_ON(q->fileio))
30307952be9bSHans Verkuil 		return -EBUSY;
30317952be9bSHans Verkuil 
30327952be9bSHans Verkuil 	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
30337952be9bSHans Verkuil 	if (threadio == NULL)
30347952be9bSHans Verkuil 		return -ENOMEM;
30357952be9bSHans Verkuil 	threadio->fnc = fnc;
30367952be9bSHans Verkuil 	threadio->priv = priv;
30377952be9bSHans Verkuil 
30387952be9bSHans Verkuil 	ret = __vb2_init_fileio(q, !q->is_output);
3039b820935bSLaurent Pinchart 	dprintk(q, 3, "file io: vb2_init_fileio result: %d\n", ret);
30407952be9bSHans Verkuil 	if (ret)
30417952be9bSHans Verkuil 		goto nomem;
30427952be9bSHans Verkuil 	q->threadio = threadio;
30437952be9bSHans Verkuil 	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
30447952be9bSHans Verkuil 	if (IS_ERR(threadio->thread)) {
30457952be9bSHans Verkuil 		ret = PTR_ERR(threadio->thread);
30467952be9bSHans Verkuil 		threadio->thread = NULL;
30477952be9bSHans Verkuil 		goto nothread;
30487952be9bSHans Verkuil 	}
30497952be9bSHans Verkuil 	return 0;
30507952be9bSHans Verkuil 
30517952be9bSHans Verkuil nothread:
30527952be9bSHans Verkuil 	__vb2_cleanup_fileio(q);
30537952be9bSHans Verkuil nomem:
30547952be9bSHans Verkuil 	kfree(threadio);
30557952be9bSHans Verkuil 	return ret;
30567952be9bSHans Verkuil }
30577952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_thread_start);
30587952be9bSHans Verkuil 
vb2_thread_stop(struct vb2_queue * q)30597952be9bSHans Verkuil int vb2_thread_stop(struct vb2_queue *q)
30607952be9bSHans Verkuil {
30617952be9bSHans Verkuil 	struct vb2_threadio_data *threadio = q->threadio;
30627952be9bSHans Verkuil 	int err;
30637952be9bSHans Verkuil 
30647952be9bSHans Verkuil 	if (threadio == NULL)
30657952be9bSHans Verkuil 		return 0;
30667952be9bSHans Verkuil 	threadio->stop = true;
30677952be9bSHans Verkuil 	/* Wake up all pending sleeps in the thread */
30687952be9bSHans Verkuil 	vb2_queue_error(q);
30697952be9bSHans Verkuil 	err = kthread_stop(threadio->thread);
30707952be9bSHans Verkuil 	__vb2_cleanup_fileio(q);
30717952be9bSHans Verkuil 	threadio->thread = NULL;
30727952be9bSHans Verkuil 	kfree(threadio);
30737952be9bSHans Verkuil 	q->threadio = NULL;
30747952be9bSHans Verkuil 	return err;
30757952be9bSHans Verkuil }
30767952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_thread_stop);
30777952be9bSHans Verkuil 
30787952be9bSHans Verkuil MODULE_DESCRIPTION("Media buffer core framework");
30797952be9bSHans Verkuil MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
30807952be9bSHans Verkuil MODULE_LICENSE("GPL");
308116b0314aSGreg Kroah-Hartman MODULE_IMPORT_NS(DMA_BUF);
3082