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. 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 */ -- 2.7.4 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel