aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-13 13:58:43 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:08:48 -0400
commitaaea56afc31345e7b0456ebb01586ba627ecd0f8 (patch)
tree4f25a8d2e134e9c22d003d8fc932228e0f07acda
parent968ced78a53509a996708a14e8b9269d1dc6a61c (diff)
V4L/DVB (7553): videobuf-vmalloc: fix STREAMOFF/STREAMON
There were a small bug on videobuf-vmalloc that were preventing STREAMOFF to work. The issue is that vmalloc'ed mmaped memory should only be freed after being sure that there aren't any mmap usage. Otherwise, the memory remap will stop working, and the userspace won't receive any frames. This bug were affecting some userspace applications, like tvtime. After this patch, tvtime started to work again with the drivers that use videobuf-vmalloc. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/videobuf-vmalloc.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
index 075acdf6b7c7..73627d380f07 100644
--- a/drivers/media/video/videobuf-vmalloc.c
+++ b/drivers/media/video/videobuf-vmalloc.c
@@ -57,19 +57,20 @@ videobuf_vm_open(struct vm_area_struct *vma)
57 map->count++; 57 map->count++;
58} 58}
59 59
60static void 60static void videobuf_vm_close(struct vm_area_struct *vma)
61videobuf_vm_close(struct vm_area_struct *vma)
62{ 61{
63 struct videobuf_mapping *map = vma->vm_private_data; 62 struct videobuf_mapping *map = vma->vm_private_data;
64 struct videobuf_queue *q = map->q; 63 struct videobuf_queue *q = map->q;
65 int i; 64 int i;
66 65
67 dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map, 66 dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
68 map->count,vma->vm_start,vma->vm_end); 67 map->count, vma->vm_start, vma->vm_end);
69 68
70 map->count--; 69 map->count--;
71 if (0 == map->count) { 70 if (0 == map->count) {
72 dprintk(1,"munmap %p q=%p\n",map,q); 71 struct videobuf_vmalloc_memory *mem;
72
73 dprintk(1, "munmap %p q=%p\n", map, q);
73 mutex_lock(&q->vb_lock); 74 mutex_lock(&q->vb_lock);
74 for (i = 0; i < VIDEO_MAX_FRAME; i++) { 75 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
75 if (NULL == q->bufs[i]) 76 if (NULL == q->bufs[i])
@@ -78,6 +79,18 @@ videobuf_vm_close(struct vm_area_struct *vma)
78 if (q->bufs[i]->map != map) 79 if (q->bufs[i]->map != map)
79 continue; 80 continue;
80 81
82 mem = q->bufs[i]->priv;
83 if (mem) {
84 /* This callback is called only if kernel has
85 allocated memory and this memory is mmapped.
86 In this case, memory should be freed,
87 in order to do memory unmap.
88 */
89 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
90 vfree(mem->vmalloc);
91 mem->vmalloc = NULL;
92 }
93
81 q->bufs[i]->map = NULL; 94 q->bufs[i]->map = NULL;
82 q->bufs[i]->baddr = 0; 95 q->bufs[i]->baddr = 0;
83 } 96 }
@@ -390,6 +403,15 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
390{ 403{
391 struct videobuf_vmalloc_memory *mem = buf->priv; 404 struct videobuf_vmalloc_memory *mem = buf->priv;
392 405
406 /* mmapped memory can't be freed here, otherwise mmapped region
407 would be released, while still needed. In this case, the memory
408 release should happen inside videobuf_vm_close().
409 So, it should free memory only if the memory were allocated for
410 read() operation.
411 */
412 if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
413 return;
414
393 if (!mem) 415 if (!mem)
394 return; 416 return;
395 417
@@ -398,10 +420,6 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
398 vfree(mem->vmalloc); 420 vfree(mem->vmalloc);
399 mem->vmalloc = NULL; 421 mem->vmalloc = NULL;
400 422
401
402
403 /* FIXME: need to do buf->priv = NULL? */
404
405 return; 423 return;
406} 424}
407EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); 425EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);