Showing error 752

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/media/video/videobuf-vmalloc.c
Line in file: 142
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Smatch (1.59)
Entered: 2011-11-07 22:22:22 UTC


Source:

  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
 36static int debug;
 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) \
 44        printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
 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
 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
 60static 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
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, ...)
132        struct videobuf_dma_sg_memory
133 */
134
135static 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
152static 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
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
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
250static 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
325error:
326        mem = NULL;
327        kfree(map);
328        return -ENOMEM;
329}
330
331static 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
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;
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
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,
388        .video_copy_to_user = __videobuf_copy_to_user,
389        .copy_stream  = __videobuf_copy_stream,
390        .vmalloc      = videobuf_to_vmalloc,
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{
402        videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
403                                 priv, &qops);
404}
405
406EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
407
408void *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}
416EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
417
418void 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}
441EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
442
443/*
444 * Local variables:
445 * c-basic-offset: 8
446 * End:
447 */