android: ion: add ion_alloc_dmabuf()
authorCho KyongHo <pullip.cho@samsung.com>
Sun, 11 Feb 2018 11:37:11 +0000 (20:37 +0900)
committerSangwook Ju <sw.ju@samsung.com>
Mon, 14 May 2018 10:45:23 +0000 (19:45 +0900)
ION does not provide API to the kernel drivers.
Thus, ion_alloc_dmabuf() is introduced. To allocate a buffer from a
specific heap of ION, the client should query heaps to search proper
heap then allocate buffers with heap mask of the found heap. This
is tedious and error-prone task for drivers.
Let's allow drivers select a heap with heap name. The Exynos extension
to ION will find the heap with the given name and select the heap for
buffer allocation.
ion_alloc_dmabuf() returns dma_buf instead of fd. To deliver the
allocated dma_buf from ion_alloc_dmabuf() to the userspace, the client
driver should assign it to an unused fd by itself.

Change-Id: Iedc0f970fcc2ddcf4739a5d8c3ecec3cd137e280
Signed-off-by: Cho KyongHo <pullip.cho@samsung.com>
drivers/staging/android/ion/Makefile
drivers/staging/android/ion/ion.c
drivers/staging/android/ion/ion_exynos.c [new file with mode: 0644]
drivers/staging/android/ion/ion_exynos.h
include/linux/ion_exynos.h [new file with mode: 0644]

index 9a8c095bd5e407464280cdc87b0663d3b99afb09..8eeb259771e677075d4f5ad9500c02e9771ed710 100644 (file)
@@ -5,4 +5,4 @@ obj-$(CONFIG_ION_CARVEOUT_HEAP) += ion_carveout_heap.o
 obj-$(CONFIG_ION_CHUNK_HEAP) += ion_chunk_heap.o
 obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o
 obj-$(CONFIG_ION_TEST) += ion_test.o
-obj-$(CONFIG_ION_EXYNOS) += ion_fdt_exynos.o ion_buffer_protect.o
+obj-$(CONFIG_ION_EXYNOS) += ion_fdt_exynos.o ion_buffer_protect.o ion_exynos.o
index ec22bccded53de44d9cc1221736f531b39421ec6..49e32f8d13c3fa26ecb949bf3ac6c9a9f9e184c5 100644 (file)
@@ -430,13 +430,13 @@ static const struct dma_buf_ops dma_buf_ops = {
        .vunmap = ion_dma_buf_vunmap,
 };
 
-int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
+struct dma_buf *__ion_alloc(size_t len, unsigned int heap_id_mask,
+                           unsigned int flags)
 {
        struct ion_device *dev = internal_dev;
        struct ion_buffer *buffer = NULL;
        struct ion_heap *heap;
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-       int fd;
        struct dma_buf *dmabuf;
 
        pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__,
@@ -450,7 +450,7 @@ int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
        len = PAGE_ALIGN(len);
 
        if (!len)
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
 
        down_read(&dev->lock);
        plist_for_each_entry(heap, &dev->heaps, node) {
@@ -464,10 +464,10 @@ int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
        up_read(&dev->lock);
 
        if (!buffer)
-               return -ENODEV;
+               return ERR_PTR(-ENODEV);
 
        if (IS_ERR(buffer))
-               return PTR_ERR(buffer);
+               return ERR_CAST(buffer);
 
        exp_info.ops = &dma_buf_ops;
        exp_info.size = buffer->size;
@@ -475,10 +475,19 @@ int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
        exp_info.priv = buffer;
 
        dmabuf = dma_buf_export(&exp_info);
-       if (IS_ERR(dmabuf)) {
+       if (IS_ERR(dmabuf))
                _ion_buffer_destroy(buffer);
+
+       return dmabuf;
+}
+
+int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
+{
+       struct dma_buf *dmabuf = __ion_alloc(len, heap_id_mask, flags);
+       int fd;
+
+       if (IS_ERR(dmabuf))
                return PTR_ERR(dmabuf);
-       }
 
        fd = dma_buf_fd(dmabuf, O_CLOEXEC);
        if (fd < 0)
@@ -538,6 +547,21 @@ out:
        return ret;
 }
 
+struct ion_heap *ion_get_heap_by_name(const char *heap_name)
+{
+       struct ion_device *dev = internal_dev;
+       struct ion_heap *heap;
+
+       plist_for_each_entry(heap, &dev->heaps, node) {
+               if (strlen(heap_name) != strlen(heap->name))
+                       continue;
+               if (strcmp(heap_name, heap->name) == 0)
+                       return heap;
+       }
+
+       return NULL;
+}
+
 static const struct file_operations ion_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = ion_ioctl,
diff --git a/drivers/staging/android/ion/ion_exynos.c b/drivers/staging/android/ion/ion_exynos.c
new file mode 100644 (file)
index 0000000..b1cd1bf
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * drivers/staging/android/ion/ion_exynos.c
+ *
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 "ion.h"
+#include "ion_exynos.h"
+
+struct dma_buf *ion_alloc_dmabuf(const char *heap_name,
+                                size_t len, unsigned int flags)
+{
+       struct ion_heap *heap = ion_get_heap_by_name(heap_name);
+
+       if (!heap) {
+               pr_err("%s: heap '%s' is not found\n", __func__, heap_name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return __ion_alloc(len, 1 << heap->id, flags);
+}
index d2ee7620619e4fbd1e2502d4a54618066e23dbb2..0c1dd2eb23902ac328330204445bf1cecc95afea 100644 (file)
@@ -18,6 +18,7 @@
 #define _ION_EXYNOS_H_
 
 struct cma;
+struct dma_buf;
 struct ion_heap;
 struct ion_platform_heap;
 
@@ -78,4 +79,7 @@ static inline void *ion_buffer_protect_single(unsigned int protection_id,
 #define ion_buffer_unprotect(priv) do { } while (0)
 #endif
 
+struct ion_heap *ion_get_heap_by_name(const char *heap_name);
+struct dma_buf *__ion_alloc(size_t len, unsigned int heap_id_mask,
+                           unsigned int flags);
 #endif /* _ION_EXYNOS_H_ */
diff --git a/include/linux/ion_exynos.h b/include/linux/ion_exynos.h
new file mode 100644 (file)
index 0000000..b0e3da2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * include/linux/ion_exynos.h
+ *
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_ION_EXYNOS_H__
+#define __LINUX_ION_EXYNOS_H__
+
+#define ION_FLAG_CACHED 1
+#define ION_FLAG_PROTECTED 16
+
+#ifdef CONFIG_ION_EXYNOS
+struct dma_buf *ion_alloc_dmabuf(const char *heap_name,
+                                size_t len, unsigned int flags);
+#else
+static inline struct dma_buf *ion_alloc_dmabuf(const char *heap_name,
+                                              size_t len, unsigned int flags)
+{
+       return ERR_PTR(-ENODEV);
+}
+#endif
+
+#endif /* __LINUX_ION_EXYNOS_H__ */