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