linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
To: linaro-kernel@lists.linaro.org, arnd@arndb.de,
	labbott@redhat.com, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
	daniel.vetter@ffwll.ch, laurent.pinchart@ideasonboard.com,
	robdclark@gmail.com, akpm@linux-foundation.org,
	hverkuil@xs4all.nl
Cc: broonie@kernel.org, Benjamin Gaignard <benjamin.gaignard@linaro.org>
Subject: [RFC simple allocator v2 2/2] add CMA simple allocator module
Date: Mon, 13 Feb 2017 15:45:06 +0100	[thread overview]
Message-ID: <1486997106-23277-3-git-send-email-benjamin.gaignard@linaro.org> (raw)
In-Reply-To: <1486997106-23277-1-git-send-email-benjamin.gaignard@linaro.org>

This patch add simple allocator for CMA regions.

version 2:
- fix size and page count computation

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
 drivers/simpleallocator/Kconfig                |   7 +
 drivers/simpleallocator/Makefile               |   1 +
 drivers/simpleallocator/simple-allocator-cma.c | 187 +++++++++++++++++++++++++
 3 files changed, 195 insertions(+)
 create mode 100644 drivers/simpleallocator/simple-allocator-cma.c

diff --git a/drivers/simpleallocator/Kconfig b/drivers/simpleallocator/Kconfig
index c6fc2e3..788fb0b 100644
--- a/drivers/simpleallocator/Kconfig
+++ b/drivers/simpleallocator/Kconfig
@@ -7,4 +7,11 @@ config SIMPLE_ALLOCATOR
 	   The Simple Allocator Framework adds an API to allocate and share
 	   memory in userland.
 
+config SIMPLE_ALLOCATOR_CMA
+	tristate "Simple Allocator CMA"
+	select SIMPLE_ALLOCATOR
+	depends on DMA_CMA
+	---help---
+	   Select this option to enable Simple Allocator on CMA area.
+
 endmenu
