[RFC PATCH v2 4/8] media: videobuf2: introduce VIDEOBUF2_PAGE memops

From: Ming Lei
Date: Wed Dec 14 2011 - 09:01:43 EST


DMA contig memory resource is very limited and precious, also
accessing to it from CPU is very slow on some platform.

For some cases(such as the comming face detection driver), DMA Streaming
buffer is enough, so introduce VIDEOBUF2_PAGE to allocate continuous
physical memory but letting video device driver to handle DMA buffer mapping
and unmapping things.

Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxxxxx>
---
drivers/media/video/Kconfig | 4 +
drivers/media/video/Makefile | 1 +
drivers/media/video/videobuf2-page.c | 117 ++++++++++++++++++++++++++++++++++
include/media/videobuf2-page.h | 20 ++++++
4 files changed, 142 insertions(+), 0 deletions(-)
create mode 100644 drivers/media/video/videobuf2-page.c
create mode 100644 include/media/videobuf2-page.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 4e8a0c4..5684a00 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -60,6 +60,10 @@ config VIDEOBUF2_VMALLOC
select VIDEOBUF2_MEMOPS
tristate

+config VIDEOBUF2_PAGE
+ select VIDEOBUF2_CORE
+ select VIDEOBUF2_MEMOPS
+ tristate

config VIDEOBUF2_DMA_SG
#depends on HAS_DMA
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index ddeaa6c..bc797f2 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -125,6 +125,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_VIDEOBUF2_PAGE) += videobuf2-page.o
obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o

diff --git a/drivers/media/video/videobuf2-page.c b/drivers/media/video/videobuf2-page.c
new file mode 100644
index 0000000..6a24a34
--- /dev/null
+++ b/drivers/media/video/videobuf2-page.c
@@ -0,0 +1,117 @@
+/*
+ * videobuf2-page.c - page memory allocator for videobuf2
+ *
+ * Copyright (C) 2011 Canonical Ltd.
+ *
+ * Author: Ming Lei <ming.lei@xxxxxxxxxxxxx>
+ *
+ * This file is based on videobuf2-vmalloc.c
+ *
+ * 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 <media/videobuf2-core.h>
+#include <media/videobuf2-memops.h>
+
+struct vb2_page_buf {
+ void *vaddr;
+ unsigned long size;
+ atomic_t refcount;
+ struct vb2_vmarea_handler handler;
+};
+
+static void vb2_page_put(void *buf_priv);
+
+static void *vb2_page_alloc(void *alloc_ctx, unsigned long size)
+{
+ struct vb2_page_buf *buf;
+
+ buf = kzalloc(sizeof *buf, GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->size = size;
+ buf->vaddr = (void *)__get_free_pages(GFP_KERNEL,
+ get_order(buf->size));
+ buf->handler.refcount = &buf->refcount;
+ buf->handler.put = vb2_page_put;
+ buf->handler.arg = buf;
+
+ if (!buf->vaddr) {
+ printk(KERN_ERR "page of size %ld failed\n", buf->size);
+ kfree(buf);
+ return NULL;
+ }
+
+ atomic_inc(&buf->refcount);
+ printk(KERN_DEBUG "Allocated page buffer of size %ld at vaddr=%p\n",
+ buf->size, buf->vaddr);
+
+ return buf;
+}
+
+static void vb2_page_put(void *buf_priv)
+{
+ struct vb2_page_buf *buf = buf_priv;
+
+ if (atomic_dec_and_test(&buf->refcount)) {
+ printk(KERN_DEBUG "%s: Freeing page mem at vaddr=%p\n",
+ __func__, buf->vaddr);
+ free_pages((unsigned long)buf->vaddr, get_order(buf->size));
+ kfree(buf);
+ }
+}
+
+static void *vb2_page_vaddr(void *buf_priv)
+{
+ struct vb2_page_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_page_num_users(void *buf_priv)
+{
+ struct vb2_page_buf *buf = buf_priv;
+ return atomic_read(&buf->refcount);
+}
+
+static int vb2_page_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+ struct vb2_page_buf *buf = buf_priv;
+
+ if (!buf) {
+ printk(KERN_ERR "No memory to map\n");
+ return -EINVAL;
+ }
+
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ return vb2_mmap_pfn_range(vma, virt_to_phys(buf->vaddr),
+ buf->size, &vb2_common_vm_ops,
+ &buf->handler);
+}
+
+const struct vb2_mem_ops vb2_page_memops = {
+ .alloc = vb2_page_alloc,
+ .put = vb2_page_put,
+ .vaddr = vb2_page_vaddr,
+ .mmap = vb2_page_mmap,
+ .num_users = vb2_page_num_users,
+};
+EXPORT_SYMBOL_GPL(vb2_page_memops);
+
+MODULE_DESCRIPTION("page memory handling routines for videobuf2");
+MODULE_AUTHOR("Ming Lei");
+MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-page.h b/include/media/videobuf2-page.h
new file mode 100644
index 0000000..c837456
--- /dev/null
+++ b/include/media/videobuf2-page.h
@@ -0,0 +1,20 @@
+/*
+ * videobuf2-page.h - page memory allocator for videobuf2
+ *
+ * Copyright (C) 2011 Canonical Ltd.
+ *
+ * Author: Ming Lei <ming.lei@xxxxxxxxxxxxx>
+ *
+ * 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.
+ */
+
+#ifndef _MEDIA_VIDEOBUF2_PAGE_H
+#define _MEDIA_VIDEOBUF2_PAGE_H
+
+#include <media/videobuf2-core.h>
+
+extern const struct vb2_mem_ops vb2_page_memops;
+
+#endif
--
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/