This source file includes following definitions.
- videobuf_vm_open
- videobuf_vm_close
- __videobuf_alloc_vb
- __videobuf_iolock
- __videobuf_mmap_mapper
- videobuf_queue_vmalloc_init
- videobuf_to_vmalloc
- videobuf_vmalloc_free
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 #include <linux/init.h>
  14 #include <linux/module.h>
  15 #include <linux/moduleparam.h>
  16 #include <linux/slab.h>
  17 #include <linux/interrupt.h>
  18 
  19 #include <linux/pci.h>
  20 #include <linux/vmalloc.h>
  21 #include <linux/pagemap.h>
  22 #include <asm/page.h>
  23 #include <asm/pgtable.h>
  24 
  25 #include <media/videobuf-vmalloc.h>
  26 
  27 #define MAGIC_DMABUF   0x17760309
  28 #define MAGIC_VMAL_MEM 0x18221223
  29 
  30 #define MAGIC_CHECK(is, should)                                         \
  31         if (unlikely((is) != (should))) {                               \
  32                 printk(KERN_ERR "magic mismatch: %x (expected %x)\n",   \
  33                                 is, should);                            \
  34                 BUG();                                                  \
  35         }
  36 
  37 static int debug;
  38 module_param(debug, int, 0644);
  39 
  40 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
  41 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");
  42 MODULE_LICENSE("GPL");
  43 
  44 #define dprintk(level, fmt, arg...)                                     \
  45         if (debug >= level)                                             \
  46                 printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
  47 
  48 
  49 
  50 
  51 static void videobuf_vm_open(struct vm_area_struct *vma)
  52 {
  53         struct videobuf_mapping *map = vma->vm_private_data;
  54 
  55         dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
  56                 map->count, vma->vm_start, vma->vm_end);
  57 
  58         map->count++;
  59 }
  60 
  61 static void videobuf_vm_close(struct vm_area_struct *vma)
  62 {
  63         struct videobuf_mapping *map = vma->vm_private_data;
  64         struct videobuf_queue *q = map->q;
  65         int i;
  66 
  67         dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
  68                 map->count, vma->vm_start, vma->vm_end);
  69 
  70         map->count--;
  71         if (0 == map->count) {
  72                 struct videobuf_vmalloc_memory *mem;
  73 
  74                 dprintk(1, "munmap %p q=%p\n", map, q);
  75                 videobuf_queue_lock(q);
  76 
  77                 
  78                 if (q->streaming)
  79                         videobuf_queue_cancel(q);
  80 
  81                 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
  82                         if (NULL == q->bufs[i])
  83                                 continue;
  84 
  85                         if (q->bufs[i]->map != map)
  86                                 continue;
  87 
  88                         mem = q->bufs[i]->priv;
  89                         if (mem) {
  90                                 
  91 
  92 
  93 
  94 
  95 
  96                                 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
  97 
  98                                 
  99 
 100 
 101                                 dprintk(1, "%s: buf[%d] freeing (%p)\n",
 102                                         __func__, i, mem->vaddr);
 103 
 104                                 vfree(mem->vaddr);
 105                                 mem->vaddr = NULL;
 106                         }
 107 
 108                         q->bufs[i]->map   = NULL;
 109                         q->bufs[i]->baddr = 0;
 110                 }
 111 
 112                 kfree(map);
 113 
 114                 videobuf_queue_unlock(q);
 115         }
 116 
 117         return;
 118 }
 119 
 120 static const struct vm_operations_struct videobuf_vm_ops = {
 121         .open     = videobuf_vm_open,
 122         .close    = videobuf_vm_close,
 123 };
 124 
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 static struct videobuf_buffer *__videobuf_alloc_vb(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         if (!vb)
 142                 return vb;
 143 
 144         mem = vb->priv = ((char *)vb) + size;
 145         mem->magic = MAGIC_VMAL_MEM;
 146 
 147         dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
 148                 __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb),
 149                 mem, (long)sizeof(*mem));
 150 
 151         return vb;
 152 }
 153 
 154 static int __videobuf_iolock(struct videobuf_queue *q,
 155                              struct videobuf_buffer *vb,
 156                              struct v4l2_framebuffer *fbuf)
 157 {
 158         struct videobuf_vmalloc_memory *mem = vb->priv;
 159         int pages;
 160 
 161         BUG_ON(!mem);
 162 
 163         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 164 
 165         switch (vb->memory) {
 166         case V4L2_MEMORY_MMAP:
 167                 dprintk(1, "%s memory method MMAP\n", __func__);
 168 
 169                 
 170                 if (!mem->vaddr) {
 171                         printk(KERN_ERR "memory is not allocated/mmapped.\n");
 172                         return -EINVAL;
 173                 }
 174                 break;
 175         case V4L2_MEMORY_USERPTR:
 176                 pages = PAGE_ALIGN(vb->size);
 177 
 178                 dprintk(1, "%s memory method USERPTR\n", __func__);
 179 
 180                 if (vb->baddr) {
 181                         printk(KERN_ERR "USERPTR is currently not supported\n");
 182                         return -EINVAL;
 183                 }
 184 
 185                 
 186 
 187 
 188 
 189                 mem->vaddr = vmalloc_user(pages);
 190                 if (!mem->vaddr) {
 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->vaddr, pages);
 196                 break;
 197         case V4L2_MEMORY_OVERLAY:
 198         default:
 199                 dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
 200 
 201                 
 202                 printk(KERN_ERR "Memory method currently unsupported.\n");
 203                 return -EINVAL;
 204         }
 205 
 206         return 0;
 207 }
 208 
 209 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
 210                                   struct videobuf_buffer *buf,
 211                                   struct vm_area_struct *vma)
 212 {
 213         struct videobuf_vmalloc_memory *mem;
 214         struct videobuf_mapping *map;
 215         int retval, pages;
 216 
 217         dprintk(1, "%s\n", __func__);
 218 
 219         
 220         map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
 221         if (NULL == map)
 222                 return -ENOMEM;
 223 
 224         buf->map = map;
 225         map->q     = q;
 226 
 227         buf->baddr = vma->vm_start;
 228 
 229         mem = buf->priv;
 230         BUG_ON(!mem);
 231         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 232 
 233         pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
 234         mem->vaddr = vmalloc_user(pages);
 235         if (!mem->vaddr) {
 236                 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
 237                 goto error;
 238         }
 239         dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages);
 240 
 241         
 242         retval = remap_vmalloc_range(vma, mem->vaddr, 0);
 243         if (retval < 0) {
 244                 printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
 245                 vfree(mem->vaddr);
 246                 goto error;
 247         }
 248 
 249         vma->vm_ops          = &videobuf_vm_ops;
 250         vma->vm_flags       |= VM_DONTEXPAND | VM_DONTDUMP;
 251         vma->vm_private_data = map;
 252 
 253         dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
 254                 map, q, vma->vm_start, vma->vm_end,
 255                 (long int)buf->bsize,
 256                 vma->vm_pgoff, buf->i);
 257 
 258         videobuf_vm_open(vma);
 259 
 260         return 0;
 261 
 262 error:
 263         mem = NULL;
 264         kfree(map);
 265         return -ENOMEM;
 266 }
 267 
 268 static struct videobuf_qtype_ops qops = {
 269         .magic        = MAGIC_QTYPE_OPS,
 270 
 271         .alloc_vb     = __videobuf_alloc_vb,
 272         .iolock       = __videobuf_iolock,
 273         .mmap_mapper  = __videobuf_mmap_mapper,
 274         .vaddr        = videobuf_to_vmalloc,
 275 };
 276 
 277 void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
 278                          const struct videobuf_queue_ops *ops,
 279                          struct device *dev,
 280                          spinlock_t *irqlock,
 281                          enum v4l2_buf_type type,
 282                          enum v4l2_field field,
 283                          unsigned int msize,
 284                          void *priv,
 285                          struct mutex *ext_lock)
 286 {
 287         videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
 288                                  priv, &qops, ext_lock);
 289 }
 290 EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
 291 
 292 void *videobuf_to_vmalloc(struct videobuf_buffer *buf)
 293 {
 294         struct videobuf_vmalloc_memory *mem = buf->priv;
 295         BUG_ON(!mem);
 296         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 297 
 298         return mem->vaddr;
 299 }
 300 EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
 301 
 302 void videobuf_vmalloc_free(struct videobuf_buffer *buf)
 303 {
 304         struct videobuf_vmalloc_memory *mem = buf->priv;
 305 
 306         
 307 
 308 
 309 
 310 
 311 
 312         if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
 313                 return;
 314 
 315         if (!mem)
 316                 return;
 317 
 318         MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 319 
 320         vfree(mem->vaddr);
 321         mem->vaddr = NULL;
 322 
 323         return;
 324 }
 325 EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
 326