[PATCH 3/8] v4l: videobuf2: add vmalloc allocator

2010-12-16 Thread Marek Szyprowski
From: Pawel Osciak p.osc...@samsung.com

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.osc...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
CC: Pawel Osciak pa...@osciak.com
---
 drivers/media/video/Kconfig |5 +
 drivers/media/video/Makefile|1 +
 drivers/media/video/videobuf2-vmalloc.c |  132 +++
 include/media/videobuf2-vmalloc.h   |   20 +
 4 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/videobuf2-vmalloc.c
 create mode 100644 include/media/videobuf2-vmalloc.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 3c239fa..2606f49 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -55,6 +55,11 @@ config VIDEOBUF2_CORE
 config VIDEOBUF2_MEMOPS
tristate
 
+config VIDEOBUF2_VMALLOC
+   select VIDEOBUF2_CORE
+   select VIDEOBUF2_MEMOPS
+   tristate
+
 #
 # Multimedia Video device configuration
 #
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index a97a2a0..538bee9 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 
 obj-$(CONFIG_VIDEOBUF2_CORE)   += videobuf2-core.o
 obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
+obj-$(CONFIG_VIDEOBUF2_VMALLOC)+= videobuf2-vmalloc.o
 
 obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
 
diff --git a/drivers/media/video/videobuf2-vmalloc.c 
b/drivers/media/video/videobuf2-vmalloc.c
new file mode 100644
index 000..b5e6936
--- /dev/null
+++ b/drivers/media/video/videobuf2-vmalloc.c
@@ -0,0 +1,132 @@
+/*
+ * videobuf2-vmalloc.c - vmalloc memory allocator for videobuf2
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak p.osc...@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include linux/module.h
+#include linux/mm.h
+#include linux/slab.h
+#include linux/vmalloc.h
+
+#include media/videobuf2-core.h
+#include media/videobuf2-memops.h
+
+struct vb2_vmalloc_buf {
+   void*vaddr;
+   unsigned long   size;
+   atomic_trefcount;
+   struct vb2_vmarea_handler   handler;
+};
+
+static void vb2_vmalloc_put(void *buf_priv);
+
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
+{
+   struct vb2_vmalloc_buf *buf;
+
+   buf = kzalloc(sizeof *buf, GFP_KERNEL);
+   if (!buf)
+   return NULL;
+
+   buf-size = size;
+   buf-vaddr = vmalloc_user(buf-size);
+   buf-handler.refcount = buf-refcount;
+   buf-handler.put = vb2_vmalloc_put;
+   buf-handler.arg = buf;
+
+   if (!buf-vaddr) {
+   printk(KERN_ERR vmalloc of size %ld failed\n, buf-size);
+   kfree(buf);
+   return NULL;
+   }
+
+   atomic_inc(buf-refcount);
+   printk(KERN_DEBUG Allocated vmalloc buffer of size %ld at vaddr=%p\n,
+   buf-size, buf-vaddr);
+
+   return buf;
+}
+
+static void vb2_vmalloc_put(void *buf_priv)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+
+   if (atomic_dec_and_test(buf-refcount)) {
+   printk(KERN_DEBUG %s: Freeing vmalloc mem at vaddr=%p\n,
+   __func__, buf-vaddr);
+   vfree(buf-vaddr);
+   kfree(buf);
+   }
+}
+
+static void *vb2_vmalloc_vaddr(void *buf_priv)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+
+   BUG_ON(!buf);
+
+   if (!buf-vaddr) {
+   printk(KERN_ERR Address of an unallocated plane requested\n);
+   return NULL;
+   }
+
+   return buf-vaddr;
+}
+
+static unsigned int vb2_vmalloc_num_users(void *buf_priv)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+   return atomic_read(buf-refcount);
+}
+
+static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+   int ret;
+
+   if (!buf) {
+   printk(KERN_ERR No memory to map\n);
+   return -EINVAL;
+   }
+
+   ret = remap_vmalloc_range(vma, buf-vaddr, 0);
+   if (ret) {
+   printk(KERN_ERR Remapping vmalloc memory, error: %d\n, ret);
+   return ret;
+   }
+
+   /*
+* Make sure that vm_areas for 2 buffers won't be merged together
+*/
+   vma-vm_flags   |= VM_DONTEXPAND;
+
+   /*
+* Use common vm_area operations to track buffer refcount.
+*/
+   vma-vm_private_data= buf-handler;
+   vma-vm_ops  

