aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/videobuf-vmalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/videobuf-vmalloc.c')
-rw-r--r--drivers/media/video/videobuf-vmalloc.c183
1 files changed, 42 insertions, 141 deletions
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
index 136e09383c06..583728f4c221 100644
--- a/drivers/media/video/videobuf-vmalloc.c
+++ b/drivers/media/video/videobuf-vmalloc.c
@@ -30,8 +30,12 @@
30#define MAGIC_DMABUF 0x17760309 30#define MAGIC_DMABUF 0x17760309
31#define MAGIC_VMAL_MEM 0x18221223 31#define MAGIC_VMAL_MEM 0x18221223
32 32
33#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ 33#define MAGIC_CHECK(is, should) \
34 { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } 34 if (unlikely((is) != (should))) { \
35 printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \
36 is, should); \
37 BUG(); \
38 }
35 39
36static int debug; 40static int debug;
37module_param(debug, int, 0644); 41module_param(debug, int, 0644);
@@ -40,19 +44,19 @@ MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
40MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 44MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
41MODULE_LICENSE("GPL"); 45MODULE_LICENSE("GPL");
42 46
43#define dprintk(level, fmt, arg...) if (debug >= level) \ 47#define dprintk(level, fmt, arg...) \
44 printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg) 48 if (debug >= level) \
49 printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
45 50
46 51
47/***************************************************************************/ 52/***************************************************************************/
48 53
49static void 54static void videobuf_vm_open(struct vm_area_struct *vma)
50videobuf_vm_open(struct vm_area_struct *vma)
51{ 55{
52 struct videobuf_mapping *map = vma->vm_private_data; 56 struct videobuf_mapping *map = vma->vm_private_data;
53 57
54 dprintk(2,"vm_open %p [count=%u,vma=%08lx-%08lx]\n",map, 58 dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
55 map->count,vma->vm_start,vma->vm_end); 59 map->count, vma->vm_start, vma->vm_end);
56 60
57 map->count++; 61 map->count++;
58} 62}
@@ -63,7 +67,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
63 struct videobuf_queue *q = map->q; 67 struct videobuf_queue *q = map->q;
64 int i; 68 int i;
65 69
66 dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, 70 dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
67 map->count, vma->vm_start, vma->vm_end); 71 map->count, vma->vm_start, vma->vm_end);
68 72
69 map->count--; 73 map->count--;
@@ -116,8 +120,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
116 return; 120 return;
117} 121}
118 122
119static const struct vm_operations_struct videobuf_vm_ops = 123static const struct vm_operations_struct videobuf_vm_ops = {
120{
121 .open = videobuf_vm_open, 124 .open = videobuf_vm_open,
122 .close = videobuf_vm_close, 125 .close = videobuf_vm_close,
123}; 126};
@@ -132,28 +135,28 @@ static const struct vm_operations_struct videobuf_vm_ops =
132 struct videobuf_dma_sg_memory 135 struct videobuf_dma_sg_memory
133 */ 136 */
134 137
135static void *__videobuf_alloc(size_t size) 138static struct videobuf_buffer *__videobuf_alloc(size_t size)
136{ 139{
137 struct videobuf_vmalloc_memory *mem; 140 struct videobuf_vmalloc_memory *mem;
138 struct videobuf_buffer *vb; 141 struct videobuf_buffer *vb;
139 142
140 vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); 143 vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
141 if (!vb) 144 if (!vb)
142 return vb; 145 return vb;
143 146
144 mem = vb->priv = ((char *)vb)+size; 147 mem = vb->priv = ((char *)vb) + size;
145 mem->magic=MAGIC_VMAL_MEM; 148 mem->magic = MAGIC_VMAL_MEM;
146 149
147 dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", 150 dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
148 __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), 151 __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb),
149 mem,(long)sizeof(*mem)); 152 mem, (long)sizeof(*mem));
150 153
151 return vb; 154 return vb;
152} 155}
153 156
154static int __videobuf_iolock (struct videobuf_queue* q, 157static int __videobuf_iolock(struct videobuf_queue *q,
155 struct videobuf_buffer *vb, 158 struct videobuf_buffer *vb,
156 struct v4l2_framebuffer *fbuf) 159 struct v4l2_framebuffer *fbuf)
157{ 160{
158 struct videobuf_vmalloc_memory *mem = vb->priv; 161 struct videobuf_vmalloc_memory *mem = vb->priv;
159 int pages; 162 int pages;
@@ -177,15 +180,13 @@ static int __videobuf_iolock (struct videobuf_queue* q,
177 180
178 dprintk(1, "%s memory method USERPTR\n", __func__); 181 dprintk(1, "%s memory method USERPTR\n", __func__);
179 182
180#if 1
181 if (vb->baddr) { 183 if (vb->baddr) {
182 printk(KERN_ERR "USERPTR is currently not supported\n"); 184 printk(KERN_ERR "USERPTR is currently not supported\n");
183 return -EINVAL; 185 return -EINVAL;
184 } 186 }
185#endif
186 187
187 /* The only USERPTR currently supported is the one needed for 188 /* The only USERPTR currently supported is the one needed for
188 read() method. 189 * read() method.
189 */ 190 */
190 191
191 mem->vmalloc = vmalloc_user(pages); 192 mem->vmalloc = vmalloc_user(pages);
@@ -210,7 +211,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
210 /* Try to remap memory */ 211 /* Try to remap memory */
211 rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); 212 rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
212 if (rc < 0) { 213 if (rc < 0) {
213 printk(KERN_ERR "mmap: remap failed with error %d. ", rc); 214 printk(KERN_ERR "mmap: remap failed with error %d", rc);
214 return -ENOMEM; 215 return -ENOMEM;
215 } 216 }
216#endif 217#endif
@@ -228,69 +229,29 @@ static int __videobuf_iolock (struct videobuf_queue* q,
228 return 0; 229 return 0;
229} 230}
230 231
231static int __videobuf_sync(struct videobuf_queue *q,
232 struct videobuf_buffer *buf)
233{
234 return 0;
235}
236
237static int __videobuf_mmap_free(struct videobuf_queue *q)
238{
239 unsigned int i;
240
241 dprintk(1, "%s\n", __func__);
242 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
243 if (q->bufs[i]) {
244 if (q->bufs[i]->map)
245 return -EBUSY;
246 }
247 }
248
249 return 0;
250}
251
252static int __videobuf_mmap_mapper(struct videobuf_queue *q, 232static int __videobuf_mmap_mapper(struct videobuf_queue *q,
253 struct vm_area_struct *vma) 233 struct videobuf_buffer *buf,
234 struct vm_area_struct *vma)
254{ 235{
255 struct videobuf_vmalloc_memory *mem; 236 struct videobuf_vmalloc_memory *mem;
256 struct videobuf_mapping *map; 237 struct videobuf_mapping *map;
257 unsigned int first;
258 int retval, pages; 238 int retval, pages;
259 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
260 239
261 dprintk(1, "%s\n", __func__); 240 dprintk(1, "%s\n", __func__);
262 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
263 return -EINVAL;
264
265 /* look for first buffer to map */
266 for (first = 0; first < VIDEO_MAX_FRAME; first++) {
267 if (NULL == q->bufs[first])
268 continue;
269
270 if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
271 continue;
272 if (q->bufs[first]->boff == offset)
273 break;
274 }
275 if (VIDEO_MAX_FRAME == first) {
276 dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
277 (vma->vm_pgoff << PAGE_SHIFT));
278 return -EINVAL;
279 }
280 241
281 /* create mapping + update buffer list */ 242 /* create mapping + update buffer list */
282 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); 243 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
283 if (NULL == map) 244 if (NULL == map)
284 return -ENOMEM; 245 return -ENOMEM;
285 246
286 q->bufs[first]->map = map; 247 buf->map = map;
287 map->start = vma->vm_start; 248 map->start = vma->vm_start;
288 map->end = vma->vm_end; 249 map->end = vma->vm_end;
289 map->q = q; 250 map->q = q;
290 251
291 q->bufs[first]->baddr = vma->vm_start; 252 buf->baddr = vma->vm_start;
292 253
293 mem = q->bufs[first]->priv; 254 mem = buf->priv;
294 BUG_ON(!mem); 255 BUG_ON(!mem);
295 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); 256 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
296 257
@@ -300,8 +261,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
300 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); 261 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
301 goto error; 262 goto error;
302 } 263 }
303 dprintk(1, "vmalloc is at addr %p (%d pages)\n", 264 dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vmalloc, pages);
304 mem->vmalloc, pages);
305 265
306 /* Try to remap memory */ 266 /* Try to remap memory */
307 retval = remap_vmalloc_range(vma, mem->vmalloc, 0); 267 retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
@@ -315,10 +275,10 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
315 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; 275 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
316 vma->vm_private_data = map; 276 vma->vm_private_data = map;
317 277
318 dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", 278 dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
319 map, q, vma->vm_start, vma->vm_end, 279 map, q, vma->vm_start, vma->vm_end,
320 (long int) q->bufs[first]->bsize, 280 (long int)buf->bsize,
321 vma->vm_pgoff, first); 281 vma->vm_pgoff, buf->i);
322 282
323 videobuf_vm_open(vma); 283 videobuf_vm_open(vma);
324 284
@@ -330,69 +290,16 @@ error:
330 return -ENOMEM; 290 return -ENOMEM;
331} 291}
332 292
333static int __videobuf_copy_to_user ( struct videobuf_queue *q,
334 char __user *data, size_t count,
335 int nonblocking )
336{
337 struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
338 BUG_ON (!mem);
339 MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
340
341 BUG_ON (!mem->vmalloc);
342
343 /* copy to userspace */
344 if (count > q->read_buf->size - q->read_off)
345 count = q->read_buf->size - q->read_off;
346
347 if (copy_to_user(data, mem->vmalloc+q->read_off, count))
348 return -EFAULT;
349
350 return count;
351}
352
353static int __videobuf_copy_stream ( struct videobuf_queue *q,
354 char __user *data, size_t count, size_t pos,
355 int vbihack, int nonblocking )
356{
357 unsigned int *fc;
358 struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
359 BUG_ON (!mem);
360 MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
361
362 if (vbihack) {
363 /* dirty, undocumented hack -- pass the frame counter
364 * within the last four bytes of each vbi data block.
365 * We need that one to maintain backward compatibility
366 * to all vbi decoding software out there ... */
367 fc = (unsigned int*)mem->vmalloc;
368 fc += (q->read_buf->size>>2) -1;
369 *fc = q->read_buf->field_count >> 1;
370 dprintk(1,"vbihack: %d\n",*fc);
371 }
372
373 /* copy stuff using the common method */
374 count = __videobuf_copy_to_user (q,data,count,nonblocking);
375
376 if ( (count==-EFAULT) && (0 == pos) )
377 return -EFAULT;
378
379 return count;
380}
381
382static struct videobuf_qtype_ops qops = { 293static struct videobuf_qtype_ops qops = {
383 .magic = MAGIC_QTYPE_OPS, 294 .magic = MAGIC_QTYPE_OPS,
384 295
385 .alloc = __videobuf_alloc, 296 .alloc = __videobuf_alloc,
386 .iolock = __videobuf_iolock, 297 .iolock = __videobuf_iolock,
387 .sync = __videobuf_sync,
388 .mmap_free = __videobuf_mmap_free,
389 .mmap_mapper = __videobuf_mmap_mapper, 298 .mmap_mapper = __videobuf_mmap_mapper,
390 .video_copy_to_user = __videobuf_copy_to_user, 299 .vaddr = videobuf_to_vmalloc,
391 .copy_stream = __videobuf_copy_stream,
392 .vmalloc = videobuf_to_vmalloc,
393}; 300};
394 301
395void videobuf_queue_vmalloc_init(struct videobuf_queue* q, 302void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
396 const struct videobuf_queue_ops *ops, 303 const struct videobuf_queue_ops *ops,
397 struct device *dev, 304 struct device *dev,
398 spinlock_t *irqlock, 305 spinlock_t *irqlock,
@@ -404,20 +311,19 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
404 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, 311 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
405 priv, &qops); 312 priv, &qops);
406} 313}
407
408EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); 314EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
409 315
410void *videobuf_to_vmalloc (struct videobuf_buffer *buf) 316void *videobuf_to_vmalloc(struct videobuf_buffer *buf)
411{ 317{
412 struct videobuf_vmalloc_memory *mem=buf->priv; 318 struct videobuf_vmalloc_memory *mem = buf->priv;
413 BUG_ON (!mem); 319 BUG_ON(!mem);
414 MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); 320 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
415 321
416 return mem->vmalloc; 322 return mem->vmalloc;
417} 323}
418EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); 324EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
419 325
420void videobuf_vmalloc_free (struct videobuf_buffer *buf) 326void videobuf_vmalloc_free(struct videobuf_buffer *buf)
421{ 327{
422 struct videobuf_vmalloc_memory *mem = buf->priv; 328 struct videobuf_vmalloc_memory *mem = buf->priv;
423 329
@@ -442,8 +348,3 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
442} 348}
443EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); 349EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
444 350
445/*
446 * Local variables:
447 * c-basic-offset: 8
448 * End:
449 */