const: mark struct vm_struct_operations
[linux-2.6.git] / drivers / media / video / 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)  if (unlikely((is) != (should))) \
34         { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
35
36 static int debug;
37 module_param(debug, int, 0644);
38
39 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
40 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
41 MODULE_LICENSE("GPL");
42
43 #define dprintk(level, fmt, arg...)     if (debug >= level) \
44         printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
45
46
47 /***************************************************************************/
48
49 static void
50 videobuf_vm_open(struct vm_area_struct *vma)
51 {
52         struct videobuf_mapping *map = vma->vm_private_data;
53
54         dprintk(2,"vm_open %p [count=%u,vma=%08lx-%08lx]\n",map,
55                 map->count,vma->vm_start,vma->vm_end);
56
57         map->count++;
58 }
59
60 static void videobuf_vm_close(struct vm_area_struct *vma)
61 {
62         struct videobuf_mapping *map = vma->vm_private_data;
63         struct videobuf_queue *q = map->q;
64         int i;
65
66         dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
67                 map->count, vma->vm_start, vma->vm_end);
68
69         map->count--;
70         if (0 == map->count) {
71                 struct videobuf_vmalloc_memory *mem;
72
73                 dprintk(1, "munmap %p q=%p\n", map, q);
74                 mutex_lock(&q->vb_lock);
75
76                 /* We need first to cancel streams, before unmapping */
77                 if (q->streaming)
78                         videobuf_queue_cancel(q);
79
80                 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
81                         if (NULL == q->bufs[i])
82                                 continue;
83
84                         if (q->bufs[i]->map != map)
85                                 continue;
86
87                         mem = q->bufs[i]->priv;
88                         if (mem) {
89                                 /* This callback is called only if kernel has
90                                    allocated memory and this memory is mmapped.
91                                    In this case, memory should be freed,
92                                    in order to do memory unmap.
93                                  */
94
95                                 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
96
97                                 /* vfree is not atomic - can't be
98                                    called with IRQ's disabled
99                                  */
100                                 dprintk(1, "%s: buf[%d] freeing (%p)\n",
101                                         __func__, i, mem->vmalloc);
102
103                                 vfree(mem->vmalloc);
104                                 mem->vmalloc = NULL;
105                         }
106
107                         q->bufs[i]->map   = NULL;
108                         q->bufs[i]->baddr = 0;
109                 }
110
111                 kfree(map);
112
113                 mutex_unlock(&q->vb_lock);
114         }
115
116         return;
117 }
118
119 static const struct vm_operations_struct videobuf_vm_ops =
120 {
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
135 static void *__videobuf_alloc(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
142         mem = vb->priv = ((char *)vb)+size;
143         mem->magic=MAGIC_VMAL_MEM;
144
145         dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
146                 __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
147                 mem,(long)sizeof(*mem));
148
149         return vb;
150 }
151
152 static int __videobuf_iolock (struct videobuf_queue* q,
153                               struct videobuf_buffer *vb,
154                               struct v4l2_framebuffer *fbuf)
155 {
156         struct videobuf_vmalloc_memory *mem = vb->priv;
157         int pages;
158
159         BUG_ON(!mem);
160
161         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
162
163         switch (vb->memory) {
164         case V4L2_MEMORY_MMAP:
165                 dprintk(1, "%s memory method MMAP\n", __func__);
166
167                 /* All handling should be done by __videobuf_mmap_mapper() */
168                 if (!mem->vmalloc) {
169                         printk(KERN_ERR "memory is not alloced/mmapped.\n");
170                         return -EINVAL;
171                 }
172                 break;
173         case V4L2_MEMORY_USERPTR:
174                 pages = PAGE_ALIGN(vb->size);
175
176                 dprintk(1, "%s memory method USERPTR\n", __func__);
177
178 #if 1
179                 if (vb->baddr) {
180                         printk(KERN_ERR "USERPTR is currently not supported\n");
181                         return -EINVAL;
182                 }
183 #endif
184
185                 /* The only USERPTR currently supported is the one needed for
186                    read() method.
187                  */
188
189                 mem->vmalloc = vmalloc_user(pages);
190                 if (!mem->vmalloc) {
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->vmalloc, pages);
196
197 #if 0
198                 int rc;
199                 /* Kernel userptr is used also by read() method. In this case,
200                    there's no need to remap, since data will be copied to user
201                  */
202                 if (!vb->baddr)
203                         return 0;
204
205                 /* FIXME: to properly support USERPTR, remap should occur.
206                    The code below won't work, since mem->vma = NULL
207                  */
208                 /* Try to remap memory */
209                 rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
210                 if (rc < 0) {
211                         printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
212                         return -ENOMEM;
213                 }
214 #endif
215
216                 break;
217         case V4L2_MEMORY_OVERLAY:
218         default:
219                 dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
220
221                 /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
222                 printk(KERN_ERR "Memory method currently unsupported.\n");
223                 return -EINVAL;
224         }
225
226         return 0;
227 }
228
229 static int __videobuf_sync(struct videobuf_queue *q,
230                            struct videobuf_buffer *buf)
231 {
232         return 0;
233 }
234
235 static int __videobuf_mmap_free(struct videobuf_queue *q)
236 {
237         unsigned int i;
238
239         dprintk(1, "%s\n", __func__);
240         for (i = 0; i < VIDEO_MAX_FRAME; i++) {
241                 if (q->bufs[i]) {
242                         if (q->bufs[i]->map)
243                                 return -EBUSY;
244                 }
245         }
246
247         return 0;
248 }
249
250 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
251                          struct vm_area_struct *vma)
252 {
253         struct videobuf_vmalloc_memory *mem;
254         struct videobuf_mapping *map;
255         unsigned int first;
256         int retval, pages;
257         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
258
259         dprintk(1, "%s\n", __func__);
260         if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
261                 return -EINVAL;
262
263         /* look for first buffer to map */
264         for (first = 0; first < VIDEO_MAX_FRAME; first++) {
265                 if (NULL == q->bufs[first])
266                         continue;
267
268                 if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
269                         continue;
270                 if (q->bufs[first]->boff == offset)
271                         break;
272         }
273         if (VIDEO_MAX_FRAME == first) {
274                 dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
275                         (vma->vm_pgoff << PAGE_SHIFT));
276                 return -EINVAL;
277         }
278
279         /* create mapping + update buffer list */
280         map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
281         if (NULL == map)
282                 return -ENOMEM;
283
284         q->bufs[first]->map = map;
285         map->start = vma->vm_start;
286         map->end   = vma->vm_end;
287         map->q     = q;
288
289         q->bufs[first]->baddr = vma->vm_start;
290
291         mem = q->bufs[first]->priv;
292         BUG_ON(!mem);
293         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
294
295         pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
296         mem->vmalloc = vmalloc_user(pages);
297         if (!mem->vmalloc) {
298                 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
299                 goto error;
300         }
301         dprintk(1, "vmalloc is at addr %p (%d pages)\n",
302                 mem->vmalloc, pages);
303
304         /* Try to remap memory */
305         retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
306         if (retval < 0) {
307                 printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
308                 vfree(mem->vmalloc);
309                 goto error;
310         }
311
312         vma->vm_ops          = &videobuf_vm_ops;
313         vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
314         vma->vm_private_data = map;
315
316         dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
317                 map, q, vma->vm_start, vma->vm_end,
318                 (long int) q->bufs[first]->bsize,
319                 vma->vm_pgoff, first);
320
321         videobuf_vm_open(vma);
322
323         return 0;
324
325 error:
326         mem = NULL;
327         kfree(map);
328         return -ENOMEM;
329 }
330
331 static int __videobuf_copy_to_user ( struct videobuf_queue *q,
332                                 char __user *data, size_t count,
333                                 int nonblocking )
334 {
335         struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
336         BUG_ON (!mem);
337         MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
338
339         BUG_ON (!mem->vmalloc);
340
341         /* copy to userspace */
342         if (count > q->read_buf->size - q->read_off)
343                 count = q->read_buf->size - q->read_off;
344
345         if (copy_to_user(data, mem->vmalloc+q->read_off, count))
346                 return -EFAULT;
347
348         return count;
349 }
350
351 static int __videobuf_copy_stream ( struct videobuf_queue *q,
352                                 char __user *data, size_t count, size_t pos,
353                                 int vbihack, int nonblocking )
354 {
355         unsigned int  *fc;
356         struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
357         BUG_ON (!mem);
358         MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
359
360         if (vbihack) {
361                 /* dirty, undocumented hack -- pass the frame counter
362                         * within the last four bytes of each vbi data block.
363                         * We need that one to maintain backward compatibility
364                         * to all vbi decoding software out there ... */
365                 fc  = (unsigned int*)mem->vmalloc;
366                 fc += (q->read_buf->size>>2) -1;
367                 *fc = q->read_buf->field_count >> 1;
368                 dprintk(1,"vbihack: %d\n",*fc);
369         }
370
371         /* copy stuff using the common method */
372         count = __videobuf_copy_to_user (q,data,count,nonblocking);
373
374         if ( (count==-EFAULT) && (0 == pos) )
375                 return -EFAULT;
376
377         return count;
378 }
379
380 static struct videobuf_qtype_ops qops = {
381         .magic        = MAGIC_QTYPE_OPS,
382
383         .alloc        = __videobuf_alloc,
384         .iolock       = __videobuf_iolock,
385         .sync         = __videobuf_sync,
386         .mmap_free    = __videobuf_mmap_free,
387         .mmap_mapper  = __videobuf_mmap_mapper,
388         .video_copy_to_user = __videobuf_copy_to_user,
389         .copy_stream  = __videobuf_copy_stream,
390         .vmalloc      = videobuf_to_vmalloc,
391 };
392
393 void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
394                          struct videobuf_queue_ops *ops,
395                          void *dev,
396                          spinlock_t *irqlock,
397                          enum v4l2_buf_type type,
398                          enum v4l2_field field,
399                          unsigned int msize,
400                          void *priv)
401 {
402         videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
403                                  priv, &qops);
404 }
405
406 EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
407
408 void *videobuf_to_vmalloc (struct videobuf_buffer *buf)
409 {
410         struct videobuf_vmalloc_memory *mem=buf->priv;
411         BUG_ON (!mem);
412         MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
413
414         return mem->vmalloc;
415 }
416 EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
417
418 void videobuf_vmalloc_free (struct videobuf_buffer *buf)
419 {
420         struct videobuf_vmalloc_memory *mem = buf->priv;
421
422         /* mmapped memory can't be freed here, otherwise mmapped region
423            would be released, while still needed. In this case, the memory
424            release should happen inside videobuf_vm_close().
425            So, it should free memory only if the memory were allocated for
426            read() operation.
427          */
428         if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
429                 return;
430
431         if (!mem)
432                 return;
433
434         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
435
436         vfree(mem->vmalloc);
437         mem->vmalloc = NULL;
438
439         return;
440 }
441 EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
442
443 /*
444  * Local variables:
445  * c-basic-offset: 8
446  * End:
447  */