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