linux/drivers/media/common/videobuf2/videobuf2-memops.c
<<
>>
Prefs
   1/*
   2 * videobuf2-memops.c - generic memory handling routines for videobuf2
   3 *
   4 * Copyright (C) 2010 Samsung Electronics
   5 *
   6 * Author: Pawel Osciak <pawel@osciak.com>
   7 *         Marek Szyprowski <m.szyprowski@samsung.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation.
  12 */
  13
  14#include <linux/slab.h>
  15#include <linux/module.h>
  16#include <linux/dma-mapping.h>
  17#include <linux/vmalloc.h>
  18#include <linux/mm.h>
  19#include <linux/sched.h>
  20#include <linux/file.h>
  21
  22#include <media/videobuf2-v4l2.h>
  23#include <media/videobuf2-memops.h>
  24
  25/**
  26 * vb2_create_framevec() - map virtual addresses to pfns
  27 * @start:      Virtual user address where we start mapping
  28 * @length:     Length of a range to map
  29 * @write:      Should we map for writing into the area
  30 *
  31 * This function allocates and fills in a vector with pfns corresponding to
  32 * virtual address range passed in arguments. If pfns have corresponding pages,
  33 * page references are also grabbed to pin pages in memory. The function
  34 * returns pointer to the vector on success and error pointer in case of
  35 * failure. Returned vector needs to be freed via vb2_destroy_pfnvec().
  36 */
  37struct frame_vector *vb2_create_framevec(unsigned long start,
  38                                         unsigned long length,
  39                                         bool write)
  40{
  41        int ret;
  42        unsigned long first, last;
  43        unsigned long nr;
  44        struct frame_vector *vec;
  45        unsigned int flags = FOLL_FORCE;
  46
  47        if (write)
  48                flags |= FOLL_WRITE;
  49
  50        first = start >> PAGE_SHIFT;
  51        last = (start + length - 1) >> PAGE_SHIFT;
  52        nr = last - first + 1;
  53        vec = frame_vector_create(nr);
  54        if (!vec)
  55                return ERR_PTR(-ENOMEM);
  56        ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
  57        if (ret < 0)
  58                goto out_destroy;
  59        /* We accept only complete set of PFNs */
  60        if (ret != nr) {
  61                ret = -EFAULT;
  62                goto out_release;
  63        }
  64        return vec;
  65out_release:
  66        put_vaddr_frames(vec);
  67out_destroy:
  68        frame_vector_destroy(vec);
  69        return ERR_PTR(ret);
  70}
  71EXPORT_SYMBOL(vb2_create_framevec);
  72
  73/**
  74 * vb2_destroy_framevec() - release vector of mapped pfns
  75 * @vec:        vector of pfns / pages to release
  76 *
  77 * This releases references to all pages in the vector @vec (if corresponding
  78 * pfns are backed by pages) and frees the passed vector.
  79 */
  80void vb2_destroy_framevec(struct frame_vector *vec)
  81{
  82        put_vaddr_frames(vec);
  83        frame_vector_destroy(vec);
  84}
  85EXPORT_SYMBOL(vb2_destroy_framevec);
  86
  87/**
  88 * vb2_common_vm_open() - increase refcount of the vma
  89 * @vma:        virtual memory region for the mapping
  90 *
  91 * This function adds another user to the provided vma. It expects
  92 * struct vb2_vmarea_handler pointer in vma->vm_private_data.
  93 */
  94static void vb2_common_vm_open(struct vm_area_struct *vma)
  95{
  96        struct vb2_vmarea_handler *h = vma->vm_private_data;
  97
  98        pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
  99               __func__, h, refcount_read(h->refcount), vma->vm_start,
 100               vma->vm_end);
 101
 102        refcount_inc(h->refcount);
 103}
 104
 105/**
 106 * vb2_common_vm_close() - decrease refcount of the vma
 107 * @vma:        virtual memory region for the mapping
 108 *
 109 * This function releases the user from the provided vma. It expects
 110 * struct vb2_vmarea_handler pointer in vma->vm_private_data.
 111 */
 112static void vb2_common_vm_close(struct vm_area_struct *vma)
 113{
 114        struct vb2_vmarea_handler *h = vma->vm_private_data;
 115
 116        pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
 117               __func__, h, refcount_read(h->refcount), vma->vm_start,
 118               vma->vm_end);
 119
 120        h->put(h->arg);
 121}
 122
 123/*
 124 * vb2_common_vm_ops - common vm_ops used for tracking refcount of mmaped
 125 * video buffers
 126 */
 127const struct vm_operations_struct vb2_common_vm_ops = {
 128        .open = vb2_common_vm_open,
 129        .close = vb2_common_vm_close,
 130};
 131EXPORT_SYMBOL_GPL(vb2_common_vm_ops);
 132
 133MODULE_DESCRIPTION("common memory handling routines for videobuf2");
 134MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
 135MODULE_LICENSE("GPL");
 136