[PATCH 3/8] v4l: videobuf2: add vmalloc allocator
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
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