V4L/DVB (9834): wm8775: convert to v4l2_subdev.
[linux-2.6-block.git] / drivers / media / video / videobuf-vmalloc.c
CommitLineData
87b9ad07
MCC
1/*
2 * helper functions for vmalloc video4linux capture buffers
3 *
5d6aaf50 4 * The functions expect the hardware being able to scatter gather
87b9ad07
MCC
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
ff699e6b 36static int debug;
87b9ad07
MCC
37module_param(debug, int, 0644);
38
39MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
40MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
41MODULE_LICENSE("GPL");
42
43#define dprintk(level, fmt, arg...) if (debug >= level) \
493977f0 44 printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
87b9ad07
MCC
45
46
47/***************************************************************************/
48
49static void
50videobuf_vm_open(struct vm_area_struct *vma)
51{
52 struct videobuf_mapping *map = vma->vm_private_data;
53
0b29669c 54 dprintk(2,"vm_open %p [count=%u,vma=%08lx-%08lx]\n",map,
87b9ad07
MCC
55 map->count,vma->vm_start,vma->vm_end);
56
57 map->count++;
58}
59
aaea56af 60static void videobuf_vm_close(struct vm_area_struct *vma)
87b9ad07
MCC
61{
62 struct videobuf_mapping *map = vma->vm_private_data;
63 struct videobuf_queue *q = map->q;
87b9ad07
MCC
64 int i;
65
aaea56af
MCC
66 dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
67 map->count, vma->vm_start, vma->vm_end);
87b9ad07
MCC
68
69 map->count--;
70 if (0 == map->count) {
aaea56af
MCC
71 struct videobuf_vmalloc_memory *mem;
72
73 dprintk(1, "munmap %p q=%p\n", map, q);
64f9477f 74 mutex_lock(&q->vb_lock);
aa9479ed
MCC
75
76 /* We need first to cancel streams, before unmapping */
77 if (q->streaming)
78 videobuf_queue_cancel(q);
79
87b9ad07
MCC
80 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
81 if (NULL == q->bufs[i])
82 continue;
87b9ad07 83
851c0c96 84 if (q->bufs[i]->map != map)
87b9ad07 85 continue;
123f8ef6 86
aaea56af
MCC
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 */
aa9479ed 94
aaea56af 95 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
aa9479ed
MCC
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
aaea56af
MCC
103 vfree(mem->vmalloc);
104 mem->vmalloc = NULL;
105 }
106
851c0c96 107 q->bufs[i]->map = NULL;
87b9ad07 108 q->bufs[i]->baddr = 0;
87b9ad07 109 }
aa9479ed 110
87b9ad07 111 kfree(map);
aa9479ed
MCC
112
113 mutex_unlock(&q->vb_lock);
87b9ad07 114 }
aa9479ed 115
87b9ad07
MCC
116 return;
117}
118
119static 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, ...)
0705135e 132 struct videobuf_dma_sg_memory
87b9ad07
MCC
133 */
134
135static void *__videobuf_alloc(size_t size)
136{
384b835a 137 struct videobuf_vmalloc_memory *mem;
87b9ad07
MCC
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",
7e28adb2 146 __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
87b9ad07
MCC
147 mem,(long)sizeof(*mem));
148
149 return vb;
150}
151
152static int __videobuf_iolock (struct videobuf_queue* q,
153 struct videobuf_buffer *vb,
154 struct v4l2_framebuffer *fbuf)
155{
968ced78 156 struct videobuf_vmalloc_memory *mem = vb->priv;
aa9479ed 157 int pages;
87b9ad07
MCC
158
159 BUG_ON(!mem);
160
968ced78 161 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad07 162
968ced78
MCC
163 switch (vb->memory) {
164 case V4L2_MEMORY_MMAP:
165 dprintk(1, "%s memory method MMAP\n", __func__);
87b9ad07 166
968ced78
MCC
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:
aa9479ed 174 pages = PAGE_ALIGN(vb->size);
87b9ad07 175
968ced78
MCC
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
87b9ad07 184
968ced78
MCC
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;
87b9ad07 193 }
968ced78
MCC
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.
de1e575d 206 The code below won't work, since mem->vma = NULL
968ced78
MCC
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;
968ced78
MCC
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;
87b9ad07
MCC
224 }
225
226 return 0;
227}
228
229static int __videobuf_sync(struct videobuf_queue *q,
230 struct videobuf_buffer *buf)
231{
232 return 0;
233}
234
235static int __videobuf_mmap_free(struct videobuf_queue *q)
236{
237 unsigned int i;
238
968ced78 239 dprintk(1, "%s\n", __func__);
87b9ad07
MCC
240 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
241 if (q->bufs[i]) {
851c0c96 242 if (q->bufs[i]->map)
87b9ad07
MCC
243 return -EBUSY;
244 }
245 }
246
247 return 0;
248}
249
250static int __videobuf_mmap_mapper(struct videobuf_queue *q,
251 struct vm_area_struct *vma)
252{
384b835a 253 struct videobuf_vmalloc_memory *mem;
87b9ad07
MCC
254 struct videobuf_mapping *map;
255 unsigned int first;
968ced78 256 int retval, pages;
87b9ad07
MCC
257 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
258
968ced78
MCC
259 dprintk(1, "%s\n", __func__);
260 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
87b9ad07
MCC
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 }
87b9ad07
MCC
278
279 /* create mapping + update buffer list */
968ced78 280 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
87b9ad07
MCC
281 if (NULL == map)
282 return -ENOMEM;
283
968ced78 284 q->bufs[first]->map = map;
87b9ad07
MCC
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
968ced78
MCC
291 mem = q->bufs[first]->priv;
292 BUG_ON(!mem);
293 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad07 294
968ced78
MCC
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);
851c0c96 303
87b9ad07 304 /* Try to remap memory */
968ced78
MCC
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;
87b9ad07
MCC
310 }
311
968ced78
MCC
312 vma->vm_ops = &videobuf_vm_ops;
313 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
314 vma->vm_private_data = map;
315
87b9ad07 316 dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
968ced78 317 map, q, vma->vm_start, vma->vm_end,
87b9ad07 318 (long int) q->bufs[first]->bsize,
968ced78 319 vma->vm_pgoff, first);
87b9ad07
MCC
320
321 videobuf_vm_open(vma);
322
968ced78
MCC
323 return 0;
324
325error:
326 mem = NULL;
327 kfree(map);
328 return -ENOMEM;
87b9ad07
MCC
329}
330
87b9ad07
MCC
331static int __videobuf_copy_to_user ( struct videobuf_queue *q,
332 char __user *data, size_t count,
333 int nonblocking )
334{
384b835a 335 struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
87b9ad07
MCC
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
351static 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;
384b835a 356 struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
87b9ad07
MCC
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
380static 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,
13bcd5d0 388 .video_copy_to_user = __videobuf_copy_to_user,
87b9ad07 389 .copy_stream = __videobuf_copy_stream,
59d34489 390 .vmalloc = videobuf_to_vmalloc,
87b9ad07
MCC
391};
392
393void 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{
d4cae5a5
MCC
402 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
403 priv, &qops);
87b9ad07
MCC
404}
405
406EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
407
408void *videobuf_to_vmalloc (struct videobuf_buffer *buf)
409{
384b835a 410 struct videobuf_vmalloc_memory *mem=buf->priv;
87b9ad07
MCC
411 BUG_ON (!mem);
412 MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
413
414 return mem->vmalloc;
415}
416EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
417
418void videobuf_vmalloc_free (struct videobuf_buffer *buf)
419{
968ced78 420 struct videobuf_vmalloc_memory *mem = buf->priv;
87b9ad07 421
aaea56af
MCC
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 == 0))
429 return;
430
968ced78
MCC
431 if (!mem)
432 return;
433
434 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad07
MCC
435
436 vfree(mem->vmalloc);
968ced78
MCC
437 mem->vmalloc = NULL;
438
87b9ad07
MCC
439 return;
440}
441EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
442
443/*
444 * Local variables:
445 * c-basic-offset: 8
446 * End:
447 */