diff options
Diffstat (limited to 'drivers/media/video/videobuf-vmalloc.c')
-rw-r--r-- | drivers/media/video/videobuf-vmalloc.c | 36 |
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 | ||
60 | static void | 60 | static void videobuf_vm_close(struct vm_area_struct *vma) |
61 | videobuf_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 | } |
407 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); | 425 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); |