diff options
Diffstat (limited to 'drivers/media/v4l2-core/videobuf2-memops.c')
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-memops.c | 148 |
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 | */ | ||
36 | struct 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 | } | ||
58 | EXPORT_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 | */ |
67 | void vb2_put_vma(struct vm_area_struct *vma) | 37 | struct 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; | ||
61 | out_release: | ||
62 | put_vaddr_frames(vec); | ||
63 | out_destroy: | ||
64 | frame_vector_destroy(vec); | ||
65 | return ERR_PTR(ret); | ||
79 | } | 66 | } |
80 | EXPORT_SYMBOL_GPL(vb2_put_vma); | 67 | EXPORT_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 | */ |
96 | int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size, | 76 | void 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 | } |
137 | EXPORT_SYMBOL_GPL(vb2_get_contig_userptr); | 81 | EXPORT_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 |