aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorPawel Osciak <p.osciak@samsung.com>2010-10-11 09:58:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:34 -0400
commit3c18ff06d811f743d380e6436fac0143ffcf1266 (patch)
tree7412bd6d9d393535aadbadd9b28593b27f9485a6 /drivers/media
parent004cc3781c40a577b0349eef825efaaebc42dd43 (diff)
[media] v4l: videobuf2: add vmalloc allocator
Add an implementation of contiguous virtual memory allocator and handling routines for videobuf2, implemented on top of vmalloc()/vfree() calls. Signed-off-by: Pawel Osciak <p.osciak@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> CC: Pawel Osciak <pawel@osciak.com> Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/Kconfig5
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/videobuf2-vmalloc.c132
3 files changed, 138 insertions, 0 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index aae5005cf86..b8c21a729b8 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -50,6 +50,11 @@ config VIDEOBUF2_CORE
50config VIDEOBUF2_MEMOPS 50config VIDEOBUF2_MEMOPS
51 tristate 51 tristate
52 52
53config VIDEOBUF2_VMALLOC
54 select VIDEOBUF2_CORE
55 select VIDEOBUF2_MEMOPS
56 tristate
57
53# 58#
54# Multimedia Video device configuration 59# Multimedia Video device configuration
55# 60#
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index fca0444b66b..e31c88e9ca7 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
113 113
114obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o 114obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o
115obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o 115obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
116obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
116 117
117obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o 118obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
118 119
diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/video/videobuf2-vmalloc.c
new file mode 100644
index 00000000000..b5e6936fb62
--- /dev/null
+++ b/drivers/media/video/videobuf2-vmalloc.c
@@ -0,0 +1,132 @@
1/*
2 * videobuf2-vmalloc.c - vmalloc memory allocator for videobuf2
3 *
4 * Copyright (C) 2010 Samsung Electronics
5 *
6 * Author: Pawel Osciak <p.osciak@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/mm.h>
15#include <linux/slab.h>
16#include <linux/vmalloc.h>
17
18#include <media/videobuf2-core.h>
19#include <media/videobuf2-memops.h>
20
21struct vb2_vmalloc_buf {
22 void *vaddr;
23 unsigned long size;
24 atomic_t refcount;
25 struct vb2_vmarea_handler handler;
26};
27
28static void vb2_vmalloc_put(void *buf_priv);
29
30static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
31{
32 struct vb2_vmalloc_buf *buf;
33
34 buf = kzalloc(sizeof *buf, GFP_KERNEL);
35 if (!buf)
36 return NULL;
37
38 buf->size = size;
39 buf->vaddr = vmalloc_user(buf->size);
40 buf->handler.refcount = &buf->refcount;
41 buf->handler.put = vb2_vmalloc_put;
42 buf->handler.arg = buf;
43
44 if (!buf->vaddr) {
45 printk(KERN_ERR "vmalloc of size %ld failed\n", buf->size);
46 kfree(buf);
47 return NULL;
48 }
49
50 atomic_inc(&buf->refcount);
51 printk(KERN_DEBUG "Allocated vmalloc buffer of size %ld at vaddr=%p\n",
52 buf->size, buf->vaddr);
53
54 return buf;
55}
56
57static void vb2_vmalloc_put(void *buf_priv)
58{
59 struct vb2_vmalloc_buf *buf = buf_priv;
60
61 if (atomic_dec_and_test(&buf->refcount)) {
62 printk(KERN_DEBUG "%s: Freeing vmalloc mem at vaddr=%p\n",
63 __func__, buf->vaddr);
64 vfree(buf->vaddr);
65 kfree(buf);
66 }
67}
68
69static void *vb2_vmalloc_vaddr(void *buf_priv)
70{
71 struct vb2_vmalloc_buf *buf = buf_priv;
72
73 BUG_ON(!buf);
74
75 if (!buf->vaddr) {
76 printk(KERN_ERR "Address of an unallocated plane requested\n");
77 return NULL;
78 }
79
80 return buf->vaddr;
81}
82
83static unsigned int vb2_vmalloc_num_users(void *buf_priv)
84{
85 struct vb2_vmalloc_buf *buf = buf_priv;
86 return atomic_read(&buf->refcount);
87}
88
89static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
90{
91 struct vb2_vmalloc_buf *buf = buf_priv;
92 int ret;
93
94 if (!buf) {
95 printk(KERN_ERR "No memory to map\n");
96 return -EINVAL;
97 }
98
99 ret = remap_vmalloc_range(vma, buf->vaddr, 0);
100 if (ret) {
101 printk(KERN_ERR "Remapping vmalloc memory, error: %d\n", ret);
102 return ret;
103 }
104
105 /*
106 * Make sure that vm_areas for 2 buffers won't be merged together
107 */
108 vma->vm_flags |= VM_DONTEXPAND;
109
110 /*
111 * Use common vm_area operations to track buffer refcount.
112 */
113 vma->vm_private_data = &buf->handler;
114 vma->vm_ops = &vb2_common_vm_ops;
115
116 vma->vm_ops->open(vma);
117
118 return 0;
119}
120
121const struct vb2_mem_ops vb2_vmalloc_memops = {
122 .alloc = vb2_vmalloc_alloc,
123 .put = vb2_vmalloc_put,
124 .vaddr = vb2_vmalloc_vaddr,
125 .mmap = vb2_vmalloc_mmap,
126 .num_users = vb2_vmalloc_num_users,
127};
128EXPORT_SYMBOL_GPL(vb2_vmalloc_memops);
129
130MODULE_DESCRIPTION("vmalloc memory handling routines for videobuf2");
131MODULE_AUTHOR("Pawel Osciak");
132MODULE_LICENSE("GPL");