aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/videobuf2-memops.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-11 19:42:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-11 19:42:39 -0400
commit06a660ada2064bbdcd09aeb8173f2ad128c71978 (patch)
tree1d0172ca83bd0a8c2186fcb41ae750420d7acb14 /drivers/media/v4l2-core/videobuf2-memops.c
parentd9b44fe30fb8637b23f804eab2e7afbce129d714 (diff)
parent63540f01917c0d8b03b9813a0d6539469b163139 (diff)
Merge tag 'media/v4.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "A series of patches that move part of the code used to allocate memory from the media subsystem to the mm subsystem" [ The mm parts have been acked by VM people, and the series was apparently in -mm for a while - Linus ] * tag 'media/v4.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: [media] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames() [media] media: vb2: Remove unused functions [media] media: vb2: Convert vb2_dc_get_userptr() to use frame vector [media] media: vb2: Convert vb2_vmalloc_get_userptr() to use frame vector [media] media: vb2: Convert vb2_dma_sg_get_userptr() to use frame vector [media] vb2: Provide helpers for mapping virtual addresses [media] media: omap_vout: Convert omap_vout_uservirt_to_phys() to use get_vaddr_pfns() [media] mm: Provide new get_vaddr_frames() helper [media] vb2: Push mmap_sem down to memops
Diffstat (limited to 'drivers/media/v4l2-core/videobuf2-memops.c')
-rw-r--r--drivers/media/v4l2-core/videobuf2-memops.c148
1 files changed, 46 insertions, 102 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c
index 0d49b7951f84..48c6a49c4928 100644
--- a/drivers/media/v4l2-core/videobuf2-memops.c
+++ b/drivers/media/v4l2-core/videobuf2-memops.c
@@ -23,118 +23,62 @@
23#include <media/videobuf2-memops.h> 23#include <media/videobuf2-memops.h>
24 24
25/** 25/**
26 * vb2_get_vma() - acquire and lock the virtual memory area 26 * vb2_create_framevec() - map virtual addresses to pfns
27 * @vma: given virtual memory area 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
28 * 30 *
29 * This function attempts to acquire an area mapped in the userspace for 31 * This function allocates and fills in a vector with pfns corresponding to
30 * the duration of a hardware operation. The area is "locked" by performing 32 * virtual address range passed in arguments. If pfns have corresponding pages,
31 * the same set of operation that are done when process calls fork() and 33 * page references are also grabbed to pin pages in memory. The function
32 * memory areas are duplicated. 34 * returns pointer to the vector on success and error pointer in case of
33 * 35 * failure. Returned vector needs to be freed via vb2_destroy_pfnvec().
34 * Returns a copy of a virtual memory region on success or NULL.
35 */
36struct vm_area_struct *vb2_get_vma(struct vm_area_struct *vma)
37{
38 struct vm_area_struct *vma_copy;
39
40 vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL);
41 if (vma_copy == NULL)
42 return NULL;
43
44 if (vma->vm_ops && vma->vm_ops->open)
45 vma->vm_ops->open(vma);
46
47 if (vma->vm_file)
48 get_file(vma->vm_file);
49
50 memcpy(vma_copy, vma, sizeof(*vma));
51
52 vma_copy->vm_mm = NULL;
53 vma_copy->vm_next = NULL;
54 vma_copy->vm_prev = NULL;
55
56 return vma_copy;
57}
58EXPORT_SYMBOL_GPL(vb2_get_vma);
59
60/**
61 * vb2_put_userptr() - release a userspace virtual memory area
62 * @vma: virtual memory region associated with the area to be released
63 *
64 * This function releases the previously acquired memory area after a hardware
65 * operation.
66 */ 36 */
67void vb2_put_vma(struct vm_area_struct *vma) 37struct frame_vector *vb2_create_framevec(unsigned long start,
38 unsigned long length,
39 bool write)
68{ 40{
69 if (!vma) 41 int ret;
70 return; 42 unsigned long first, last;
71 43 unsigned long nr;
72 if (vma->vm_ops && vma->vm_ops->close) 44 struct frame_vector *vec;
73 vma->vm_ops->close(vma); 45
74 46 first = start >> PAGE_SHIFT;
75 if (vma->vm_file) 47 last = (start + length - 1) >> PAGE_SHIFT;
76 fput(vma->vm_file); 48 nr = last - first + 1;
77 49 vec = frame_vector_create(nr);
78 kfree(vma); 50 if (!vec)
51 return ERR_PTR(-ENOMEM);
52 ret = get_vaddr_frames(start, nr, write, 1, vec);
53 if (ret < 0)
54 goto out_destroy;
55 /* We accept only complete set of PFNs */
56 if (ret != nr) {
57 ret = -EFAULT;
58 goto out_release;
59 }
60 return vec;
61out_release:
62 put_vaddr_frames(vec);
63out_destroy:
64 frame_vector_destroy(vec);
65 return ERR_PTR(ret);
79} 66}
80EXPORT_SYMBOL_GPL(vb2_put_vma); 67EXPORT_SYMBOL(vb2_create_framevec);
81 68
82/** 69/**
83 * vb2_get_contig_userptr() - lock physically contiguous userspace mapped memory 70 * vb2_destroy_framevec() - release vector of mapped pfns
84 * @vaddr: starting virtual address of the area to be verified 71 * @vec: vector of pfns / pages to release
85 * @size: size of the area
86 * @res_paddr: will return physical address for the given vaddr
87 * @res_vma: will return locked copy of struct vm_area for the given area
88 *
89 * This function will go through memory area of size @size mapped at @vaddr and
90 * verify that the underlying physical pages are contiguous. If they are
91 * contiguous the virtual memory area is locked and a @res_vma is filled with
92 * the copy and @res_pa set to the physical address of the buffer.
93 * 72 *
94 * Returns 0 on success. 73 * This releases references to all pages in the vector @vec (if corresponding
74 * pfns are backed by pages) and frees the passed vector.
95 */ 75 */
96int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size, 76void vb2_destroy_framevec(struct frame_vector *vec)
97 struct vm_area_struct **res_vma, dma_addr_t *res_pa)
98{ 77{
99 struct mm_struct *mm = current->mm; 78 put_vaddr_frames(vec);
100 struct vm_area_struct *vma; 79 frame_vector_destroy(vec);
101 unsigned long offset, start, end;
102 unsigned long this_pfn, prev_pfn;
103 dma_addr_t pa = 0;
104
105 start = vaddr;
106 offset = start & ~PAGE_MASK;
107 end = start + size;
108
109 vma = find_vma(mm, start);
110
111 if (vma == NULL || vma->vm_end < end)
112 return -EFAULT;
113
114 for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
115 int ret = follow_pfn(vma, start, &this_pfn);
116 if (ret)
117 return ret;
118
119 if (prev_pfn == 0)
120 pa = this_pfn << PAGE_SHIFT;
121 else if (this_pfn != prev_pfn + 1)
122 return -EFAULT;
123
124 prev_pfn = this_pfn;
125 }
126
127 /*
128 * Memory is contiguous, lock vma and return to the caller
129 */
130 *res_vma = vb2_get_vma(vma);
131 if (*res_vma == NULL)
132 return -ENOMEM;
133
134 *res_pa = pa + offset;
135 return 0;
136} 80}
137EXPORT_SYMBOL_GPL(vb2_get_contig_userptr); 81EXPORT_SYMBOL(vb2_destroy_framevec);
138 82
139/** 83/**
140 * vb2_common_vm_open() - increase refcount of the vma 84 * vb2_common_vm_open() - increase refcount of the vma