[Linaro-mm-sig] [PATCH v3 3/4] add CMA heap

benjamin.gaignard at stericsson.com benjamin.gaignard at stericsson.com
Wed Mar 14 15:35:14 UTC 2012


From: Benjamin Gaignard <benjamin.gaignard at linaro.org>

New heap, allocation is done with dma_alloc_coherent API.
device dma_mask and coherent_dma_mask fields must be set to DMA_BIT_MASK(32)
CMA heap use ion_heap private field to store the device pointer

Signed-off-by: Benjamin Gaignard <benjamin.gaignard at linaro.org>
---
 drivers/gpu/ion/Kconfig            |    6 ++
 drivers/gpu/ion/Makefile           |    1 +
 drivers/gpu/ion/cma/Makefile       |    1 +
 drivers/gpu/ion/cma/ion_cma_heap.c |  126 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/ion/cma/ion_cma_heap.h |   11 +++
 5 files changed, 145 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/ion/cma/Makefile
 create mode 100644 drivers/gpu/ion/cma/ion_cma_heap.c
 create mode 100644 drivers/gpu/ion/cma/ion_cma_heap.h

diff --git a/drivers/gpu/ion/Kconfig b/drivers/gpu/ion/Kconfig
index 0e87dab..231dbb1 100644
--- a/drivers/gpu/ion/Kconfig
+++ b/drivers/gpu/ion/Kconfig
@@ -9,3 +9,9 @@ config ION_TEGRA
 	depends on ARCH_TEGRA && ION
 	help
 	  Choose this option if you wish to use ion on an nVidia Tegra.
+
+config ION_CMA
+	tristate "Ion CMA heap"
+	depends on ION && CMA
+	help
+	  Choose this option to enable ION CMA heap.
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
index 73fe3fa..05f174a 100644
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ION) +=	ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o
 obj-$(CONFIG_ION_TEGRA) += tegra/
+obj-$(CONFIG_ION_CMA) += cma/
diff --git a/drivers/gpu/ion/cma/Makefile b/drivers/gpu/ion/cma/Makefile
new file mode 100644
index 0000000..673508d
--- /dev/null
+++ b/drivers/gpu/ion/cma/Makefile
@@ -0,0 +1 @@
+obj-y += ion_cma_heap.o
diff --git a/drivers/gpu/ion/cma/ion_cma_heap.c b/drivers/gpu/ion/cma/ion_cma_heap.c
new file mode 100644
index 0000000..53d59fc
--- /dev/null
+++ b/drivers/gpu/ion/cma/ion_cma_heap.c
@@ -0,0 +1,126 @@
+/*
+ * drivers/gpu/ion/ion_cma_heap.c
+ *
+ * Copyright (C) Linaro 2012
+ * Author: <benjamin.gaignard at linaro.org> for ST-Ericsson.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/ion.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/miscdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+
+/* for ion_heap_ops structure */
+#include "../ion_priv.h"
+
+#define ION_CMA_ALLOCATE_FAILED -1
+
+struct ion_cma_buffer_info {
+	void *cpu_addr;
+	dma_addr_t handle;
+};
+
+/* ION CMA heap operations functions */
+static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
+			    unsigned long len, unsigned long align,
+			    unsigned long flags)
+{
+	struct device *dev = heap->priv;
+	struct ion_cma_buffer_info *info;
+
+	dev_dbg(dev, "Request buffer allocation len %ld\n", len);
+
+	info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL);
+	if (!info) {
+		dev_err(dev, "Can't allocate buffer info\n");
+		return ION_CMA_ALLOCATE_FAILED;
+	}
+
+	info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), 0);
+
+	if (!info->cpu_addr) {
+		dev_err(dev, "Fail to allocate buffer\n");
+		kfree(info);
+		return ION_CMA_ALLOCATE_FAILED;
+	}
+
+	/* keep this for memory release */
+	buffer->priv_virt = info;
+	dev_dbg(dev, "Allocate buffer %p\n", buffer);
+	return 0;
+}
+
+static void ion_cma_free(struct ion_buffer *buffer)
+{
+	struct device *dev = buffer->heap->priv;
+	struct ion_cma_buffer_info *info = buffer->priv_virt;
+
+	dev_dbg(dev, "Release buffer %p\n", buffer);
+	dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle);
+	kfree(info);
+}
+
+/* return physical address in addr */
+static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer,
+			ion_phys_addr_t *addr, size_t *len)
+{
+	struct device *dev = heap->priv;
+	struct ion_cma_buffer_info *info = buffer->priv_virt;
+
+	dev_dbg(dev, "Return buffer %p physical address 0x%x\n", buffer,
+		virt_to_phys(info->cpu_addr));
+
+	*addr = virt_to_phys(info->cpu_addr);
+	*len = buffer->size;
+
+	return 0;
+}
+
+static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
+			struct vm_area_struct *vma)
+{
+	struct device *dev = buffer->heap->priv;
+	struct ion_cma_buffer_info *info = buffer->priv_virt;
+
+	return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle,
+				 buffer->size);
+}
+
+static struct ion_heap_ops ion_cma_ops = {
+	.allocate = ion_cma_allocate,
+	.free = ion_cma_free,
+	.phys = ion_cma_phys,
+	.map_user = ion_cma_mmap,
+};
+
+struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data,
+				     struct device *dev)
+{
+	struct ion_heap *heap;
+
+	heap = ion_heap_create(data);
+
+	if (heap) {
+		heap->ops = &ion_cma_ops;
+		/* set device as private heaps data, later it will be
+		 * used to make the link with reserved CMA memory */
+		heap->priv = dev;
+	}
+	return heap;
+}
+EXPORT_SYMBOL(ion_cma_heap_create);
diff --git a/drivers/gpu/ion/cma/ion_cma_heap.h b/drivers/gpu/ion/cma/ion_cma_heap.h
new file mode 100644
index 0000000..267e654
--- /dev/null
+++ b/drivers/gpu/ion/cma/ion_cma_heap.h
@@ -0,0 +1,11 @@
+/*
+ * ion_cma_heap.h
+ *
+ * Copyright (C) Linaro 2012
+ *
+ * Author: <benjamin.gaignard at linaro.org> for ST-Ericsson.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data,
+				     struct device *dev);
-- 
1.7.0.4




More information about the Linaro-mm-sig mailing list