[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