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