Skip to content

Commit

Permalink
V4L/DVB (7553): videobuf-vmalloc: fix STREAMOFF/STREAMON
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mauro Carvalho Chehab committed Apr 24, 2008
1 parent 968ced7 commit aaea56a
Showing 1 changed file with 27 additions and 9 deletions.
36 changes: 27 additions & 9 deletions drivers/media/video/videobuf-vmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,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])
Expand All @@ -78,6 +79,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;
}
Expand Down Expand Up @@ -390,6 +403,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;

Expand All @@ -398,10 +420,6 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
vfree(mem->vmalloc);
mem->vmalloc = NULL;



/* FIXME: need to do buf->priv = NULL? */

return;
}
EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
Expand Down

0 comments on commit aaea56a

Please sign in to comment.