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;
305*7af8d697SYunke Cao p->bytesused = 0;
306*7af8d697SYunke Cao p->length = 0;
307*7af8d697SYunke Cao p->m.fd = 0;
308*7af8d697SYunke Cao p->data_offset = 0;
3097952be9bSHans Verkuil }
3107952be9bSHans Verkuil
3117952be9bSHans Verkuil /*
3127952be9bSHans Verkuil * __vb2_buf_dmabuf_put() - release memory associated with
3137952be9bSHans Verkuil * a DMABUF shared buffer
3147952be9bSHans Verkuil */
__vb2_buf_dmabuf_put(struct vb2_buffer * vb)3157952be9bSHans Verkuil static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
3167952be9bSHans Verkuil {
3177952be9bSHans Verkuil unsigned int plane;
3187952be9bSHans Verkuil
3197952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane)
3207952be9bSHans Verkuil __vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
3217952be9bSHans Verkuil }
3227952be9bSHans Verkuil
3237952be9bSHans Verkuil /*
32438a417e8SSergey Senozhatsky * __vb2_buf_mem_prepare() - call ->prepare() on buffer's private memory
32538a417e8SSergey Senozhatsky * to sync caches
32638a417e8SSergey Senozhatsky */
__vb2_buf_mem_prepare(struct vb2_buffer * vb)32738a417e8SSergey Senozhatsky static void __vb2_buf_mem_prepare(struct vb2_buffer *vb)
32838a417e8SSergey Senozhatsky {
32938a417e8SSergey Senozhatsky unsigned int plane;
33038a417e8SSergey Senozhatsky
331093067edSSergey Senozhatsky if (vb->synced)
332093067edSSergey Senozhatsky return;
333093067edSSergey Senozhatsky
33438a417e8SSergey Senozhatsky vb->synced = 1;
3354dbe7eabSSergey Senozhatsky for (plane = 0; plane < vb->num_planes; ++plane)
3364dbe7eabSSergey Senozhatsky call_void_memop(vb, prepare, vb->planes[plane].mem_priv);
33738a417e8SSergey Senozhatsky }
33838a417e8SSergey Senozhatsky
33938a417e8SSergey Senozhatsky /*
34038a417e8SSergey Senozhatsky * __vb2_buf_mem_finish() - call ->finish on buffer's private memory
34138a417e8SSergey Senozhatsky * to sync caches
34238a417e8SSergey Senozhatsky */
__vb2_buf_mem_finish(struct vb2_buffer * vb)34338a417e8SSergey Senozhatsky static void __vb2_buf_mem_finish(struct vb2_buffer *vb)
34438a417e8SSergey Senozhatsky {
34538a417e8SSergey Senozhatsky unsigned int plane;
34638a417e8SSergey Senozhatsky
347093067edSSergey Senozhatsky if (!vb->synced)
348093067edSSergey Senozhatsky return;
349093067edSSergey Senozhatsky
35038a417e8SSergey Senozhatsky vb->synced = 0;
3514dbe7eabSSergey Senozhatsky for (plane = 0; plane < vb->num_planes; ++plane)
3524dbe7eabSSergey Senozhatsky call_void_memop(vb, finish, vb->planes[plane].mem_priv);
35338a417e8SSergey Senozhatsky }
35438a417e8SSergey Senozhatsky
35538a417e8SSergey Senozhatsky /*
3567952be9bSHans Verkuil * __setup_offsets() - setup unique offsets ("cookies") for every plane in
3577952be9bSHans Verkuil * the buffer.
3587952be9bSHans Verkuil */
__setup_offsets(struct vb2_buffer * vb)3597952be9bSHans Verkuil static void __setup_offsets(struct vb2_buffer *vb)
3607952be9bSHans Verkuil {
3617952be9bSHans Verkuil struct vb2_queue *q = vb->vb2_queue;
3627952be9bSHans Verkuil unsigned int plane;
3637952be9bSHans Verkuil unsigned long off = 0;
3647952be9bSHans Verkuil
3657952be9bSHans Verkuil if (vb->index) {
3667952be9bSHans Verkuil struct vb2_buffer *prev = q->bufs[vb->index - 1];
3677952be9bSHans Verkuil struct vb2_plane *p = &prev->planes[prev->num_planes - 1];
3687952be9bSHans Verkuil
3697952be9bSHans Verkuil off = PAGE_ALIGN(p->m.offset + p->length);
3707952be9bSHans Verkuil }
3717952be9bSHans Verkuil
3727952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane) {
3737952be9bSHans Verkuil vb->planes[plane].m.offset = off;
3747952be9bSHans Verkuil
375b820935bSLaurent Pinchart dprintk(q, 3, "buffer %d, plane %d offset 0x%08lx\n",
3767952be9bSHans Verkuil vb->index, plane, off);
3777952be9bSHans Verkuil
3787952be9bSHans Verkuil off += vb->planes[plane].length;
3797952be9bSHans Verkuil off = PAGE_ALIGN(off);
3807952be9bSHans Verkuil }
3817952be9bSHans Verkuil }
3827952be9bSHans Verkuil
init_buffer_cache_hints(struct vb2_queue * q,struct vb2_buffer * vb)3830a12d652SSergey Senozhatsky static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
3840a12d652SSergey Senozhatsky {
3850a12d652SSergey Senozhatsky /*
3860a12d652SSergey Senozhatsky * DMA exporter should take care of cache syncs, so we can avoid
3870a12d652SSergey Senozhatsky * explicit ->prepare()/->finish() syncs. For other ->memory types
3880a12d652SSergey Senozhatsky * we always need ->prepare() or/and ->finish() cache sync.
3890a12d652SSergey Senozhatsky */
3900a12d652SSergey Senozhatsky if (q->memory == VB2_MEMORY_DMABUF) {
3910a12d652SSergey Senozhatsky vb->skip_cache_sync_on_finish = 1;
3920a12d652SSergey Senozhatsky vb->skip_cache_sync_on_prepare = 1;
3930a12d652SSergey Senozhatsky return;
3940a12d652SSergey Senozhatsky }
3950a12d652SSergey Senozhatsky
3960a12d652SSergey Senozhatsky /*
3970a12d652SSergey Senozhatsky * ->finish() cache sync can be avoided when queue direction is
3980a12d652SSergey Senozhatsky * TO_DEVICE.
3990a12d652SSergey Senozhatsky */
4000a12d652SSergey Senozhatsky if (q->dma_dir == DMA_TO_DEVICE)
4010a12d652SSergey Senozhatsky vb->skip_cache_sync_on_finish = 1;
4020a12d652SSergey Senozhatsky }
4030a12d652SSergey Senozhatsky
4047952be9bSHans Verkuil /*
4053e947c36SHans Verkuil * __vb2_queue_alloc() - allocate vb2 buffer structures and (for MMAP type)
4067952be9bSHans Verkuil * video buffer memory for all buffers/planes on the queue and initializes the
4077952be9bSHans Verkuil * queue
4087952be9bSHans Verkuil *
4097952be9bSHans Verkuil * Returns the number of buffers successfully allocated.
4107952be9bSHans 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])4117952be9bSHans Verkuil static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
4127952be9bSHans Verkuil unsigned int num_buffers, unsigned int num_planes,
4137952be9bSHans Verkuil const unsigned plane_sizes[VB2_MAX_PLANES])
4147952be9bSHans Verkuil {
4157952be9bSHans Verkuil unsigned int buffer, plane;
4167952be9bSHans Verkuil struct vb2_buffer *vb;
4177952be9bSHans Verkuil int ret;
4187952be9bSHans Verkuil
4197952be9bSHans Verkuil /* Ensure that q->num_buffers+num_buffers is below VB2_MAX_FRAME */
4207952be9bSHans Verkuil num_buffers = min_t(unsigned int, num_buffers,
4217952be9bSHans Verkuil VB2_MAX_FRAME - q->num_buffers);
4227952be9bSHans Verkuil
4237952be9bSHans Verkuil for (buffer = 0; buffer < num_buffers; ++buffer) {
4243e947c36SHans Verkuil /* Allocate vb2 buffer structures */
4257952be9bSHans Verkuil vb = kzalloc(q->buf_struct_size, GFP_KERNEL);
4267952be9bSHans Verkuil if (!vb) {
427b820935bSLaurent Pinchart dprintk(q, 1, "memory alloc for buffer struct failed\n");
4287952be9bSHans Verkuil break;
4297952be9bSHans Verkuil }
4307952be9bSHans Verkuil
4317952be9bSHans Verkuil vb->state = VB2_BUF_STATE_DEQUEUED;
4327952be9bSHans Verkuil vb->vb2_queue = q;
4337952be9bSHans Verkuil vb->num_planes = num_planes;
4347952be9bSHans Verkuil vb->index = q->num_buffers + buffer;
4357952be9bSHans Verkuil vb->type = q->type;
4367952be9bSHans Verkuil vb->memory = memory;
4370a12d652SSergey Senozhatsky init_buffer_cache_hints(q, vb);
4387952be9bSHans Verkuil for (plane = 0; plane < num_planes; ++plane) {
4397952be9bSHans Verkuil vb->planes[plane].length = plane_sizes[plane];
4407952be9bSHans Verkuil vb->planes[plane].min_length = plane_sizes[plane];
4417952be9bSHans Verkuil }
4428e013700SHans Verkuil call_void_bufop(q, init_buffer, vb);
4438e013700SHans Verkuil
4447952be9bSHans Verkuil q->bufs[vb->index] = vb;
4457952be9bSHans Verkuil
4467952be9bSHans Verkuil /* Allocate video buffer memory for the MMAP type */
4477952be9bSHans Verkuil if (memory == VB2_MEMORY_MMAP) {
4487952be9bSHans Verkuil ret = __vb2_buf_mem_alloc(vb);
4497952be9bSHans Verkuil if (ret) {
450b820935bSLaurent Pinchart dprintk(q, 1, "failed allocating memory for buffer %d\n",
4517952be9bSHans Verkuil buffer);
4527952be9bSHans Verkuil q->bufs[vb->index] = NULL;
4537952be9bSHans Verkuil kfree(vb);
4547952be9bSHans Verkuil break;
4557952be9bSHans Verkuil }
4567952be9bSHans Verkuil __setup_offsets(vb);
4577952be9bSHans Verkuil /*
4587952be9bSHans Verkuil * Call the driver-provided buffer initialization
4597952be9bSHans Verkuil * callback, if given. An error in initialization
4607952be9bSHans Verkuil * results in queue setup failure.
4617952be9bSHans Verkuil */
4627952be9bSHans Verkuil ret = call_vb_qop(vb, buf_init, vb);
4637952be9bSHans Verkuil if (ret) {
464b820935bSLaurent Pinchart dprintk(q, 1, "buffer %d %p initialization failed\n",
4657952be9bSHans Verkuil buffer, vb);
4667952be9bSHans Verkuil __vb2_buf_mem_free(vb);
4677952be9bSHans Verkuil q->bufs[vb->index] = NULL;
4687952be9bSHans Verkuil kfree(vb);
4697952be9bSHans Verkuil break;
4707952be9bSHans Verkuil }
4717952be9bSHans Verkuil }
4727952be9bSHans Verkuil }
4737952be9bSHans Verkuil
474b820935bSLaurent Pinchart dprintk(q, 3, "allocated %d buffers, %d plane(s) each\n",
4757952be9bSHans Verkuil buffer, num_planes);
4767952be9bSHans Verkuil
4777952be9bSHans Verkuil return buffer;
4787952be9bSHans Verkuil }
4797952be9bSHans Verkuil
4807952be9bSHans Verkuil /*
4817952be9bSHans Verkuil * __vb2_free_mem() - release all video buffer memory for a given queue
4827952be9bSHans Verkuil */
__vb2_free_mem(struct vb2_queue * q,unsigned int buffers)4837952be9bSHans Verkuil static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
4847952be9bSHans Verkuil {
4857952be9bSHans Verkuil unsigned int buffer;
4867952be9bSHans Verkuil struct vb2_buffer *vb;
4877952be9bSHans Verkuil
4887952be9bSHans Verkuil for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
4897952be9bSHans Verkuil ++buffer) {
4907952be9bSHans Verkuil vb = q->bufs[buffer];
4917952be9bSHans Verkuil if (!vb)
4927952be9bSHans Verkuil continue;
4937952be9bSHans Verkuil
4947952be9bSHans Verkuil /* Free MMAP buffers or release USERPTR buffers */
4957952be9bSHans Verkuil if (q->memory == VB2_MEMORY_MMAP)
4967952be9bSHans Verkuil __vb2_buf_mem_free(vb);
4977952be9bSHans Verkuil else if (q->memory == VB2_MEMORY_DMABUF)
4987952be9bSHans Verkuil __vb2_buf_dmabuf_put(vb);
4997952be9bSHans Verkuil else
5007952be9bSHans Verkuil __vb2_buf_userptr_put(vb);
5017952be9bSHans Verkuil }
5027952be9bSHans Verkuil }
5037952be9bSHans Verkuil
5047952be9bSHans Verkuil /*
5057952be9bSHans Verkuil * __vb2_queue_free() - free buffers at the end of the queue - video memory and
5067952be9bSHans Verkuil * related information, if no buffers are left return the queue to an
5077952be9bSHans Verkuil * uninitialized state. Might be called even if the queue has already been freed.
5087952be9bSHans Verkuil */
__vb2_queue_free(struct vb2_queue * q,unsigned int buffers)50901cb370fSHans Verkuil static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
5107952be9bSHans Verkuil {
5117952be9bSHans Verkuil unsigned int buffer;
5127952be9bSHans Verkuil
51301cb370fSHans Verkuil lockdep_assert_held(&q->mmap_lock);
5147952be9bSHans Verkuil
5157952be9bSHans Verkuil /* Call driver-provided cleanup function for each buffer, if provided */
5167952be9bSHans Verkuil for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
5177952be9bSHans Verkuil ++buffer) {
5187952be9bSHans Verkuil struct vb2_buffer *vb = q->bufs[buffer];
5197952be9bSHans Verkuil
5207952be9bSHans Verkuil if (vb && vb->planes[0].mem_priv)
5217952be9bSHans Verkuil call_void_vb_qop(vb, buf_cleanup, vb);
5227952be9bSHans Verkuil }
5237952be9bSHans Verkuil
5247952be9bSHans Verkuil /* Release video buffer memory */
5257952be9bSHans Verkuil __vb2_free_mem(q, buffers);
5267952be9bSHans Verkuil
5277952be9bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
5287952be9bSHans Verkuil /*
5297952be9bSHans Verkuil * Check that all the calls were balances during the life-time of this
5307952be9bSHans Verkuil * queue. If not (or if the debug level is 1 or up), then dump the
5317952be9bSHans Verkuil * counters to the kernel log.
5327952be9bSHans Verkuil */
5337952be9bSHans Verkuil if (q->num_buffers) {
5347952be9bSHans Verkuil bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming ||
535a10b2153SHans Verkuil q->cnt_prepare_streaming != q->cnt_unprepare_streaming ||
5367952be9bSHans Verkuil q->cnt_wait_prepare != q->cnt_wait_finish;
5377952be9bSHans Verkuil
5387952be9bSHans Verkuil if (unbalanced || debug) {
5397952be9bSHans Verkuil pr_info("counters for queue %p:%s\n", q,
5407952be9bSHans Verkuil unbalanced ? " UNBALANCED!" : "");
5417952be9bSHans Verkuil pr_info(" setup: %u start_streaming: %u stop_streaming: %u\n",
5427952be9bSHans Verkuil q->cnt_queue_setup, q->cnt_start_streaming,
5437952be9bSHans Verkuil q->cnt_stop_streaming);
544a10b2153SHans Verkuil pr_info(" prepare_streaming: %u unprepare_streaming: %u\n",
545a10b2153SHans Verkuil q->cnt_prepare_streaming, q->cnt_unprepare_streaming);
5467952be9bSHans Verkuil pr_info(" wait_prepare: %u wait_finish: %u\n",
5477952be9bSHans Verkuil q->cnt_wait_prepare, q->cnt_wait_finish);
5487952be9bSHans Verkuil }
5497952be9bSHans Verkuil q->cnt_queue_setup = 0;
5507952be9bSHans Verkuil q->cnt_wait_prepare = 0;
5517952be9bSHans Verkuil q->cnt_wait_finish = 0;
552a10b2153SHans Verkuil q->cnt_prepare_streaming = 0;
5537952be9bSHans Verkuil q->cnt_start_streaming = 0;
5547952be9bSHans Verkuil q->cnt_stop_streaming = 0;
555a10b2153SHans Verkuil q->cnt_unprepare_streaming = 0;
5567952be9bSHans Verkuil }
5577952be9bSHans Verkuil for (buffer = 0; buffer < q->num_buffers; ++buffer) {
5587952be9bSHans Verkuil struct vb2_buffer *vb = q->bufs[buffer];
5597952be9bSHans Verkuil bool unbalanced = vb->cnt_mem_alloc != vb->cnt_mem_put ||
5607952be9bSHans Verkuil vb->cnt_mem_prepare != vb->cnt_mem_finish ||
5617952be9bSHans Verkuil vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
5627952be9bSHans Verkuil vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
5637952be9bSHans Verkuil vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
5647952be9bSHans Verkuil vb->cnt_buf_queue != vb->cnt_buf_done ||
5657952be9bSHans Verkuil vb->cnt_buf_prepare != vb->cnt_buf_finish ||
5667952be9bSHans Verkuil vb->cnt_buf_init != vb->cnt_buf_cleanup;
5677952be9bSHans Verkuil
5687952be9bSHans Verkuil if (unbalanced || debug) {
5697952be9bSHans Verkuil pr_info(" counters for queue %p, buffer %d:%s\n",
5707952be9bSHans Verkuil q, buffer, unbalanced ? " UNBALANCED!" : "");
5717952be9bSHans Verkuil pr_info(" buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n",
5727952be9bSHans Verkuil vb->cnt_buf_init, vb->cnt_buf_cleanup,
5737952be9bSHans Verkuil vb->cnt_buf_prepare, vb->cnt_buf_finish);
57428d77c21SHans Verkuil pr_info(" buf_out_validate: %u buf_queue: %u buf_done: %u buf_request_complete: %u\n",
57528d77c21SHans Verkuil vb->cnt_buf_out_validate, vb->cnt_buf_queue,
57628d77c21SHans Verkuil vb->cnt_buf_done, vb->cnt_buf_request_complete);
5777952be9bSHans Verkuil pr_info(" alloc: %u put: %u prepare: %u finish: %u mmap: %u\n",
5787952be9bSHans Verkuil vb->cnt_mem_alloc, vb->cnt_mem_put,
5797952be9bSHans Verkuil vb->cnt_mem_prepare, vb->cnt_mem_finish,
5807952be9bSHans Verkuil vb->cnt_mem_mmap);
5817952be9bSHans Verkuil pr_info(" get_userptr: %u put_userptr: %u\n",
5827952be9bSHans Verkuil vb->cnt_mem_get_userptr, vb->cnt_mem_put_userptr);
5837952be9bSHans Verkuil pr_info(" attach_dmabuf: %u detach_dmabuf: %u map_dmabuf: %u unmap_dmabuf: %u\n",
5847952be9bSHans Verkuil vb->cnt_mem_attach_dmabuf, vb->cnt_mem_detach_dmabuf,
5857952be9bSHans Verkuil vb->cnt_mem_map_dmabuf, vb->cnt_mem_unmap_dmabuf);
5867952be9bSHans Verkuil pr_info(" get_dmabuf: %u num_users: %u vaddr: %u cookie: %u\n",
5877952be9bSHans Verkuil vb->cnt_mem_get_dmabuf,
5887952be9bSHans Verkuil vb->cnt_mem_num_users,
5897952be9bSHans Verkuil vb->cnt_mem_vaddr,
5907952be9bSHans Verkuil vb->cnt_mem_cookie);
5917952be9bSHans Verkuil }
5927952be9bSHans Verkuil }
5937952be9bSHans Verkuil #endif
5947952be9bSHans Verkuil
5953e947c36SHans Verkuil /* Free vb2 buffers */
5967952be9bSHans Verkuil for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
5977952be9bSHans Verkuil ++buffer) {
5987952be9bSHans Verkuil kfree(q->bufs[buffer]);
5997952be9bSHans Verkuil q->bufs[buffer] = NULL;
6007952be9bSHans Verkuil }
6017952be9bSHans Verkuil
6027952be9bSHans Verkuil q->num_buffers -= buffers;
6037952be9bSHans Verkuil if (!q->num_buffers) {
6047952be9bSHans Verkuil q->memory = VB2_MEMORY_UNKNOWN;
6057952be9bSHans Verkuil INIT_LIST_HEAD(&q->queued_list);
6067952be9bSHans Verkuil }
6077952be9bSHans Verkuil }
6087952be9bSHans Verkuil
vb2_buffer_in_use(struct vb2_queue * q,struct vb2_buffer * vb)6097952be9bSHans Verkuil bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
6107952be9bSHans Verkuil {
6117952be9bSHans Verkuil unsigned int plane;
6127952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane) {
6137952be9bSHans Verkuil void *mem_priv = vb->planes[plane].mem_priv;
6147952be9bSHans Verkuil /*
6157952be9bSHans Verkuil * If num_users() has not been provided, call_memop
6167952be9bSHans Verkuil * will return 0, apparently nobody cares about this
6177952be9bSHans Verkuil * case anyway. If num_users() returns more than 1,
6187952be9bSHans Verkuil * we are not the only user of the plane's memory.
6197952be9bSHans Verkuil */
6207952be9bSHans Verkuil if (mem_priv && call_memop(vb, num_users, mem_priv) > 1)
6217952be9bSHans Verkuil return true;
6227952be9bSHans Verkuil }
6237952be9bSHans Verkuil return false;
6247952be9bSHans Verkuil }
6257952be9bSHans Verkuil EXPORT_SYMBOL(vb2_buffer_in_use);
6267952be9bSHans Verkuil
6277952be9bSHans Verkuil /*
6287952be9bSHans Verkuil * __buffers_in_use() - return true if any buffers on the queue are in use and
6297952be9bSHans Verkuil * the queue cannot be freed (by the means of REQBUFS(0)) call
6307952be9bSHans Verkuil */
__buffers_in_use(struct vb2_queue * q)6317952be9bSHans Verkuil static bool __buffers_in_use(struct vb2_queue *q)
6327952be9bSHans Verkuil {
6337952be9bSHans Verkuil unsigned int buffer;
6347952be9bSHans Verkuil for (buffer = 0; buffer < q->num_buffers; ++buffer) {
6357952be9bSHans Verkuil if (vb2_buffer_in_use(q, q->bufs[buffer]))
6367952be9bSHans Verkuil return true;
6377952be9bSHans Verkuil }
6387952be9bSHans Verkuil return false;
6397952be9bSHans Verkuil }
6407952be9bSHans Verkuil
vb2_core_querybuf(struct vb2_queue * q,unsigned int index,void * pb)6417952be9bSHans Verkuil void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
6427952be9bSHans Verkuil {
6437952be9bSHans Verkuil call_void_bufop(q, fill_user_buffer, q->bufs[index], pb);
6447952be9bSHans Verkuil }
6457952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_querybuf);
6467952be9bSHans Verkuil
6477952be9bSHans Verkuil /*
6487952be9bSHans Verkuil * __verify_userptr_ops() - verify that all memory operations required for
6497952be9bSHans Verkuil * USERPTR queue type have been provided
6507952be9bSHans Verkuil */
__verify_userptr_ops(struct vb2_queue * q)6517952be9bSHans Verkuil static int __verify_userptr_ops(struct vb2_queue *q)
6527952be9bSHans Verkuil {
6537952be9bSHans Verkuil if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
6547952be9bSHans Verkuil !q->mem_ops->put_userptr)
6557952be9bSHans Verkuil return -EINVAL;
6567952be9bSHans Verkuil
6577952be9bSHans Verkuil return 0;
6587952be9bSHans Verkuil }
6597952be9bSHans Verkuil
6607952be9bSHans Verkuil /*
6617952be9bSHans Verkuil * __verify_mmap_ops() - verify that all memory operations required for
6627952be9bSHans Verkuil * MMAP queue type have been provided
6637952be9bSHans Verkuil */
__verify_mmap_ops(struct vb2_queue * q)6647952be9bSHans Verkuil static int __verify_mmap_ops(struct vb2_queue *q)
6657952be9bSHans Verkuil {
6667952be9bSHans Verkuil if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
6677952be9bSHans Verkuil !q->mem_ops->put || !q->mem_ops->mmap)
6687952be9bSHans Verkuil return -EINVAL;
6697952be9bSHans Verkuil
6707952be9bSHans Verkuil return 0;
6717952be9bSHans Verkuil }
6727952be9bSHans Verkuil
6737952be9bSHans Verkuil /*
6747952be9bSHans Verkuil * __verify_dmabuf_ops() - verify that all memory operations required for
6757952be9bSHans Verkuil * DMABUF queue type have been provided
6767952be9bSHans Verkuil */
__verify_dmabuf_ops(struct vb2_queue * q)6777952be9bSHans Verkuil static int __verify_dmabuf_ops(struct vb2_queue *q)
6787952be9bSHans Verkuil {
6797952be9bSHans Verkuil if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
6807952be9bSHans Verkuil !q->mem_ops->detach_dmabuf || !q->mem_ops->map_dmabuf ||
6817952be9bSHans Verkuil !q->mem_ops->unmap_dmabuf)
6827952be9bSHans Verkuil return -EINVAL;
6837952be9bSHans Verkuil
6847952be9bSHans Verkuil return 0;
6857952be9bSHans Verkuil }
6867952be9bSHans Verkuil
vb2_verify_memory_type(struct vb2_queue * q,enum vb2_memory memory,unsigned int type)6877952be9bSHans Verkuil int vb2_verify_memory_type(struct vb2_queue *q,
6887952be9bSHans Verkuil enum vb2_memory memory, unsigned int type)
6897952be9bSHans Verkuil {
6907952be9bSHans Verkuil if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
6917952be9bSHans Verkuil memory != VB2_MEMORY_DMABUF) {
692b820935bSLaurent Pinchart dprintk(q, 1, "unsupported memory type\n");
6937952be9bSHans Verkuil return -EINVAL;
6947952be9bSHans Verkuil }
6957952be9bSHans Verkuil
6967952be9bSHans Verkuil if (type != q->type) {
697b820935bSLaurent Pinchart dprintk(q, 1, "requested type is incorrect\n");
6987952be9bSHans Verkuil return -EINVAL;
6997952be9bSHans Verkuil }
7007952be9bSHans Verkuil
7017952be9bSHans Verkuil /*
7027952be9bSHans Verkuil * Make sure all the required memory ops for given memory type
7037952be9bSHans Verkuil * are available.
7047952be9bSHans Verkuil */
7057952be9bSHans Verkuil if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
706b820935bSLaurent Pinchart dprintk(q, 1, "MMAP for current setup unsupported\n");
7077952be9bSHans Verkuil return -EINVAL;
7087952be9bSHans Verkuil }
7097952be9bSHans Verkuil
7107952be9bSHans Verkuil if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
711b820935bSLaurent Pinchart dprintk(q, 1, "USERPTR for current setup unsupported\n");
7127952be9bSHans Verkuil return -EINVAL;
7137952be9bSHans Verkuil }
7147952be9bSHans Verkuil
7157952be9bSHans Verkuil if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
716b820935bSLaurent Pinchart dprintk(q, 1, "DMABUF for current setup unsupported\n");
7177952be9bSHans Verkuil return -EINVAL;
7187952be9bSHans Verkuil }
7197952be9bSHans Verkuil
7207952be9bSHans Verkuil /*
7217952be9bSHans Verkuil * Place the busy tests at the end: -EBUSY can be ignored when
7227952be9bSHans Verkuil * create_bufs is called with count == 0, but count == 0 should still
7237952be9bSHans Verkuil * do the memory and type validation.
7247952be9bSHans Verkuil */
7257952be9bSHans Verkuil if (vb2_fileio_is_active(q)) {
726b820935bSLaurent Pinchart dprintk(q, 1, "file io in progress\n");
7277952be9bSHans Verkuil return -EBUSY;
7287952be9bSHans Verkuil }
7297952be9bSHans Verkuil return 0;
7307952be9bSHans Verkuil }
7317952be9bSHans Verkuil EXPORT_SYMBOL(vb2_verify_memory_type);
7327952be9bSHans Verkuil
set_queue_coherency(struct vb2_queue * q,bool non_coherent_mem)733b00a9e59SSergey Senozhatsky static void set_queue_coherency(struct vb2_queue *q, bool non_coherent_mem)
734b00a9e59SSergey Senozhatsky {
735b00a9e59SSergey Senozhatsky q->non_coherent_mem = 0;
736b00a9e59SSergey Senozhatsky
737b00a9e59SSergey Senozhatsky if (!vb2_queue_allows_cache_hints(q))
738b00a9e59SSergey Senozhatsky return;
739b00a9e59SSergey Senozhatsky q->non_coherent_mem = non_coherent_mem;
740b00a9e59SSergey Senozhatsky }
741b00a9e59SSergey Senozhatsky
verify_coherency_flags(struct vb2_queue * q,bool non_coherent_mem)742b00a9e59SSergey Senozhatsky static bool verify_coherency_flags(struct vb2_queue *q, bool non_coherent_mem)
743b00a9e59SSergey Senozhatsky {
744b00a9e59SSergey Senozhatsky if (non_coherent_mem != q->non_coherent_mem) {
745b00a9e59SSergey Senozhatsky dprintk(q, 1, "memory coherency model mismatch\n");
746b00a9e59SSergey Senozhatsky return false;
747b00a9e59SSergey Senozhatsky }
748b00a9e59SSergey Senozhatsky return true;
749b00a9e59SSergey Senozhatsky }
750b00a9e59SSergey Senozhatsky
vb2_core_reqbufs(struct vb2_queue * q,enum vb2_memory memory,unsigned int flags,unsigned int * count)7517952be9bSHans Verkuil int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
752b00a9e59SSergey Senozhatsky unsigned int flags, unsigned int *count)
7537952be9bSHans Verkuil {
7547952be9bSHans Verkuil unsigned int num_buffers, allocated_buffers, num_planes = 0;
7557952be9bSHans Verkuil unsigned plane_sizes[VB2_MAX_PLANES] = { };
756c0acf9cfSSergey Senozhatsky bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
7578ee92410SJohan Fjeldtvedt unsigned int i;
7587952be9bSHans Verkuil int ret;
7597952be9bSHans Verkuil
7607952be9bSHans Verkuil if (q->streaming) {
761b820935bSLaurent Pinchart dprintk(q, 1, "streaming active\n");
7627952be9bSHans Verkuil return -EBUSY;
7637952be9bSHans Verkuil }
7647952be9bSHans Verkuil
765d65842f7SHans Verkuil if (q->waiting_in_dqbuf && *count) {
766b820935bSLaurent Pinchart dprintk(q, 1, "another dup()ped fd is waiting for a buffer\n");
767d65842f7SHans Verkuil return -EBUSY;
768d65842f7SHans Verkuil }
769d65842f7SHans Verkuil
7707952be9bSHans Verkuil if (*count == 0 || q->num_buffers != 0 ||
771b00a9e59SSergey Senozhatsky (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory) ||
772b00a9e59SSergey Senozhatsky !verify_coherency_flags(q, non_coherent_mem)) {
7737952be9bSHans Verkuil /*
7747952be9bSHans Verkuil * We already have buffers allocated, so first check if they
7757952be9bSHans Verkuil * are not in use and can be freed.
7767952be9bSHans Verkuil */
7777952be9bSHans Verkuil mutex_lock(&q->mmap_lock);
778d644cca5SJohn Sheu if (debug && q->memory == VB2_MEMORY_MMAP &&
779d644cca5SJohn Sheu __buffers_in_use(q))
780b820935bSLaurent Pinchart dprintk(q, 1, "memory in use, orphaning buffers\n");
7817952be9bSHans Verkuil
7827952be9bSHans Verkuil /*
78355028695SHans Verkuil * Call queue_cancel to clean up any buffers in the
7847952be9bSHans Verkuil * QUEUED state which is possible if buffers were prepared or
7857952be9bSHans Verkuil * queued without ever calling STREAMON.
7867952be9bSHans Verkuil */
7877952be9bSHans Verkuil __vb2_queue_cancel(q);
78801cb370fSHans Verkuil __vb2_queue_free(q, q->num_buffers);
7897952be9bSHans Verkuil mutex_unlock(&q->mmap_lock);
7907952be9bSHans Verkuil
7917952be9bSHans Verkuil /*
7927952be9bSHans Verkuil * In case of REQBUFS(0) return immediately without calling
7937952be9bSHans Verkuil * driver's queue_setup() callback and allocating resources.
7947952be9bSHans Verkuil */
7957952be9bSHans Verkuil if (*count == 0)
7967952be9bSHans Verkuil return 0;
7977952be9bSHans Verkuil }
7987952be9bSHans Verkuil
7997952be9bSHans Verkuil /*
8007952be9bSHans Verkuil * Make sure the requested values and current defaults are sane.
8017952be9bSHans Verkuil */
8027952be9bSHans Verkuil WARN_ON(q->min_buffers_needed > VB2_MAX_FRAME);
8037952be9bSHans Verkuil num_buffers = max_t(unsigned int, *count, q->min_buffers_needed);
8047952be9bSHans Verkuil num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
8057952be9bSHans Verkuil memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
806098e5edcSHans Verkuil /*
807098e5edcSHans Verkuil * Set this now to ensure that drivers see the correct q->memory value
808098e5edcSHans Verkuil * in the queue_setup op.
809098e5edcSHans Verkuil */
810098e5edcSHans Verkuil mutex_lock(&q->mmap_lock);
8117952be9bSHans Verkuil q->memory = memory;
812098e5edcSHans Verkuil mutex_unlock(&q->mmap_lock);
813b00a9e59SSergey Senozhatsky set_queue_coherency(q, non_coherent_mem);
8147952be9bSHans Verkuil
8157952be9bSHans Verkuil /*
8167952be9bSHans Verkuil * Ask the driver how many buffers and planes per buffer it requires.
8177952be9bSHans Verkuil * Driver also sets the size and allocator context for each plane.
8187952be9bSHans Verkuil */
8197952be9bSHans Verkuil ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
8207952be9bSHans Verkuil plane_sizes, q->alloc_devs);
8217952be9bSHans Verkuil if (ret)
822098e5edcSHans Verkuil goto error;
8237952be9bSHans Verkuil
8248ee92410SJohan Fjeldtvedt /* Check that driver has set sane values */
825098e5edcSHans Verkuil if (WARN_ON(!num_planes)) {
826098e5edcSHans Verkuil ret = -EINVAL;
827098e5edcSHans Verkuil goto error;
828098e5edcSHans Verkuil }
8298ee92410SJohan Fjeldtvedt
8308ee92410SJohan Fjeldtvedt for (i = 0; i < num_planes; i++)
831098e5edcSHans Verkuil if (WARN_ON(!plane_sizes[i])) {
832098e5edcSHans Verkuil ret = -EINVAL;
833098e5edcSHans Verkuil goto error;
834098e5edcSHans Verkuil }
8358ee92410SJohan Fjeldtvedt
8367952be9bSHans Verkuil /* Finally, allocate buffers and video memory */
8377952be9bSHans Verkuil allocated_buffers =
8387952be9bSHans Verkuil __vb2_queue_alloc(q, memory, num_buffers, num_planes, plane_sizes);
8397952be9bSHans Verkuil if (allocated_buffers == 0) {
840b820935bSLaurent Pinchart dprintk(q, 1, "memory allocation failed\n");
841098e5edcSHans Verkuil ret = -ENOMEM;
842098e5edcSHans Verkuil goto error;
8437952be9bSHans Verkuil }
8447952be9bSHans Verkuil
8457952be9bSHans Verkuil /*
8467952be9bSHans Verkuil * There is no point in continuing if we can't allocate the minimum
8477952be9bSHans Verkuil * number of buffers needed by this vb2_queue.
8487952be9bSHans Verkuil */
8497952be9bSHans Verkuil if (allocated_buffers < q->min_buffers_needed)
8507952be9bSHans Verkuil ret = -ENOMEM;
8517952be9bSHans Verkuil
8527952be9bSHans Verkuil /*
8537952be9bSHans Verkuil * Check if driver can handle the allocated number of buffers.
8547952be9bSHans Verkuil */
8557952be9bSHans Verkuil if (!ret && allocated_buffers < num_buffers) {
8567952be9bSHans Verkuil num_buffers = allocated_buffers;
8577952be9bSHans Verkuil /*
8587952be9bSHans Verkuil * num_planes is set by the previous queue_setup(), but since it
8597952be9bSHans Verkuil * signals to queue_setup() whether it is called from create_bufs()
8607952be9bSHans Verkuil * vs reqbufs() we zero it here to signal that queue_setup() is
8617952be9bSHans Verkuil * called for the reqbufs() case.
8627952be9bSHans Verkuil */
8637952be9bSHans Verkuil num_planes = 0;
8647952be9bSHans Verkuil
8657952be9bSHans Verkuil ret = call_qop(q, queue_setup, q, &num_buffers,
8667952be9bSHans Verkuil &num_planes, plane_sizes, q->alloc_devs);
8677952be9bSHans Verkuil
8687952be9bSHans Verkuil if (!ret && allocated_buffers < num_buffers)
8697952be9bSHans Verkuil ret = -ENOMEM;
8707952be9bSHans Verkuil
8717952be9bSHans Verkuil /*
8727952be9bSHans Verkuil * Either the driver has accepted a smaller number of buffers,
8737952be9bSHans Verkuil * or .queue_setup() returned an error
8747952be9bSHans Verkuil */
8757952be9bSHans Verkuil }
8767952be9bSHans Verkuil
8777952be9bSHans Verkuil mutex_lock(&q->mmap_lock);
8787952be9bSHans Verkuil q->num_buffers = allocated_buffers;
8797952be9bSHans Verkuil
8807952be9bSHans Verkuil if (ret < 0) {
8817952be9bSHans Verkuil /*
8827952be9bSHans Verkuil * Note: __vb2_queue_free() will subtract 'allocated_buffers'
883098e5edcSHans Verkuil * from q->num_buffers and it will reset q->memory to
884098e5edcSHans Verkuil * VB2_MEMORY_UNKNOWN.
8857952be9bSHans Verkuil */
8867952be9bSHans Verkuil __vb2_queue_free(q, allocated_buffers);
8877952be9bSHans Verkuil mutex_unlock(&q->mmap_lock);
8887952be9bSHans Verkuil return ret;
8897952be9bSHans Verkuil }
8907952be9bSHans Verkuil mutex_unlock(&q->mmap_lock);
8917952be9bSHans Verkuil
8927952be9bSHans Verkuil /*
8937952be9bSHans Verkuil * Return the number of successfully allocated buffers
8947952be9bSHans Verkuil * to the userspace.
8957952be9bSHans Verkuil */
8967952be9bSHans Verkuil *count = allocated_buffers;
8977952be9bSHans Verkuil q->waiting_for_buffers = !q->is_output;
8987952be9bSHans Verkuil
8997952be9bSHans Verkuil return 0;
900098e5edcSHans Verkuil
901098e5edcSHans Verkuil error:
902098e5edcSHans Verkuil mutex_lock(&q->mmap_lock);
903098e5edcSHans Verkuil q->memory = VB2_MEMORY_UNKNOWN;
904098e5edcSHans Verkuil mutex_unlock(&q->mmap_lock);
905098e5edcSHans Verkuil return ret;
9067952be9bSHans Verkuil }
9077952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
9087952be9bSHans 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[])9097952be9bSHans Verkuil int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
910b00a9e59SSergey Senozhatsky unsigned int flags, unsigned int *count,
9117b4b4555SSergey Senozhatsky unsigned int requested_planes,
9127b4b4555SSergey Senozhatsky const unsigned int requested_sizes[])
9137952be9bSHans Verkuil {
9147952be9bSHans Verkuil unsigned int num_planes = 0, num_buffers, allocated_buffers;
9157952be9bSHans Verkuil unsigned plane_sizes[VB2_MAX_PLANES] = { };
916c0acf9cfSSergey Senozhatsky bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
917098e5edcSHans Verkuil bool no_previous_buffers = !q->num_buffers;
9187952be9bSHans Verkuil int ret;
9197952be9bSHans Verkuil
9207952be9bSHans Verkuil if (q->num_buffers == VB2_MAX_FRAME) {
921b820935bSLaurent Pinchart dprintk(q, 1, "maximum number of buffers already allocated\n");
9227952be9bSHans Verkuil return -ENOBUFS;
9237952be9bSHans Verkuil }
9247952be9bSHans Verkuil
925098e5edcSHans Verkuil if (no_previous_buffers) {
926d65842f7SHans Verkuil if (q->waiting_in_dqbuf && *count) {
927b820935bSLaurent Pinchart dprintk(q, 1, "another dup()ped fd is waiting for a buffer\n");
928d65842f7SHans Verkuil return -EBUSY;
929d65842f7SHans Verkuil }
9307952be9bSHans Verkuil memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
931098e5edcSHans Verkuil /*
932098e5edcSHans Verkuil * Set this now to ensure that drivers see the correct q->memory
933098e5edcSHans Verkuil * value in the queue_setup op.
934098e5edcSHans Verkuil */
935098e5edcSHans Verkuil mutex_lock(&q->mmap_lock);
9367952be9bSHans Verkuil q->memory = memory;
937098e5edcSHans Verkuil mutex_unlock(&q->mmap_lock);
9387952be9bSHans Verkuil q->waiting_for_buffers = !q->is_output;
939b00a9e59SSergey Senozhatsky set_queue_coherency(q, non_coherent_mem);
9407b4b4555SSergey Senozhatsky } else {
9417b4b4555SSergey Senozhatsky if (q->memory != memory) {
942b820935bSLaurent Pinchart dprintk(q, 1, "memory model mismatch\n");
94362dcb4f4SHans Verkuil return -EINVAL;
9447952be9bSHans Verkuil }
945b00a9e59SSergey Senozhatsky if (!verify_coherency_flags(q, non_coherent_mem))
946b00a9e59SSergey Senozhatsky return -EINVAL;
9477b4b4555SSergey Senozhatsky }
9487952be9bSHans Verkuil
9497952be9bSHans Verkuil num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
9507952be9bSHans Verkuil
9517952be9bSHans Verkuil if (requested_planes && requested_sizes) {
9527952be9bSHans Verkuil num_planes = requested_planes;
9537952be9bSHans Verkuil memcpy(plane_sizes, requested_sizes, sizeof(plane_sizes));
9547952be9bSHans Verkuil }
9557952be9bSHans Verkuil
9567952be9bSHans Verkuil /*
9577952be9bSHans Verkuil * Ask the driver, whether the requested number of buffers, planes per
9587952be9bSHans Verkuil * buffer and their sizes are acceptable
9597952be9bSHans Verkuil */
9607952be9bSHans Verkuil ret = call_qop(q, queue_setup, q, &num_buffers,
9617952be9bSHans Verkuil &num_planes, plane_sizes, q->alloc_devs);
9627952be9bSHans Verkuil if (ret)
963098e5edcSHans Verkuil goto error;
9647952be9bSHans Verkuil
9657952be9bSHans Verkuil /* Finally, allocate buffers and video memory */
9667952be9bSHans Verkuil allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
9677952be9bSHans Verkuil num_planes, plane_sizes);
9687952be9bSHans Verkuil if (allocated_buffers == 0) {
969b820935bSLaurent Pinchart dprintk(q, 1, "memory allocation failed\n");
970098e5edcSHans Verkuil ret = -ENOMEM;
971098e5edcSHans Verkuil goto error;
9727952be9bSHans Verkuil }
9737952be9bSHans Verkuil
9747952be9bSHans Verkuil /*
9757952be9bSHans Verkuil * Check if driver can handle the so far allocated number of buffers.
9767952be9bSHans Verkuil */
9777952be9bSHans Verkuil if (allocated_buffers < num_buffers) {
9787952be9bSHans Verkuil num_buffers = allocated_buffers;
9797952be9bSHans Verkuil
9807952be9bSHans Verkuil /*
9817952be9bSHans Verkuil * q->num_buffers contains the total number of buffers, that the
9827952be9bSHans Verkuil * queue driver has set up
9837952be9bSHans Verkuil */
9847952be9bSHans Verkuil ret = call_qop(q, queue_setup, q, &num_buffers,
9857952be9bSHans Verkuil &num_planes, plane_sizes, q->alloc_devs);
9867952be9bSHans Verkuil
9877952be9bSHans Verkuil if (!ret && allocated_buffers < num_buffers)
9887952be9bSHans Verkuil ret = -ENOMEM;
9897952be9bSHans Verkuil
9907952be9bSHans Verkuil /*
9917952be9bSHans Verkuil * Either the driver has accepted a smaller number of buffers,
9927952be9bSHans Verkuil * or .queue_setup() returned an error
9937952be9bSHans Verkuil */
9947952be9bSHans Verkuil }
9957952be9bSHans Verkuil
9967952be9bSHans Verkuil mutex_lock(&q->mmap_lock);
9977952be9bSHans Verkuil q->num_buffers += allocated_buffers;
9987952be9bSHans Verkuil
9997952be9bSHans Verkuil if (ret < 0) {
10007952be9bSHans Verkuil /*
10017952be9bSHans Verkuil * Note: __vb2_queue_free() will subtract 'allocated_buffers'
1002098e5edcSHans Verkuil * from q->num_buffers and it will reset q->memory to
1003098e5edcSHans Verkuil * VB2_MEMORY_UNKNOWN.
10047952be9bSHans Verkuil */
10057952be9bSHans Verkuil __vb2_queue_free(q, allocated_buffers);
10067952be9bSHans Verkuil mutex_unlock(&q->mmap_lock);
10077952be9bSHans Verkuil return -ENOMEM;
10087952be9bSHans Verkuil }
10097952be9bSHans Verkuil mutex_unlock(&q->mmap_lock);
10107952be9bSHans Verkuil
10117952be9bSHans Verkuil /*
10127952be9bSHans Verkuil * Return the number of successfully allocated buffers
10137952be9bSHans Verkuil * to the userspace.
10147952be9bSHans Verkuil */
10157952be9bSHans Verkuil *count = allocated_buffers;
10167952be9bSHans Verkuil
10177952be9bSHans Verkuil return 0;
1018098e5edcSHans Verkuil
1019098e5edcSHans Verkuil error:
1020098e5edcSHans Verkuil if (no_previous_buffers) {
1021098e5edcSHans Verkuil mutex_lock(&q->mmap_lock);
1022098e5edcSHans Verkuil q->memory = VB2_MEMORY_UNKNOWN;
1023098e5edcSHans Verkuil mutex_unlock(&q->mmap_lock);
1024098e5edcSHans Verkuil }
1025098e5edcSHans Verkuil return ret;
10267952be9bSHans Verkuil }
10277952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
10287952be9bSHans Verkuil
vb2_plane_vaddr(struct vb2_buffer * vb,unsigned int plane_no)10297952be9bSHans Verkuil void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
10307952be9bSHans Verkuil {
10317952be9bSHans Verkuil if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
10327952be9bSHans Verkuil return NULL;
10337952be9bSHans Verkuil
1034a4b83debSSergey Senozhatsky return call_ptr_memop(vaddr, vb, vb->planes[plane_no].mem_priv);
10357952be9bSHans Verkuil
10367952be9bSHans Verkuil }
10377952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
10387952be9bSHans Verkuil
vb2_plane_cookie(struct vb2_buffer * vb,unsigned int plane_no)10397952be9bSHans Verkuil void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
10407952be9bSHans Verkuil {
10417952be9bSHans Verkuil if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
10427952be9bSHans Verkuil return NULL;
10437952be9bSHans Verkuil
1044a4b83debSSergey Senozhatsky return call_ptr_memop(cookie, vb, vb->planes[plane_no].mem_priv);
10457952be9bSHans Verkuil }
10467952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_plane_cookie);
10477952be9bSHans Verkuil
vb2_buffer_done(struct vb2_buffer * vb,enum vb2_buffer_state state)10487952be9bSHans Verkuil void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
10497952be9bSHans Verkuil {
10507952be9bSHans Verkuil struct vb2_queue *q = vb->vb2_queue;
10517952be9bSHans Verkuil unsigned long flags;
10527952be9bSHans Verkuil
10537952be9bSHans Verkuil if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))
10547952be9bSHans Verkuil return;
10557952be9bSHans Verkuil
10567952be9bSHans Verkuil if (WARN_ON(state != VB2_BUF_STATE_DONE &&
10577952be9bSHans Verkuil state != VB2_BUF_STATE_ERROR &&
1058c6e4e2c4SHans Verkuil state != VB2_BUF_STATE_QUEUED))
10597952be9bSHans Verkuil state = VB2_BUF_STATE_ERROR;
10607952be9bSHans Verkuil
10617952be9bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
10627952be9bSHans Verkuil /*
10637952be9bSHans Verkuil * Although this is not a callback, it still does have to balance
10647952be9bSHans Verkuil * with the buf_queue op. So update this counter manually.
10657952be9bSHans Verkuil */
10667952be9bSHans Verkuil vb->cnt_buf_done++;
10677952be9bSHans Verkuil #endif
1068c89ee8edSEzequiel Garcia dprintk(q, 4, "done processing on buffer %d, state: %s\n",
1069c89ee8edSEzequiel Garcia vb->index, vb2_state_name(state));
10707952be9bSHans Verkuil
107138a417e8SSergey Senozhatsky if (state != VB2_BUF_STATE_QUEUED)
107238a417e8SSergey Senozhatsky __vb2_buf_mem_finish(vb);
10737952be9bSHans Verkuil
10747952be9bSHans Verkuil spin_lock_irqsave(&q->done_lock, flags);
1075c6e4e2c4SHans Verkuil if (state == VB2_BUF_STATE_QUEUED) {
10767952be9bSHans Verkuil vb->state = VB2_BUF_STATE_QUEUED;
10777952be9bSHans Verkuil } else {
10787952be9bSHans Verkuil /* Add the buffer to the done buffers list */
10797952be9bSHans Verkuil list_add_tail(&vb->done_entry, &q->done_list);
10807952be9bSHans Verkuil vb->state = state;
10817952be9bSHans Verkuil }
10827952be9bSHans Verkuil atomic_dec(&q->owned_by_drv_count);
1083fd89e0bbSHans Verkuil
1084dde6bdccSHans Verkuil if (state != VB2_BUF_STATE_QUEUED && vb->req_obj.req) {
1085fd89e0bbSHans Verkuil media_request_object_unbind(&vb->req_obj);
1086fd89e0bbSHans Verkuil media_request_object_put(&vb->req_obj);
1087fd89e0bbSHans Verkuil }
1088fd89e0bbSHans Verkuil
10897952be9bSHans Verkuil spin_unlock_irqrestore(&q->done_lock, flags);
10907952be9bSHans Verkuil
10917952be9bSHans Verkuil trace_vb2_buf_done(q, vb);
10927952be9bSHans Verkuil
10937952be9bSHans Verkuil switch (state) {
10947952be9bSHans Verkuil case VB2_BUF_STATE_QUEUED:
10957952be9bSHans Verkuil return;
10967952be9bSHans Verkuil default:
10977952be9bSHans Verkuil /* Inform any processes that may be waiting for buffers */
10987952be9bSHans Verkuil wake_up(&q->done_wq);
10997952be9bSHans Verkuil break;
11007952be9bSHans Verkuil }
11017952be9bSHans Verkuil }
11027952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_buffer_done);
11037952be9bSHans Verkuil
vb2_discard_done(struct vb2_queue * q)11047952be9bSHans Verkuil void vb2_discard_done(struct vb2_queue *q)
11057952be9bSHans Verkuil {
11067952be9bSHans Verkuil struct vb2_buffer *vb;
11077952be9bSHans Verkuil unsigned long flags;
11087952be9bSHans Verkuil
11097952be9bSHans Verkuil spin_lock_irqsave(&q->done_lock, flags);
11107952be9bSHans Verkuil list_for_each_entry(vb, &q->done_list, done_entry)
11117952be9bSHans Verkuil vb->state = VB2_BUF_STATE_ERROR;
11127952be9bSHans Verkuil spin_unlock_irqrestore(&q->done_lock, flags);
11137952be9bSHans Verkuil }
11147952be9bSHans Verkuil EXPORT_SYMBOL_GPL(vb2_discard_done);
11157952be9bSHans Verkuil
11167952be9bSHans Verkuil /*
11177952be9bSHans Verkuil * __prepare_mmap() - prepare an MMAP buffer
11187952be9bSHans Verkuil */
__prepare_mmap(struct vb2_buffer * vb)1119db6e8d57SHans Verkuil static int __prepare_mmap(struct vb2_buffer *vb)
11207952be9bSHans Verkuil {
11217952be9bSHans Verkuil int ret = 0;
11227952be9bSHans Verkuil
11237952be9bSHans Verkuil ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1124db6e8d57SHans Verkuil vb, vb->planes);
11257952be9bSHans Verkuil return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
11267952be9bSHans Verkuil }
11277952be9bSHans Verkuil
11287952be9bSHans Verkuil /*
11297952be9bSHans Verkuil * __prepare_userptr() - prepare a USERPTR buffer
11307952be9bSHans Verkuil */
__prepare_userptr(struct vb2_buffer * vb)1131db6e8d57SHans Verkuil static int __prepare_userptr(struct vb2_buffer *vb)
11327952be9bSHans Verkuil {
11337952be9bSHans Verkuil struct vb2_plane planes[VB2_MAX_PLANES];
11347952be9bSHans Verkuil struct vb2_queue *q = vb->vb2_queue;
11357952be9bSHans Verkuil void *mem_priv;
11367952be9bSHans Verkuil unsigned int plane;
11377952be9bSHans Verkuil int ret = 0;
11387952be9bSHans Verkuil bool reacquired = vb->planes[0].mem_priv == NULL;
11397952be9bSHans Verkuil
11407952be9bSHans Verkuil memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
11417952be9bSHans Verkuil /* Copy relevant information provided by the userspace */
11427952be9bSHans Verkuil ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1143db6e8d57SHans Verkuil vb, planes);
11447952be9bSHans Verkuil if (ret)
11457952be9bSHans Verkuil return ret;
11467952be9bSHans Verkuil
11477952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane) {
11487952be9bSHans Verkuil /* Skip the plane if already verified */
11497952be9bSHans Verkuil if (vb->planes[plane].m.userptr &&
11507952be9bSHans Verkuil vb->planes[plane].m.userptr == planes[plane].m.userptr
11517952be9bSHans Verkuil && vb->planes[plane].length == planes[plane].length)
11527952be9bSHans Verkuil continue;
11537952be9bSHans Verkuil
1154b820935bSLaurent Pinchart dprintk(q, 3, "userspace address for plane %d changed, reacquiring memory\n",
11557952be9bSHans Verkuil plane);
11567952be9bSHans Verkuil
11577952be9bSHans Verkuil /* Check if the provided plane buffer is large enough */
11587952be9bSHans Verkuil if (planes[plane].length < vb->planes[plane].min_length) {
1159b820935bSLaurent Pinchart dprintk(q, 1, "provided buffer size %u is less than setup size %u for plane %d\n",
11607952be9bSHans Verkuil planes[plane].length,
11617952be9bSHans Verkuil vb->planes[plane].min_length,
11627952be9bSHans Verkuil plane);
11637952be9bSHans Verkuil ret = -EINVAL;
11647952be9bSHans Verkuil goto err;
11657952be9bSHans Verkuil }
11667952be9bSHans Verkuil
11677952be9bSHans Verkuil /* Release previously acquired memory if present */
11687952be9bSHans Verkuil if (vb->planes[plane].mem_priv) {
11697952be9bSHans Verkuil if (!reacquired) {
11707952be9bSHans Verkuil reacquired = true;
11717e4e7162SHans Verkuil vb->copied_timestamp = 0;
11727952be9bSHans Verkuil call_void_vb_qop(vb, buf_cleanup, vb);
11737952be9bSHans Verkuil }
11747952be9bSHans Verkuil call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
11757952be9bSHans Verkuil }
11767952be9bSHans Verkuil
11777952be9bSHans Verkuil vb->planes[plane].mem_priv = NULL;
11787952be9bSHans Verkuil vb->planes[plane].bytesused = 0;
11797952be9bSHans Verkuil vb->planes[plane].length = 0;
11807952be9bSHans Verkuil vb->planes[plane].m.userptr = 0;
11817952be9bSHans Verkuil vb->planes[plane].data_offset = 0;
11827952be9bSHans Verkuil
11837952be9bSHans Verkuil /* Acquire each plane's memory */
1184a4b83debSSergey Senozhatsky mem_priv = call_ptr_memop(get_userptr,
1185a4b83debSSergey Senozhatsky vb,
11867952be9bSHans Verkuil q->alloc_devs[plane] ? : q->dev,
11877952be9bSHans Verkuil planes[plane].m.userptr,
1188a4b83debSSergey Senozhatsky planes[plane].length);
11897952be9bSHans Verkuil if (IS_ERR(mem_priv)) {
1190b820935bSLaurent Pinchart dprintk(q, 1, "failed acquiring userspace memory for plane %d\n",
11917952be9bSHans Verkuil plane);
11927952be9bSHans Verkuil ret = PTR_ERR(mem_priv);
11937952be9bSHans Verkuil goto err;
11947952be9bSHans Verkuil }
11957952be9bSHans Verkuil vb->planes[plane].mem_priv = mem_priv;
11967952be9bSHans Verkuil }
11977952be9bSHans Verkuil
11987952be9bSHans Verkuil /*
11997952be9bSHans Verkuil * Now that everything is in order, copy relevant information
12007952be9bSHans Verkuil * provided by userspace.
12017952be9bSHans Verkuil */
12027952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane) {
12037952be9bSHans Verkuil vb->planes[plane].bytesused = planes[plane].bytesused;
12047952be9bSHans Verkuil vb->planes[plane].length = planes[plane].length;
12057952be9bSHans Verkuil vb->planes[plane].m.userptr = planes[plane].m.userptr;
12067952be9bSHans Verkuil vb->planes[plane].data_offset = planes[plane].data_offset;
12077952be9bSHans Verkuil }
12087952be9bSHans Verkuil
12097952be9bSHans Verkuil if (reacquired) {
12107952be9bSHans Verkuil /*
12117952be9bSHans Verkuil * One or more planes changed, so we must call buf_init to do
12127952be9bSHans Verkuil * the driver-specific initialization on the newly acquired
12137952be9bSHans Verkuil * buffer, if provided.
12147952be9bSHans Verkuil */
12157952be9bSHans Verkuil ret = call_vb_qop(vb, buf_init, vb);
12167952be9bSHans Verkuil if (ret) {
1217b820935bSLaurent Pinchart dprintk(q, 1, "buffer initialization failed\n");
12187952be9bSHans Verkuil goto err;
12197952be9bSHans Verkuil }
12207952be9bSHans Verkuil }
12217952be9bSHans Verkuil
12227952be9bSHans Verkuil ret = call_vb_qop(vb, buf_prepare, vb);
12237952be9bSHans Verkuil if (ret) {
1224b820935bSLaurent Pinchart dprintk(q, 1, "buffer preparation failed\n");
12257952be9bSHans Verkuil call_void_vb_qop(vb, buf_cleanup, vb);
12267952be9bSHans Verkuil goto err;
12277952be9bSHans Verkuil }
12287952be9bSHans Verkuil
12297952be9bSHans Verkuil return 0;
12307952be9bSHans Verkuil err:
12317952be9bSHans Verkuil /* In case of errors, release planes that were already acquired */
12327952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane) {
12337952be9bSHans Verkuil if (vb->planes[plane].mem_priv)
12347952be9bSHans Verkuil call_void_memop(vb, put_userptr,
12357952be9bSHans Verkuil vb->planes[plane].mem_priv);
12367952be9bSHans Verkuil vb->planes[plane].mem_priv = NULL;
12377952be9bSHans Verkuil vb->planes[plane].m.userptr = 0;
12387952be9bSHans Verkuil vb->planes[plane].length = 0;
12397952be9bSHans Verkuil }
12407952be9bSHans Verkuil
12417952be9bSHans Verkuil return ret;
12427952be9bSHans Verkuil }
12437952be9bSHans Verkuil
12447952be9bSHans Verkuil /*
12457952be9bSHans Verkuil * __prepare_dmabuf() - prepare a DMABUF buffer
12467952be9bSHans Verkuil */
__prepare_dmabuf(struct vb2_buffer * vb)1247db6e8d57SHans Verkuil static int __prepare_dmabuf(struct vb2_buffer *vb)
12487952be9bSHans Verkuil {
12497952be9bSHans Verkuil struct vb2_plane planes[VB2_MAX_PLANES];
12507952be9bSHans Verkuil struct vb2_queue *q = vb->vb2_queue;
12517952be9bSHans Verkuil void *mem_priv;
12527952be9bSHans Verkuil unsigned int plane;
12537952be9bSHans Verkuil int ret = 0;
12547952be9bSHans Verkuil bool reacquired = vb->planes[0].mem_priv == NULL;
12557952be9bSHans Verkuil
12567952be9bSHans Verkuil memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
12577952be9bSHans Verkuil /* Copy relevant information provided by the userspace */
12587952be9bSHans Verkuil ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1259db6e8d57SHans Verkuil vb, planes);
12607952be9bSHans Verkuil if (ret)
12617952be9bSHans Verkuil return ret;
12627952be9bSHans Verkuil
12637952be9bSHans Verkuil for (plane = 0; plane < vb->num_planes; ++plane) {
12647952be9bSHans Verkuil struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
12657952be9bSHans Verkuil
12667952be9bSHans Verkuil if (IS_ERR_OR_NULL(dbuf)) {
1267b820935bSLaurent Pinchart dprintk(q, 1, "invalid dmabuf fd for plane %d\n",
12687952be9bSHans Verkuil plane);
12697952be9bSHans Verkuil ret = -EINVAL;
12707952be9bSHans Verkuil goto err;
12717952be9bSHans Verkuil }
12727952be9bSHans Verkuil
12737952be9bSHans Verkuil /* use DMABUF size if length is not provided */
12747952be9bSHans Verkuil if (planes[plane].length == 0)
12757952be9bSHans Verkuil planes[plane].length = dbuf->size;
12767952be9bSHans Verkuil
12777952be9bSHans Verkuil if (planes[plane].length < vb->planes[plane].min_length) {
1278b820935bSLaurent Pinchart dprintk(q, 1, "invalid dmabuf length %u for plane %d, minimum length %u\n",
12797952be9bSHans Verkuil planes[plane].length, plane,
12807952be9bSHans Verkuil vb->planes[plane].min_length);
12817952be9bSHans Verkuil dma_buf_put(dbuf);
12827952be9bSHans Verkuil ret = -EINVAL;
12837952be9bSHans Verkuil goto err;
12847952be9bSHans Verkuil }
12857952be9bSHans Verkuil
12867952be9bSHans Verkuil /* Skip the plane if already verified */
12877952be9bSHans Verkuil if (dbuf == vb->planes[plane].dbuf &&
12887952be9bSHans Verkuil vb->planes[plane].length == planes[plane].length) {
12897952be9bSHans Verkuil dma_buf_put(dbuf);
12907952be9bSHans Verkuil continue;
12917952be9bSHans Verkuil }
12927952be9bSHans Verkuil
1293b820935bSLaurent Pinchart dprintk(q, 3, "buffer for plane %d changed\n", plane);
12947952be9bSHans Verkuil
12957952be9bSHans Verkuil if (!reacquired) {
12967952be9bSHans Verkuil reacquired = true;
12977e4e7162SHans Verkuil vb->copied_timestamp = 0;
12987952be9bSHans Verkuil call_void_vb_qop(vb, buf_cleanup, vb);
12997952be9bSHans Verkuil }
13007952be9bSHans Verkuil
13017952be9bSHans Verkuil /* Release previously acquired memory if present */
13027952be9bSHans Verkuil __vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
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