From: Cho KyongHo Date: Sun, 11 Feb 2018 11:37:11 +0000 (+0900) Subject: android: ion: add ion_alloc_dmabuf() X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=d458ca439e86448dae0e41ee331a32d50c4b3578;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git android: ion: add ion_alloc_dmabuf() 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 --- diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 9a8c095bd5e4..8eeb259771e6 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -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 diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ec22bccded53..49e32f8d13c3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -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 index 000000000000..b1cd1bf60177 --- /dev/null +++ b/drivers/staging/android/ion/ion_exynos.c @@ -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); +} diff --git a/drivers/staging/android/ion/ion_exynos.h b/drivers/staging/android/ion/ion_exynos.h index d2ee7620619e..0c1dd2eb2390 100644 --- a/drivers/staging/android/ion/ion_exynos.h +++ b/drivers/staging/android/ion/ion_exynos.h @@ -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 index 000000000000..b0e3da259aa1 --- /dev/null +++ b/include/linux/ion_exynos.h @@ -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__ */