V4L/DVB (7553): videobuf-vmalloc: fix STREAMOFF/STREAMON
[linux-2.6] / 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 gatter
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                 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
76                         if (NULL == q->bufs[i])
77                                 continue;
78
79                         if (q->bufs[i]->map != map)
80                                 continue;
81
82                         mem = q->bufs[i]->priv;
83                         if (mem) {
84                                 /* This callback is called only if kernel has
85                                    allocated memory and this memory is mmapped.
86                                    In this case, memory should be freed,
87                                    in order to do memory unmap.
88                                  */
89                                 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
90                                 vfree(mem->vmalloc);
91                                 mem->vmalloc = NULL;
92                         }
93
94                         q->bufs[i]->map   = NULL;
95                         q->bufs[i]->baddr = 0;
96                 }
97                 mutex_unlock(&q->vb_lock);
98                 kfree(map);
99         }
100         return;
101 }
102
103 static struct vm_operations_struct videobuf_vm_ops =
104 {
105         .open     = videobuf_vm_open,
106         .close    = videobuf_vm_close,
107 };
108
109 /* ---------------------------------------------------------------------
110  * vmalloc handlers for the generic methods
111  */
112
113 /* Allocated area consists on 3 parts:
114         struct video_buffer
115         struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
116         struct videobuf_dma_sg_memory
117  */
118
119 static void *__videobuf_alloc(size_t size)
120 {
121         struct videobuf_vmalloc_memory *mem;
122         struct videobuf_buffer *vb;
123
124         vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
125
126         mem = vb->priv = ((char *)vb)+size;
127         mem->magic=MAGIC_VMAL_MEM;
128
129         dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
130                 __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
131                 mem,(long)sizeof(*mem));
132
133         return vb;
134 }
135
136 static int __videobuf_iolock (struct videobuf_queue* q,
137                               struct videobuf_buffer *vb,
138                               struct v4l2_framebuffer *fbuf)
139 {
140         struct videobuf_vmalloc_memory *mem = vb->priv;
141
142         BUG_ON(!mem);
143
144         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
145
146         switch (vb->memory) {
147         case V4L2_MEMORY_MMAP:
148                 dprintk(1, "%s memory method MMAP\n", __func__);
149
150                 /* All handling should be done by __videobuf_mmap_mapper() */
151                 if (!mem->vmalloc) {
152                         printk(KERN_ERR "memory is not alloced/mmapped.\n");
153                         return -EINVAL;
154                 }
155                 break;
156         case V4L2_MEMORY_USERPTR:
157         {
158                 int pages = PAGE_ALIGN(vb->size);
159
160                 dprintk(1, "%s memory method USERPTR\n", __func__);
161
162 #if 1
163                 if (vb->baddr) {
164                         printk(KERN_ERR "USERPTR is currently not supported\n");
165                         return -EINVAL;
166                 }
167 #endif
168
169                 /* The only USERPTR currently supported is the one needed for
170                    read() method.
171                  */
172
173                 mem->vmalloc = vmalloc_user(pages);
174                 if (!mem->vmalloc) {
175                         printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
176                         return -ENOMEM;
177                 }
178                 dprintk(1, "vmalloc is at addr %p (%d pages)\n",
179                         mem->vmalloc, pages);
180
181 #if 0
182                 int rc;
183                 /* Kernel userptr is used also by read() method. In this case,
184                    there's no need to remap, since data will be copied to user
185                  */
186                 if (!vb->baddr)
187                         return 0;
188
189                 /* FIXME: to properly support USERPTR, remap should occur.
190                    The code bellow won't work, since mem->vma = NULL
191                  */
192                 /* Try to remap memory */
193                 rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
194                 if (rc < 0) {
195                         printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
196                         return -ENOMEM;
197                 }
198 #endif
199
200                 break;
201         }
202         case V4L2_MEMORY_OVERLAY:
203         default:
204                 dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
205
206                 /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
207                 printk(KERN_ERR "Memory method currently unsupported.\n");
208                 return -EINVAL;
209         }
210
211         return 0;
212 }
213
214 static int __videobuf_sync(struct videobuf_queue *q,
215                            struct videobuf_buffer *buf)
216 {
217         return 0;
218 }
219
220 static int __videobuf_mmap_free(struct videobuf_queue *q)
221 {
222         unsigned int i;
223
224         dprintk(1, "%s\n", __func__);
225         for (i = 0; i < VIDEO_MAX_FRAME; i++) {
226                 if (q->bufs[i]) {
227                         if (q->bufs[i]->map)
228                                 return -EBUSY;
229                 }
230         }
231
232         return 0;
233 }
234
235 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
236                          struct vm_area_struct *vma)
237 {
238         struct videobuf_vmalloc_memory *mem;
239         struct videobuf_mapping *map;
240         unsigned int first;
241         int retval, pages;
242         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
243
244         dprintk(1, "%s\n", __func__);
245         if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
246                 return -EINVAL;
247
248         /* look for first buffer to map */
249         for (first = 0; first < VIDEO_MAX_FRAME; first++) {
250                 if (NULL == q->bufs[first])
251                         continue;
252
253                 if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
254                         continue;
255                 if (q->bufs[first]->boff == offset)
256                         break;
257         }
258         if (VIDEO_MAX_FRAME == first) {
259                 dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
260                         (vma->vm_pgoff << PAGE_SHIFT));
261                 return -EINVAL;
262         }
263
264         /* create mapping + update buffer list */
265         map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
266         if (NULL == map)
267                 return -ENOMEM;
268
269         q->bufs[first]->map = map;
270         map->start = vma->vm_start;
271         map->end   = vma->vm_end;
272         map->q     = q;
273
274         q->bufs[first]->baddr = vma->vm_start;
275
276         mem = q->bufs[first]->priv;
277         BUG_ON(!mem);
278         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
279
280         pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
281         mem->vmalloc = vmalloc_user(pages);
282         if (!mem->vmalloc) {
283                 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
284                 goto error;
285         }
286         dprintk(1, "vmalloc is at addr %p (%d pages)\n",
287                 mem->vmalloc, pages);
288
289         /* Try to remap memory */
290         retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
291         if (retval < 0) {
292                 printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
293                 vfree(mem->vmalloc);
294                 goto error;
295         }
296
297         vma->vm_ops          = &videobuf_vm_ops;
298         vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
299         vma->vm_private_data = map;
300
301         dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
302                 map, q, vma->vm_start, vma->vm_end,
303                 (long int) q->bufs[first]->bsize,
304                 vma->vm_pgoff, first);
305
306         videobuf_vm_open(vma);
307
308         return 0;
309
310 error:
311         mem = NULL;
312         kfree(map);
313         return -ENOMEM;
314 }
315
316 static int __videobuf_copy_to_user ( struct videobuf_queue *q,
317                                 char __user *data, size_t count,
318                                 int nonblocking )
319 {
320         struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
321         BUG_ON (!mem);
322         MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
323
324         BUG_ON (!mem->vmalloc);
325
326         /* copy to userspace */
327         if (count > q->read_buf->size - q->read_off)
328                 count = q->read_buf->size - q->read_off;
329
330         if (copy_to_user(data, mem->vmalloc+q->read_off, count))
331                 return -EFAULT;
332
333         return count;
334 }
335
336 static int __videobuf_copy_stream ( struct videobuf_queue *q,
337                                 char __user *data, size_t count, size_t pos,
338                                 int vbihack, int nonblocking )
339 {
340         unsigned int  *fc;
341         struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
342         BUG_ON (!mem);
343         MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
344
345         if (vbihack) {
346                 /* dirty, undocumented hack -- pass the frame counter
347                         * within the last four bytes of each vbi data block.
348                         * We need that one to maintain backward compatibility
349                         * to all vbi decoding software out there ... */
350                 fc  = (unsigned int*)mem->vmalloc;
351                 fc += (q->read_buf->size>>2) -1;
352                 *fc = q->read_buf->field_count >> 1;
353                 dprintk(1,"vbihack: %d\n",*fc);
354         }
355
356         /* copy stuff using the common method */
357         count = __videobuf_copy_to_user (q,data,count,nonblocking);
358
359         if ( (count==-EFAULT) && (0 == pos) )
360                 return -EFAULT;
361
362         return count;
363 }
364
365 static struct videobuf_qtype_ops qops = {
366         .magic        = MAGIC_QTYPE_OPS,
367
368         .alloc        = __videobuf_alloc,
369         .iolock       = __videobuf_iolock,
370         .sync         = __videobuf_sync,
371         .mmap_free    = __videobuf_mmap_free,
372         .mmap_mapper  = __videobuf_mmap_mapper,
373         .video_copy_to_user = __videobuf_copy_to_user,
374         .copy_stream  = __videobuf_copy_stream,
375 };
376
377 void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
378                          struct videobuf_queue_ops *ops,
379                          void *dev,
380                          spinlock_t *irqlock,
381                          enum v4l2_buf_type type,
382                          enum v4l2_field field,
383                          unsigned int msize,
384                          void *priv)
385 {
386         videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
387                                  priv, &qops);
388 }
389
390 EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
391
392 void *videobuf_to_vmalloc (struct videobuf_buffer *buf)
393 {
394         struct videobuf_vmalloc_memory *mem=buf->priv;
395         BUG_ON (!mem);
396         MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
397
398         return mem->vmalloc;
399 }
400 EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
401
402 void videobuf_vmalloc_free (struct videobuf_buffer *buf)
403 {
404         struct videobuf_vmalloc_memory *mem = buf->priv;
405
406         /* mmapped memory can't be freed here, otherwise mmapped region
407            would be released, while still needed. In this case, the memory
408            release should happen inside videobuf_vm_close().
409            So, it should free memory only if the memory were allocated for
410            read() operation.
411          */
412         if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
413                 return;
414
415         if (!mem)
416                 return;
417
418         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
419
420         vfree(mem->vmalloc);
421         mem->vmalloc = NULL;
422
423         return;
424 }
425 EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
426
427 /*
428  * Local variables:
429  * c-basic-offset: 8
430  * End:
431  */