summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-13 11:58:43 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-13 11:58:43 -0300
commit1578e14b943d0db4c03ad27e229a4df96207226e (patch)
tree4d93226211dea9c168c4164e865126866847f108
parentcd67e78204d5af9dd57eec434cd35517d3c1e2b3 (diff)
downloadmediapointer-dvb-s2-1578e14b943d0db4c03ad27e229a4df96207226e.tar.gz
mediapointer-dvb-s2-1578e14b943d0db4c03ad27e229a4df96207226e.tar.bz2
videobuf-vmalloc: fix STREAMOFF/STREAMON
From: Mauro Carvalho Chehab <mchehab@infradead.org> 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--linux/drivers/media/video/videobuf-vmalloc.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/linux/drivers/media/video/videobuf-vmalloc.c b/linux/drivers/media/video/videobuf-vmalloc.c
index 340337eda..b031c822f 100644
--- a/linux/drivers/media/video/videobuf-vmalloc.c
+++ b/linux/drivers/media/video/videobuf-vmalloc.c
@@ -58,19 +58,20 @@ videobuf_vm_open(struct vm_area_struct *vma)
map->count++;
}
-static void
-videobuf_vm_close(struct vm_area_struct *vma)
+static void videobuf_vm_close(struct vm_area_struct *vma)
{
struct videobuf_mapping *map = vma->vm_private_data;
struct videobuf_queue *q = map->q;
int i;
- dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map,
- map->count,vma->vm_start,vma->vm_end);
+ dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
+ map->count, vma->vm_start, vma->vm_end);
map->count--;
if (0 == map->count) {
- dprintk(1,"munmap %p q=%p\n",map,q);
+ struct videobuf_vmalloc_memory *mem;
+
+ dprintk(1, "munmap %p q=%p\n", map, q);
mutex_lock(&q->vb_lock);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
@@ -79,6 +80,18 @@ videobuf_vm_close(struct vm_area_struct *vma)
if (q->bufs[i]->map != map)
continue;
+ mem = q->bufs[i]->priv;
+ if (mem) {
+ /* This callback is called only if kernel has
+ allocated memory and this memory is mmapped.
+ In this case, memory should be freed,
+ in order to do memory unmap.
+ */
+ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+ vfree(mem->vmalloc);
+ mem->vmalloc = NULL;
+ }
+
q->bufs[i]->map = NULL;
q->bufs[i]->baddr = 0;
}
@@ -391,6 +404,15 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
{
struct videobuf_vmalloc_memory *mem = buf->priv;
+ /* mmapped memory can't be freed here, otherwise mmapped region
+ would be released, while still needed. In this case, the memory
+ release should happen inside videobuf_vm_close().
+ So, it should free memory only if the memory were allocated for
+ read() operation.
+ */
+ if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
+ return;
+
if (!mem)
return;
@@ -399,15 +421,6 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
vfree(mem->vmalloc);
mem->vmalloc = NULL;
-
-#if 0
- /* FIXME: This would be the proper place for freeing buf->map? */
- kfree(buf->map);
- buf->map = NULL;
-#endif
-
- /* FIXME: need to do buf->priv = NULL? */
-
return;
}
EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);