• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * helper functions for vmalloc video4linux capture buffers
4  *
5  * The functions expect the hardware being able to scatter gather
6  * (i.e. the buffers are not linear in physical memory, but fragmented
7  * into PAGE_SIZE chunks).  They also assume the driver does not need
8  * to touch the video data.
9  *
10  * (c) 2007 Mauro Carvalho Chehab <mchehab@kernel.org>
11  */
12 
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/slab.h>
17 #include <linux/interrupt.h>
18 #include <linux/pgtable.h>
19 
20 #include <linux/pci.h>
21 #include <linux/vmalloc.h>
22 #include <linux/pagemap.h>
23 #include <asm/page.h>
24 
25 #include <media/videobuf-vmalloc.h>
26 
27 #define MAGIC_DMABUF   0x17760309
28 #define MAGIC_VMAL_MEM 0x18221223
29 
30 #define MAGIC_CHECK(is, should)						\
31 	if (unlikely((is) != (should))) {				\
32 		printk(KERN_ERR "magic mismatch: %x (expected %x)\n",	\
33 				is, should);				\
34 		BUG();							\
35 	}
36 
37 static int debug;
38 module_param(debug, int, 0644);
39 
40 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
41 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");
42 MODULE_LICENSE("GPL");
43 
44 #define dprintk(level, fmt, arg...)					\
45 	if (debug >= level)						\
46 		printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
47 
48 
49 /***************************************************************************/
50 
videobuf_vm_open(struct vm_area_struct * vma)51 static void videobuf_vm_open(struct vm_area_struct *vma)
52 {
53 	struct videobuf_mapping *map = vma->vm_private_data;
54 
55 	dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
56 		map->count, vma->vm_start, vma->vm_end);
57 
58 	map->count++;
59 }
60 
videobuf_vm_close(struct vm_area_struct * vma)61 static void videobuf_vm_close(struct vm_area_struct *vma)
62 {
63 	struct videobuf_mapping *map = vma->vm_private_data;
64 	struct videobuf_queue *q = map->q;
65 	int i;
66 
67 	dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
68 		map->count, vma->vm_start, vma->vm_end);
69 
70 	map->count--;
71 	if (0 == map->count) {
72 		struct videobuf_vmalloc_memory *mem;
73 
74 		dprintk(1, "munmap %p q=%p\n", map, q);
75 		videobuf_queue_lock(q);
76 
77 		/* We need first to cancel streams, before unmapping */
78 		if (q->streaming)
79 			videobuf_queue_cancel(q);
80 
81 		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
82 			if (NULL == q->bufs[i])
83 				continue;
84 
85 			if (q->bufs[i]->map != map)
86 				continue;
87 
88 			mem = q->bufs[i]->priv;
89 			if (mem) {
90 				/* This callback is called only if kernel has
91 				   allocated memory and this memory is mmapped.
92 				   In this case, memory should be freed,
93 				   in order to do memory unmap.
94 				 */
95 
96 				MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
97 
98 				/* vfree is not atomic - can't be
99 				   called with IRQ's disabled
100 				 */
101 				dprintk(1, "%s: buf[%d] freeing (%p)\n",
102 					__func__, i, mem->vaddr);
103 
104 				vfree(mem->vaddr);
105 				mem->vaddr = NULL;
106 			}
107 
108 			q->bufs[i]->map   = NULL;
109 			q->bufs[i]->baddr = 0;
110 		}
111 
112 		kfree(map);
113 
114 		videobuf_queue_unlock(q);
115 	}
116 
117 	return;
118 }
119 
120 static const struct vm_operations_struct videobuf_vm_ops = {
121 	.open     = videobuf_vm_open,
122 	.close    = videobuf_vm_close,
123 };
124 
125 /* ---------------------------------------------------------------------
126  * vmalloc handlers for the generic methods
127  */
128 
129 /* Allocated area consists on 3 parts:
130 	struct video_buffer
131 	struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
132 	struct videobuf_dma_sg_memory
133  */
134 
__videobuf_alloc_vb(size_t size)135 static struct videobuf_buffer *__videobuf_alloc_vb(size_t size)
136 {
137 	struct videobuf_vmalloc_memory *mem;
138 	struct videobuf_buffer *vb;
139 
140 	vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
141 	if (!vb)
142 		return vb;
143 
144 	mem = vb->priv = ((char *)vb) + size;
145 	mem->magic = MAGIC_VMAL_MEM;
146 
147 	dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
148 		__func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb),
149 		mem, (long)sizeof(*mem));
150 
151 	return vb;
152 }
153 
__videobuf_iolock(struct videobuf_queue * q,struct videobuf_buffer * vb,struct v4l2_framebuffer * fbuf)154 static int __videobuf_iolock(struct videobuf_queue *q,
155 			     struct videobuf_buffer *vb,
156 			     struct v4l2_framebuffer *fbuf)
157 {
158 	struct videobuf_vmalloc_memory *mem = vb->priv;
159 	int pages;
160 
161 	BUG_ON(!mem);
162 
163 	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
164 
165 	switch (vb->memory) {
166 	case V4L2_MEMORY_MMAP:
167 		dprintk(1, "%s memory method MMAP\n", __func__);
168 
169 		/* All handling should be done by __videobuf_mmap_mapper() */
170 		if (!mem->vaddr) {
171 			printk(KERN_ERR "memory is not allocated/mmapped.\n");
172 			return -EINVAL;
173 		}
174 		break;
175 	case V4L2_MEMORY_USERPTR:
176 		pages = PAGE_ALIGN(vb->size);
177 
178 		dprintk(1, "%s memory method USERPTR\n", __func__);
179 
180 		if (vb->baddr) {
181 			printk(KERN_ERR "USERPTR is currently not supported\n");
182 			return -EINVAL;
183 		}
184 
185 		/* The only USERPTR currently supported is the one needed for
186 		 * read() method.
187 		 */
188 
189 		mem->vaddr = vmalloc_user(pages);
190 		if (!mem->vaddr) {
191 			printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
192 			return -ENOMEM;
193 		}
194 		dprintk(1, "vmalloc is at addr %p (%d pages)\n",
195 			mem->vaddr, pages);
196 		break;
197 	case V4L2_MEMORY_OVERLAY:
198 	default:
199 		dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
200 
201 		/* Currently, doesn't support V4L2_MEMORY_OVERLAY */
202 		printk(KERN_ERR "Memory method currently unsupported.\n");
203 		return -EINVAL;
204 	}
205 
206 	return 0;
207 }
208 
__videobuf_mmap_mapper(struct videobuf_queue * q,struct videobuf_buffer * buf,struct vm_area_struct * vma)209 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
210 				  struct videobuf_buffer *buf,
211 				  struct vm_area_struct *vma)
212 {
213 	struct videobuf_vmalloc_memory *mem;
214 	struct videobuf_mapping *map;
215 	int retval, pages;
216 
217 	dprintk(1, "%s\n", __func__);
218 
219 	/* create mapping + update buffer list */
220 	map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
221 	if (NULL == map)
222 		return -ENOMEM;
223 
224 	buf->map = map;
225 	map->q     = q;
226 
227 	buf->baddr = vma->vm_start;
228 
229 	mem = buf->priv;
230 	BUG_ON(!mem);
231 	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
232 
233 	pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
234 	mem->vaddr = vmalloc_user(pages);
235 	if (!mem->vaddr) {
236 		printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
237 		goto error;
238 	}
239 	dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages);
240 
241 	/* Try to remap memory */
242 	retval = remap_vmalloc_range(vma, mem->vaddr, 0);
243 	if (retval < 0) {
244 		printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
245 		vfree(mem->vaddr);
246 		goto error;
247 	}
248 
249 	vma->vm_ops          = &videobuf_vm_ops;
250 	vma->vm_flags       |= VM_DONTEXPAND | VM_DONTDUMP;
251 	vma->vm_private_data = map;
252 
253 	dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
254 		map, q, vma->vm_start, vma->vm_end,
255 		(long int)buf->bsize,
256 		vma->vm_pgoff, buf->i);
257 
258 	videobuf_vm_open(vma);
259 
260 	return 0;
261 
262 error:
263 	mem = NULL;
264 	kfree(map);
265 	return -ENOMEM;
266 }
267 
268 static struct videobuf_qtype_ops qops = {
269 	.magic        = MAGIC_QTYPE_OPS,
270 
271 	.alloc_vb     = __videobuf_alloc_vb,
272 	.iolock       = __videobuf_iolock,
273 	.mmap_mapper  = __videobuf_mmap_mapper,
274 	.vaddr        = videobuf_to_vmalloc,
275 };
276 
videobuf_queue_vmalloc_init(struct videobuf_queue * q,const struct videobuf_queue_ops * ops,struct device * dev,spinlock_t * irqlock,enum v4l2_buf_type type,enum v4l2_field field,unsigned int msize,void * priv,struct mutex * ext_lock)277 void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
278 			 const struct videobuf_queue_ops *ops,
279 			 struct device *dev,
280 			 spinlock_t *irqlock,
281 			 enum v4l2_buf_type type,
282 			 enum v4l2_field field,
283 			 unsigned int msize,
284 			 void *priv,
285 			 struct mutex *ext_lock)
286 {
287 	videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
288 				 priv, &qops, ext_lock);
289 }
290 EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
291 
videobuf_to_vmalloc(struct videobuf_buffer * buf)292 void *videobuf_to_vmalloc(struct videobuf_buffer *buf)
293 {
294 	struct videobuf_vmalloc_memory *mem = buf->priv;
295 	BUG_ON(!mem);
296 	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
297 
298 	return mem->vaddr;
299 }
300 EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
301 
videobuf_vmalloc_free(struct videobuf_buffer * buf)302 void videobuf_vmalloc_free(struct videobuf_buffer *buf)
303 {
304 	struct videobuf_vmalloc_memory *mem = buf->priv;
305 
306 	/* mmapped memory can't be freed here, otherwise mmapped region
307 	   would be released, while still needed. In this case, the memory
308 	   release should happen inside videobuf_vm_close().
309 	   So, it should free memory only if the memory were allocated for
310 	   read() operation.
311 	 */
312 	if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
313 		return;
314 
315 	if (!mem)
316 		return;
317 
318 	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
319 
320 	vfree(mem->vaddr);
321 	mem->vaddr = NULL;
322 
323 	return;
324 }
325 EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
326 
327