Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * videobuf2-memops.c - generic memory handling routines for videobuf2
0003  *
0004  * Copyright (C) 2010 Samsung Electronics
0005  *
0006  * Author: Pawel Osciak <pawel@osciak.com>
0007  *     Marek Szyprowski <m.szyprowski@samsung.com>
0008  *
0009  * This program is free software; you can redistribute it and/or modify
0010  * it under the terms of the GNU General Public License as published by
0011  * the Free Software Foundation.
0012  */
0013 
0014 #include <linux/slab.h>
0015 #include <linux/module.h>
0016 #include <linux/dma-mapping.h>
0017 #include <linux/vmalloc.h>
0018 #include <linux/mm.h>
0019 #include <linux/sched.h>
0020 #include <linux/file.h>
0021 
0022 #include <media/videobuf2-v4l2.h>
0023 #include <media/videobuf2-memops.h>
0024 
0025 /**
0026  * vb2_create_framevec() - map virtual addresses to pfns
0027  * @start:  Virtual user address where we start mapping
0028  * @length: Length of a range to map
0029  *
0030  * This function allocates and fills in a vector with pfns corresponding to
0031  * virtual address range passed in arguments. If pfns have corresponding pages,
0032  * page references are also grabbed to pin pages in memory. The function
0033  * returns pointer to the vector on success and error pointer in case of
0034  * failure. Returned vector needs to be freed via vb2_destroy_pfnvec().
0035  */
0036 struct frame_vector *vb2_create_framevec(unsigned long start,
0037                      unsigned long length)
0038 {
0039     int ret;
0040     unsigned long first, last;
0041     unsigned long nr;
0042     struct frame_vector *vec;
0043 
0044     first = start >> PAGE_SHIFT;
0045     last = (start + length - 1) >> PAGE_SHIFT;
0046     nr = last - first + 1;
0047     vec = frame_vector_create(nr);
0048     if (!vec)
0049         return ERR_PTR(-ENOMEM);
0050     ret = get_vaddr_frames(start & PAGE_MASK, nr, vec);
0051     if (ret < 0)
0052         goto out_destroy;
0053     /* We accept only complete set of PFNs */
0054     if (ret != nr) {
0055         ret = -EFAULT;
0056         goto out_release;
0057     }
0058     return vec;
0059 out_release:
0060     put_vaddr_frames(vec);
0061 out_destroy:
0062     frame_vector_destroy(vec);
0063     return ERR_PTR(ret);
0064 }
0065 EXPORT_SYMBOL(vb2_create_framevec);
0066 
0067 /**
0068  * vb2_destroy_framevec() - release vector of mapped pfns
0069  * @vec:    vector of pfns / pages to release
0070  *
0071  * This releases references to all pages in the vector @vec (if corresponding
0072  * pfns are backed by pages) and frees the passed vector.
0073  */
0074 void vb2_destroy_framevec(struct frame_vector *vec)
0075 {
0076     put_vaddr_frames(vec);
0077     frame_vector_destroy(vec);
0078 }
0079 EXPORT_SYMBOL(vb2_destroy_framevec);
0080 
0081 /**
0082  * vb2_common_vm_open() - increase refcount of the vma
0083  * @vma:    virtual memory region for the mapping
0084  *
0085  * This function adds another user to the provided vma. It expects
0086  * struct vb2_vmarea_handler pointer in vma->vm_private_data.
0087  */
0088 static void vb2_common_vm_open(struct vm_area_struct *vma)
0089 {
0090     struct vb2_vmarea_handler *h = vma->vm_private_data;
0091 
0092     pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
0093            __func__, h, refcount_read(h->refcount), vma->vm_start,
0094            vma->vm_end);
0095 
0096     refcount_inc(h->refcount);
0097 }
0098 
0099 /**
0100  * vb2_common_vm_close() - decrease refcount of the vma
0101  * @vma:    virtual memory region for the mapping
0102  *
0103  * This function releases the user from the provided vma. It expects
0104  * struct vb2_vmarea_handler pointer in vma->vm_private_data.
0105  */
0106 static void vb2_common_vm_close(struct vm_area_struct *vma)
0107 {
0108     struct vb2_vmarea_handler *h = vma->vm_private_data;
0109 
0110     pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
0111            __func__, h, refcount_read(h->refcount), vma->vm_start,
0112            vma->vm_end);
0113 
0114     h->put(h->arg);
0115 }
0116 
0117 /*
0118  * vb2_common_vm_ops - common vm_ops used for tracking refcount of mmapped
0119  * video buffers
0120  */
0121 const struct vm_operations_struct vb2_common_vm_ops = {
0122     .open = vb2_common_vm_open,
0123     .close = vb2_common_vm_close,
0124 };
0125 EXPORT_SYMBOL_GPL(vb2_common_vm_ops);
0126 
0127 MODULE_DESCRIPTION("common memory handling routines for videobuf2");
0128 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
0129 MODULE_LICENSE("GPL");