Merge branches 'tracing/kmemtrace2' and 'tracing/ftrace' into tracing/urgent
[deliverable/linux.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 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 == 0))
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 */
This page took 0.046508 seconds and 5 git commands to generate.