[PATCH 3/8] v4l: videobuf2: add vmalloc allocator

2010-12-06 Thread Marek Szyprowski
From: Pawel Osciak p.osc...@samsung.com

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.osc...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
CC: Pawel Osciak pa...@osciak.com
---
 drivers/media/video/Kconfig |5 +
 drivers/media/video/Makefile|1 +
 drivers/media/video/videobuf2-vmalloc.c |  132 +++
 include/media/videobuf2-vmalloc.h   |   20 +
 4 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/videobuf2-vmalloc.c
 create mode 100644 include/media/videobuf2-vmalloc.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 83ce858..9351423 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -55,6 +55,11 @@ config VIDEOBUF2_CORE
 config VIDEOBUF2_MEMOPS
tristate
 
+config VIDEOBUF2_VMALLOC
+   select VIDEOBUF2_CORE
+   select VIDEOBUF2_MEMOPS
+   tristate
+
 #
 # Multimedia Video device configuration
 #
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index a97a2a0..538bee9 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 
 obj-$(CONFIG_VIDEOBUF2_CORE)   += videobuf2-core.o
 obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
+obj-$(CONFIG_VIDEOBUF2_VMALLOC)+= videobuf2-vmalloc.o
 
 obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
 
diff --git a/drivers/media/video/videobuf2-vmalloc.c 
b/drivers/media/video/videobuf2-vmalloc.c
new file mode 100644
index 000..b5e6936
--- /dev/null
+++ b/drivers/media/video/videobuf2-vmalloc.c
@@ -0,0 +1,132 @@
+/*
+ * videobuf2-vmalloc.c - vmalloc memory allocator for videobuf2
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak p.osc...@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include linux/module.h
+#include linux/mm.h
+#include linux/slab.h
+#include linux/vmalloc.h
+
+#include media/videobuf2-core.h
+#include media/videobuf2-memops.h
+
+struct vb2_vmalloc_buf {
+   void*vaddr;
+   unsigned long   size;
+   atomic_trefcount;
+   struct vb2_vmarea_handler   handler;
+};
+
+static void vb2_vmalloc_put(void *buf_priv);
+
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
+{
+   struct vb2_vmalloc_buf *buf;
+
+   buf = kzalloc(sizeof *buf, GFP_KERNEL);
+   if (!buf)
+   return NULL;
+
+   buf-size = size;
+   buf-vaddr = vmalloc_user(buf-size);
+   buf-handler.refcount = buf-refcount;
+   buf-handler.put = vb2_vmalloc_put;
+   buf-handler.arg = buf;
+
+   if (!buf-vaddr) {
+   printk(KERN_ERR vmalloc of size %ld failed\n, buf-size);
+   kfree(buf);
+   return NULL;
+   }
+
+   atomic_inc(buf-refcount);
+   printk(KERN_DEBUG Allocated vmalloc buffer of size %ld at vaddr=%p\n,
+   buf-size, buf-vaddr);
+
+   return buf;
+}
+
+static void vb2_vmalloc_put(void *buf_priv)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+
+   if (atomic_dec_and_test(buf-refcount)) {
+   printk(KERN_DEBUG %s: Freeing vmalloc mem at vaddr=%p\n,
+   __func__, buf-vaddr);
+   vfree(buf-vaddr);
+   kfree(buf);
+   }
+}
+
+static void *vb2_vmalloc_vaddr(void *buf_priv)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+
+   BUG_ON(!buf);
+
+   if (!buf-vaddr) {
+   printk(KERN_ERR Address of an unallocated plane requested\n);
+   return NULL;
+   }
+
+   return buf-vaddr;
+}
+
+static unsigned int vb2_vmalloc_num_users(void *buf_priv)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+   return atomic_read(buf-refcount);
+}
+
+static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+   struct vb2_vmalloc_buf *buf = buf_priv;
+   int ret;
+
+   if (!buf) {
+   printk(KERN_ERR No memory to map\n);
+   return -EINVAL;
+   }
+
+   ret = remap_vmalloc_range(vma, buf-vaddr, 0);
+   if (ret) {
+   printk(KERN_ERR Remapping vmalloc memory, error: %d\n, ret);
+   return ret;
+   }
+
+   /*
+* Make sure that vm_areas for 2 buffers won't be merged together
+*/
+   vma-vm_flags   |= VM_DONTEXPAND;
+
+   /*
+* Use common vm_area operations to track buffer refcount.
+*/
+   vma-vm_private_data= buf-handler;
+   vma-vm_ops