On 12/16/18 2:46 AM, Alexey Skidanov wrote:
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@start" kernel boot parameter.
I've been thinking about this and I think it works but
I'm still kind of torn about not having devicetree bindings.
It doesn't _preclude_ devicetree bindings but I'd hate to
merge this and then end up with something incompatible.
I do want to support non-Android use cases too.
I'm also curious about the value of this heap with just PAGE_SIZE.
The original purpose of the chunk heap was a carveout where
you could easily get allocations large than PAGE_SIZE to
reduce TLB pressure. Do you have another use case for the
chunk heap?
Sumit, do you have any thoughts?
Thanks,
Laura
Link: http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-November/128495.html
Signed-off-by: Alexey Skidanov <alexey.skidanov@xxxxxxxxx>
---
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 */
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel