[PATCH] staging: android: ion: Add chunk heaps instantiation

Alexey Skidanov alexey.skidanov at intel.com
Sun Dec 16 10:46:01 UTC 2018


Chunk heap instantiation should be supported for device tree platforms and
non device tree platforms. For device tree platforms, it's a platform
specific code responsibility to retrieve the heap configuration data
and to call the appropriate API for heap creation. For non device tree
platforms, there is no defined way to create the heaps.

This patch provides the way of chunk heaps creation using
"ion_chunk_heap=name:size at start" kernel boot parameter.

Link: http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-November/128495.html
Signed-off-by: Alexey Skidanov <alexey.skidanov at intel.com>
---
 drivers/staging/android/ion/ion_chunk_heap.c | 96 +++++++++++++++++++++++++---
 include/linux/ion.h                          | 18 ++++++
 2 files changed, 105 insertions(+), 9 deletions(-)
 create mode 100644 include/linux/ion.h

diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 102c093..1a8e3ad 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -21,8 +21,12 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/ion.h>
 #include "ion.h"
 
+static struct ion_chunk_heap_cfg chunk_heap_cfg[MAX_NUM_OF_CHUNK_HEAPS];
+static unsigned int num_of_req_chunk_heaps;
+
 struct ion_chunk_heap {
 	struct ion_heap heap;
 	struct gen_pool *pool;
@@ -117,15 +121,15 @@ static struct ion_heap_ops chunk_heap_ops = {
 	.unmap_kernel = ion_heap_unmap_kernel,
 };
 
-struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
+static struct ion_heap *ion_chunk_heap_create(struct ion_chunk_heap_cfg *heap_cfg)
 {
 	struct ion_chunk_heap *chunk_heap;
 	int ret;
 	struct page *page;
 	size_t size;
 
-	page = pfn_to_page(PFN_DOWN(heap_data->base));
-	size = heap_data->size;
+	page = pfn_to_page(PFN_DOWN(heap_cfg->base));
+	size = heap_cfg->size;
 
 	ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
 	if (ret)
@@ -135,23 +139,27 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
 	if (!chunk_heap)
 		return ERR_PTR(-ENOMEM);
 
-	chunk_heap->chunk_size = (unsigned long)heap_data->priv;
+	chunk_heap->chunk_size = heap_cfg->chunk_size;
 	chunk_heap->pool = gen_pool_create(get_order(chunk_heap->chunk_size) +
 					   PAGE_SHIFT, -1);
 	if (!chunk_heap->pool) {
 		ret = -ENOMEM;
 		goto error_gen_pool_create;
 	}
-	chunk_heap->base = heap_data->base;
-	chunk_heap->size = heap_data->size;
+	chunk_heap->base = heap_cfg->base;
+	chunk_heap->size = heap_cfg->size;
+	chunk_heap->heap.name = heap_cfg->heap_name;
 	chunk_heap->allocated = 0;
 
-	gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1);
+	gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_cfg->size, -1);
 	chunk_heap->heap.ops = &chunk_heap_ops;
 	chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;
 	chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
-	pr_debug("%s: base %pa size %zu\n", __func__,
-		 &chunk_heap->base, heap_data->size);
+
+	pr_info("%s: name %s base %pa size %zu\n", __func__,
+		heap_cfg->heap_name,
+		&heap_cfg->base,
+		heap_cfg->size);
 
 	return &chunk_heap->heap;
 
@@ -160,3 +168,73 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
 	return ERR_PTR(ret);
 }
 
+static int __init setup_heap(char *param)
+{
+	char *at_sign, *coma, *colon;
+	size_t size_to_copy;
+	struct ion_chunk_heap_cfg *cfg;
+
+	do {
+		cfg = &chunk_heap_cfg[num_of_req_chunk_heaps];
+
+		/* heap name */
+		colon = strchr(param, ':');
+		if (!colon)
+			return -EINVAL;
+
+		size_to_copy = min_t(size_t, MAX_CHUNK_HEAP_NAME_SIZE - 1,
+				     (colon - param));
+		strncpy(cfg->heap_name,	param, size_to_copy);
+		cfg->heap_name[size_to_copy] = '\0';
+
+		/* heap size */
+		cfg->size = memparse((colon + 1), &at_sign);
+		if ((colon + 1) == at_sign)
+			return -EINVAL;
+
+		/* heap base addr */
+		if (*at_sign == '@')
+			cfg->base = memparse(at_sign + 1, &coma);
+		else
+			return -EINVAL;
+
+		if (at_sign == coma)
+			return -EINVAL;
+
+		/* Chunk size */
+		cfg->chunk_size = PAGE_SIZE;
+
+		num_of_req_chunk_heaps++;
+
+		/* if one more heap configuration exists */
+		if (*coma == ',')
+			param = coma + 1;
+		else
+			param = NULL;
+	} while (num_of_req_chunk_heaps < MAX_NUM_OF_CHUNK_HEAPS && param);
+
+	return 0;
+}
+
+__setup("ion_chunk_heap=", setup_heap);
+
+int ion_add_chunk_heaps(struct ion_chunk_heap_cfg *cfg,
+			unsigned int num_of_heaps)
+{
+	unsigned int i;
+	struct ion_heap *heap;
+
+	for (i = 0; i < num_of_heaps; i++) {
+		heap = ion_chunk_heap_create(&cfg[i]);
+		if (heap)
+			ion_device_add_heap(heap);
+	}
+	return 0;
+}
+
+static int ion_add_chunk_heaps_from_boot_param(void)
+{
+	return ion_add_chunk_heaps(chunk_heap_cfg, num_of_req_chunk_heaps);
+}
+
+device_initcall(ion_add_chunk_heaps_from_boot_param);
diff --git a/include/linux/ion.h b/include/linux/ion.h
new file mode 100644
index 0000000..60296c9
--- /dev/null
+++ b/include/linux/ion.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_ION_H
+#define _LINUX_ION_H
+
+#define MAX_NUM_OF_CHUNK_HEAPS 32
+#define MAX_CHUNK_HEAP_NAME_SIZE 32
+
+struct ion_chunk_heap_cfg {
+	char heap_name[MAX_CHUNK_HEAP_NAME_SIZE];
+	phys_addr_t base;
+	size_t size;
+	size_t chunk_size;
+};
+
+int ion_add_chunk_heaps(struct ion_chunk_heap_cfg *cfg,
+			unsigned int  num_of_heaps);
+
+#endif /* _LINUX_ION_H */
-- 
2.7.4



More information about the devel mailing list