This source file includes following definitions.
- videobuf_vm_open
- videobuf_vm_close
- __videobuf_alloc_vb
- __videobuf_iolock
- __videobuf_mmap_mapper
- videobuf_queue_vmalloc_init
- videobuf_to_vmalloc
- videobuf_vmalloc_free
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/slab.h>
17 #include <linux/interrupt.h>
18
19 #include <linux/pci.h>
20 #include <linux/vmalloc.h>
21 #include <linux/pagemap.h>
22 #include <asm/page.h>
23 #include <asm/pgtable.h>
24
25 #include <media/videobuf-vmalloc.h>
26
27 #define MAGIC_DMABUF 0x17760309
28 #define MAGIC_VMAL_MEM 0x18221223
29
30 #define MAGIC_CHECK(is, should) \
31 if (unlikely((is) != (should))) { \
32 printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \
33 is, should); \
34 BUG(); \
35 }
36
37 static int debug;
38 module_param(debug, int, 0644);
39
40 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
41 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");
42 MODULE_LICENSE("GPL");
43
44 #define dprintk(level, fmt, arg...) \
45 if (debug >= level) \
46 printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
47
48
49
50
51 static void videobuf_vm_open(struct vm_area_struct *vma)
52 {
53 struct videobuf_mapping *map = vma->vm_private_data;
54
55 dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
56 map->count, vma->vm_start, vma->vm_end);
57
58 map->count++;
59 }
60
61 static void videobuf_vm_close(struct vm_area_struct *vma)
62 {
63 struct videobuf_mapping *map = vma->vm_private_data;
64 struct videobuf_queue *q = map->q;
65 int i;
66
67 dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
68 map->count, vma->vm_start, vma->vm_end);
69
70 map->count--;
71 if (0 == map->count) {
72 struct videobuf_vmalloc_memory *mem;
73
74 dprintk(1, "munmap %p q=%p\n", map, q);
75 videobuf_queue_lock(q);
76
77
78 if (q->streaming)
79 videobuf_queue_cancel(q);
80
81 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
82 if (NULL == q->bufs[i])
83 continue;
84
85 if (q->bufs[i]->map != map)
86 continue;
87
88 mem = q->bufs[i]->priv;
89 if (mem) {
90
91
92
93
94
95
96 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
97
98
99
100
101 dprintk(1, "%s: buf[%d] freeing (%p)\n",
102 __func__, i, mem->vaddr);
103
104 vfree(mem->vaddr);
105 mem->vaddr = NULL;
106 }
107
108 q->bufs[i]->map = NULL;
109 q->bufs[i]->baddr = 0;
110 }
111
112 kfree(map);
113
114 videobuf_queue_unlock(q);
115 }
116
117 return;
118 }
119
120 static const struct vm_operations_struct videobuf_vm_ops = {
121 .open = videobuf_vm_open,
122 .close = videobuf_vm_close,
123 };
124
125
126
127
128
129
130
131
132
133
134
135 static struct videobuf_buffer *__videobuf_alloc_vb(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 if (!vb)
142 return vb;
143
144 mem = vb->priv = ((char *)vb) + size;
145 mem->magic = MAGIC_VMAL_MEM;
146
147 dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
148 __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb),
149 mem, (long)sizeof(*mem));
150
151 return vb;
152 }
153
154 static int __videobuf_iolock(struct videobuf_queue *q,
155 struct videobuf_buffer *vb,
156 struct v4l2_framebuffer *fbuf)
157 {
158 struct videobuf_vmalloc_memory *mem = vb->priv;
159 int pages;
160
161 BUG_ON(!mem);
162
163 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
164
165 switch (vb->memory) {
166 case V4L2_MEMORY_MMAP:
167 dprintk(1, "%s memory method MMAP\n", __func__);
168
169
170 if (!mem->vaddr) {
171 printk(KERN_ERR "memory is not allocated/mmapped.\n");
172 return -EINVAL;
173 }
174 break;
175 case V4L2_MEMORY_USERPTR:
176 pages = PAGE_ALIGN(vb->size);
177
178 dprintk(1, "%s memory method USERPTR\n", __func__);
179
180 if (vb->baddr) {
181 printk(KERN_ERR "USERPTR is currently not supported\n");
182 return -EINVAL;
183 }
184
185
186
187
188
189 mem->vaddr = vmalloc_user(pages);
190 if (!mem->vaddr) {
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->vaddr, pages);
196 break;
197 case V4L2_MEMORY_OVERLAY:
198 default:
199 dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
200
201
202 printk(KERN_ERR "Memory method currently unsupported.\n");
203 return -EINVAL;
204 }
205
206 return 0;
207 }
208
209 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
210 struct videobuf_buffer *buf,
211 struct vm_area_struct *vma)
212 {
213 struct videobuf_vmalloc_memory *mem;
214 struct videobuf_mapping *map;
215 int retval, pages;
216
217 dprintk(1, "%s\n", __func__);
218
219
220 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
221 if (NULL == map)
222 return -ENOMEM;
223
224 buf->map = map;
225 map->q = q;
226
227 buf->baddr = vma->vm_start;
228
229 mem = buf->priv;
230 BUG_ON(!mem);
231 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
232
233 pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
234 mem->vaddr = vmalloc_user(pages);
235 if (!mem->vaddr) {
236 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
237 goto error;
238 }
239 dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages);
240
241
242 retval = remap_vmalloc_range(vma, mem->vaddr, 0);
243 if (retval < 0) {
244 printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
245 vfree(mem->vaddr);
246 goto error;
247 }
248
249 vma->vm_ops = &videobuf_vm_ops;
250 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
251 vma->vm_private_data = map;
252
253 dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
254 map, q, vma->vm_start, vma->vm_end,
255 (long int)buf->bsize,
256 vma->vm_pgoff, buf->i);
257
258 videobuf_vm_open(vma);
259
260 return 0;
261
262 error:
263 mem = NULL;
264 kfree(map);
265 return -ENOMEM;
266 }
267
268 static struct videobuf_qtype_ops qops = {
269 .magic = MAGIC_QTYPE_OPS,
270
271 .alloc_vb = __videobuf_alloc_vb,
272 .iolock = __videobuf_iolock,
273 .mmap_mapper = __videobuf_mmap_mapper,
274 .vaddr = videobuf_to_vmalloc,
275 };
276
277 void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
278 const struct videobuf_queue_ops *ops,
279 struct device *dev,
280 spinlock_t *irqlock,
281 enum v4l2_buf_type type,
282 enum v4l2_field field,
283 unsigned int msize,
284 void *priv,
285 struct mutex *ext_lock)
286 {
287 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
288 priv, &qops, ext_lock);
289 }
290 EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
291
292 void *videobuf_to_vmalloc(struct videobuf_buffer *buf)
293 {
294 struct videobuf_vmalloc_memory *mem = buf->priv;
295 BUG_ON(!mem);
296 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
297
298 return mem->vaddr;
299 }
300 EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
301
302 void videobuf_vmalloc_free(struct videobuf_buffer *buf)
303 {
304 struct videobuf_vmalloc_memory *mem = buf->priv;
305
306
307
308
309
310
311
312 if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
313 return;
314
315 if (!mem)
316 return;
317
318 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
319
320 vfree(mem->vaddr);
321 mem->vaddr = NULL;
322
323 return;
324 }
325 EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
326