diff --git a/drivers/simpleallocator/Makefile b/drivers/simpleallocator/Makefile
index e27c6ad..4e11611 100644
--- a/drivers/simpleallocator/Makefile
+++ b/drivers/simpleallocator/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_SIMPLE_ALLOCATOR) += simple-allocator.o
+obj-$(CONFIG_SIMPLE_ALLOCATOR_CMA) += simple-allocator-cma.o
diff --git a/drivers/simpleallocator/simple-allocator-cma.c b/drivers/simpleallocator/simple-allocator-cma.c
new file mode 100644
index 0000000..07cbf5b
--- /dev/null
+++ b/drivers/simpleallocator/simple-allocator-cma.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) Linaro 2017
+ *
+ * Author: Benjamin Gaignard <benjamin.gaignard@linaro.org>
+ *
+ * License terms:  GNU General Public License (GPL)
+ */
+
+#include <linux/cma.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "simple-allocator-priv.h"
+#include "../mm/cma.h"
+
+struct sa_cma_device {
+	struct sa_device parent;
+	struct cma *cma;
+};
+
+struct sa_cma_buffer_info {
+	void *vaddr;
+	size_t count;
+	size_t size;
+	struct page *pages;
+	struct sa_cma_device *sa_cma;
+};
+
+static struct sa_cma_device *sa_cma[MAX_CMA_AREAS];
+
+static inline struct sa_cma_device *to_sa_cma(struct sa_device *sadev)
+{
+	return container_of(sadev, struct sa_cma_device, parent);
+}
+
+static struct sg_table *sa_cma_map_dma_buf(struct dma_buf_attachment *attach,
+					   enum dma_data_direction direction)
+{
+	struct dma_buf *dmabuf = attach->dmabuf;
+	struct sa_cma_buffer_info *info = dmabuf->priv;
+	struct sg_table *sgt;
+	int ret;
+
+	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
+	if (unlikely(ret))
+		return NULL;
+
+	sg_set_page(sgt->sgl, info->pages, info->size, 0);
+	sg_dma_address(sgt->sgl) = (dma_addr_t) page_address(info->pages);
+	sg_dma_len(sgt->sgl) = info->size;
+
+	return sgt;
+}
+
+static void sa_cma_unmap_dma_buf(struct dma_buf_attachment *attach,
+				 struct sg_table *sgt,
+				 enum dma_data_direction dir)
+{
+	kfree(sgt);
+}
+
+static int sa_cma_mmap_dma_buf(struct dma_buf *dmabuf,
+			       struct vm_area_struct *vma)
+{
+	struct sa_cma_buffer_info *info = dmabuf->priv;
+	unsigned long user_count = vma_pages(vma);
+	unsigned long count = info->count;
+	unsigned long pfn = page_to_pfn(info->pages);
+	unsigned long off = vma->vm_pgoff;
+	int ret = -ENXIO;
+
+	if (off < count && user_count <= (count - off)) {
+		ret = remap_pfn_range(vma, vma->vm_start,
+				      pfn + off,
+				      user_count << PAGE_SHIFT,
+				      vma->vm_page_prot);
+	}
+
+	return ret;
+}
+
+static void sa_cma_release_dma_buf(struct dma_buf *dmabuf)
+{
+	struct sa_cma_buffer_info *info = dmabuf->priv;
+
+	cma_release(info->sa_cma->cma, info->pages, info->count);
+
+	kfree(info);
+}
+
+static void *sa_cma_kmap_dma_buf(struct dma_buf *dmabuf, unsigned long offset)
+{
+	struct sa_cma_buffer_info *info = dmabuf->priv;
+
+	return page_address(info->pages) + offset;
+}
+
+static struct dma_buf_ops sa_dma_buf_ops = {
+	.map_dma_buf = sa_cma_map_dma_buf,
+	.unmap_dma_buf = sa_cma_unmap_dma_buf,
+	.mmap = sa_cma_mmap_dma_buf,
+	.release = sa_cma_release_dma_buf,
+	.kmap_atomic = sa_cma_kmap_dma_buf,
+	.kmap = sa_cma_kmap_dma_buf,
+};
+
+static struct dma_buf *sa_cma_allocate(struct sa_device *sadev,
+				       u64 length, u32 flags)
+{
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	struct sa_cma_buffer_info *info;
+	struct dma_buf *dmabuf;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return NULL;
+
+	info->size = round_up(length, PAGE_SIZE);
+	info->count = PAGE_ALIGN(info->size) >> PAGE_SHIFT;
+	info->sa_cma = to_sa_cma(sadev);
+
+	info->pages = cma_alloc(info->sa_cma->cma, info->count, 0);
+
+	if (!info->pages)
+		goto cleanup;
+
+	exp_info.ops = &sa_dma_buf_ops;
+	exp_info.size = info->size;
+	exp_info.flags = flags;
+	exp_info.priv = info;
+
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf))
+		goto export_failed;
+
+	return dmabuf;
+
+export_failed:
+	cma_release(info->sa_cma->cma, info->pages, info->count);
+cleanup:
+	kfree(info);
+	return NULL;
+}
+
+struct sa_cma_device *simple_allocator_register_cma(struct cma *cma)
+{
+	struct sa_cma_device *sa_cma;
+	int ret;
+
+	sa_cma = kzalloc(sizeof(*sa_cma), GFP_KERNEL);
+	if (!sa_cma)
+		return NULL;
+
+	sa_cma->cma = cma;
+	sa_cma->parent.owner = THIS_MODULE;
+	sa_cma->parent.name = "cma";
+	sa_cma->parent.allocate = sa_cma_allocate;
+
+	ret = simple_allocator_register(&sa_cma->parent);
+	if (ret) {
+		kfree(sa_cma);
+		return NULL;
+	}
+
+	return sa_cma;
+}
+
+static int __init sa_cma_init(void)
+{
+	int i;
+
+	for (i = 0; i < cma_area_count; i++)
+		sa_cma[i] = simple_allocator_register_cma(&cma_areas[i]);
+
+	return 0;
+}
+
+static void __exit sa_cma_exit(void)
+{
+	int i;
+
+	for (i = 0; i < cma_area_count; i++)
+		simple_allocator_unregister(&sa_cma[i]->parent);
+}
+
+module_init(sa_cma_init);
+module_exit(sa_cma_exit);
-- 
1.9.1

  parent reply	other threads:[~2017-02-13 14:45 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-13 14:45 [RFC simple allocator v2 0/2] Simple allocator Benjamin Gaignard
2017-02-13 14:45 ` [RFC simple allocator v2 1/2] Create Simple Allocator module Benjamin Gaignard
2017-02-14 19:30   ` Laurent Pinchart
2017-02-15  8:41     ` Benjamin Gaignard
2017-02-14 19:33   ` Daniel Vetter
2017-02-14 19:39     ` Laurent Pinchart
2017-02-14 19:44       ` Daniel Vetter
2017-02-14 19:59         ` Laurent Pinchart
2017-02-15  8:51           ` Benjamin Gaignard
2017-02-15 12:15           ` Mark Brown
2017-02-26 20:30             ` Daniel Vetter
2017-02-13 14:45 ` Benjamin Gaignard [this message]
2017-02-13 18:18 ` [RFC simple allocator v2 0/2] Simple allocator Mark Brown
2017-02-13 19:01   ` Laura Abbott
2017-02-14 16:45     ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1486997106-23277-3-git-send-email-benjamin.gaignard@linaro.org \
    --to=benjamin.gaignard@linaro.org \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=broonie@kernel.org \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hverkuil@xs4all.nl \
    --cc=labbott@redhat.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linaro-kernel@lists.linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=robdclark@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).