Hi,
This is v4 of the series to cleanup to Ion. Greg took some of the patches that weren't CMA related already. There was a minor bisectability problem with the CMA APIs so this is a new version to address that. I also addressed some minor comments on the patch to collapse header files.
Thanks, Laura
Laura Abbott (12): cma: Store a name in the cma structure cma: Introduce cma_for_each_area staging: android: ion: Use CMA APIs directly staging: android: ion: Stop butchering the DMA address staging: android: ion: Break the ABI in the name of forward progress staging: android: ion: Get rid of ion_phys_addr_t staging: android: ion: Collapse internal header files staging: android: ion: Rework heap registration/enumeration staging: android: ion: Drop ion_map_kernel interface staging: android: ion: Remove ion_handle and ion_client staging: android: ion: Set query return value staging/android: Update Ion TODO list
arch/powerpc/kvm/book3s_hv_builtin.c | 3 +- drivers/base/dma-contiguous.c | 5 +- drivers/staging/android/TODO | 21 +- drivers/staging/android/ion/Kconfig | 32 + drivers/staging/android/ion/Makefile | 11 +- drivers/staging/android/ion/compat_ion.c | 152 ----- drivers/staging/android/ion/compat_ion.h | 29 - drivers/staging/android/ion/ion-ioctl.c | 55 +- drivers/staging/android/ion/ion.c | 812 ++---------------------- drivers/staging/android/ion/ion.h | 386 ++++++++--- drivers/staging/android/ion/ion_carveout_heap.c | 21 +- drivers/staging/android/ion/ion_chunk_heap.c | 16 +- drivers/staging/android/ion/ion_cma_heap.c | 120 ++-- drivers/staging/android/ion/ion_heap.c | 68 -- drivers/staging/android/ion/ion_page_pool.c | 3 +- drivers/staging/android/ion/ion_priv.h | 453 ------------- drivers/staging/android/ion/ion_system_heap.c | 39 +- drivers/staging/android/uapi/ion.h | 36 +- include/linux/cma.h | 6 +- mm/cma.c | 31 +- mm/cma.h | 1 + mm/cma_debug.c | 2 +- 22 files changed, 524 insertions(+), 1778 deletions(-) delete mode 100644 drivers/staging/android/ion/compat_ion.c delete mode 100644 drivers/staging/android/ion/compat_ion.h delete mode 100644 drivers/staging/android/ion/ion_priv.h
Frameworks that may want to enumerate CMA heaps (e.g. Ion) will find it useful to have an explicit name attached to each region. Store the name in each CMA structure.
Signed-off-by: Laura Abbott labbott@redhat.com --- arch/powerpc/kvm/book3s_hv_builtin.c | 3 ++- drivers/base/dma-contiguous.c | 5 +++-- include/linux/cma.h | 4 +++- mm/cma.c | 17 +++++++++++++++-- mm/cma.h | 1 + mm/cma_debug.c | 2 +- 6 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 4d6c64b..b739ff8 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -100,7 +100,8 @@ void __init kvm_cma_reserve(void) (unsigned long)selected_size / SZ_1M); align_size = HPT_ALIGN_PAGES << PAGE_SHIFT; cma_declare_contiguous(0, selected_size, 0, align_size, - KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma); + KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, "kvm_cma", + &kvm_cma); } }
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index b55804c..ea9726e 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -165,7 +165,8 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, { int ret;
- ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma); + ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, + "reserved", res_cma); if (ret) return ret;
@@ -258,7 +259,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem) return -EINVAL; }
- err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma); + err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma); if (err) { pr_err("Reserved memory: unable to setup CMA region\n"); return err; diff --git a/include/linux/cma.h b/include/linux/cma.h index 03f32d0..d41d1f8 100644 --- a/include/linux/cma.h +++ b/include/linux/cma.h @@ -21,13 +21,15 @@ struct cma; extern unsigned long totalcma_pages; extern phys_addr_t cma_get_base(const struct cma *cma); extern unsigned long cma_get_size(const struct cma *cma); +extern const char *cma_get_name(const struct cma *cma);
extern int __init cma_declare_contiguous(phys_addr_t base, phys_addr_t size, phys_addr_t limit, phys_addr_t alignment, unsigned int order_per_bit, - bool fixed, struct cma **res_cma); + bool fixed, const char *name, struct cma **res_cma); extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, unsigned int order_per_bit, + const char *name, struct cma **res_cma); extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, gfp_t gfp_mask); diff --git a/mm/cma.c b/mm/cma.c index a6033e3..43c1b2c 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -53,6 +53,11 @@ unsigned long cma_get_size(const struct cma *cma) return cma->count << PAGE_SHIFT; }
+const char *cma_get_name(const struct cma *cma) +{ + return cma->name ? cma->name : "(undefined)"; +} + static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, int align_order) { @@ -168,6 +173,7 @@ core_initcall(cma_init_reserved_areas); */ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, unsigned int order_per_bit, + const char *name, struct cma **res_cma) { struct cma *cma; @@ -198,6 +204,13 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, * subsystems (like slab allocator) are available. */ cma = &cma_areas[cma_area_count]; + if (name) { + cma->name = name; + } else { + cma->name = kasprintf(GFP_KERNEL, "cma%d\n", cma_area_count); + if (!cma->name) + return -ENOMEM; + } cma->base_pfn = PFN_DOWN(base); cma->count = size >> PAGE_SHIFT; cma->order_per_bit = order_per_bit; @@ -229,7 +242,7 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, int __init cma_declare_contiguous(phys_addr_t base, phys_addr_t size, phys_addr_t limit, phys_addr_t alignment, unsigned int order_per_bit, - bool fixed, struct cma **res_cma) + bool fixed, const char *name, struct cma **res_cma) { phys_addr_t memblock_end = memblock_end_of_DRAM(); phys_addr_t highmem_start; @@ -335,7 +348,7 @@ int __init cma_declare_contiguous(phys_addr_t base, base = addr; }
- ret = cma_init_reserved_mem(base, size, order_per_bit, res_cma); + ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma); if (ret) goto err;
diff --git a/mm/cma.h b/mm/cma.h index 17c75a4..4986128 100644 --- a/mm/cma.h +++ b/mm/cma.h @@ -11,6 +11,7 @@ struct cma { struct hlist_head mem_head; spinlock_t mem_head_lock; #endif + const char *name; };
extern struct cma cma_areas[MAX_CMA_AREAS]; diff --git a/mm/cma_debug.c b/mm/cma_debug.c index ffc0c3d..595b757 100644 --- a/mm/cma_debug.c +++ b/mm/cma_debug.c @@ -167,7 +167,7 @@ static void cma_debugfs_add_one(struct cma *cma, int idx) char name[16]; int u32s;
- sprintf(name, "cma-%d", idx); + sprintf(name, "cma-%s", cma->name);
tmp = debugfs_create_dir(name, cma_debugfs_root);
Frameworks (e.g. Ion) may want to iterate over each possible CMA area to allow for enumeration. Introduce a function to allow a callback.
Signed-off-by: Laura Abbott labbott@redhat.com --- include/linux/cma.h | 2 ++ mm/cma.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+)
diff --git a/include/linux/cma.h b/include/linux/cma.h index d41d1f8..3e8fbf5 100644 --- a/include/linux/cma.h +++ b/include/linux/cma.h @@ -34,4 +34,6 @@ extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, gfp_t gfp_mask); extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count); + +extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data); #endif diff --git a/mm/cma.c b/mm/cma.c index 43c1b2c..978b4a1 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -504,3 +504,17 @@ bool cma_release(struct cma *cma, const struct page *pages, unsigned int count)
return true; } + +int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data) +{ + int i; + + for (i = 0; i < cma_area_count; i++) { + int ret = it(&cma_areas[i], data); + + if (ret) + return ret; + } + + return 0; +}
When CMA was first introduced, its primary use was for DMA allocation and the only way to get CMA memory was to call dma_alloc_coherent. This put Ion in an awkward position since there was no device structure readily available and setting one up messed up the coherency model. These days, CMA can be allocated directly from the APIs. Switch to using this model to avoid needing a dummy device. This also mitigates some of the caching problems (e.g. dma_alloc_coherent only returning uncached memory).
Signed-off-by: Laura Abbott labbott@redhat.com --- v4: Put some #ifdef around CMA heap functions. This is ugly but gets removed a few patches later. --- drivers/staging/android/ion/Kconfig | 7 +++ drivers/staging/android/ion/Makefile | 3 +- drivers/staging/android/ion/ion_cma_heap.c | 97 ++++++++---------------------- drivers/staging/android/ion/ion_heap.c | 4 ++ 4 files changed, 39 insertions(+), 72 deletions(-)
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 206c4de..15108c4 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -10,3 +10,10 @@ menuconfig ION If you're not using Android its probably safe to say N here.
+config ION_CMA_HEAP + bool "Ion CMA heap support" + depends on ION && CMA + help + Choose this option to enable CMA heaps with Ion. This heap is backed + by the Contiguous Memory Allocator (CMA). If your system has these + regions, you should say Y here. diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 26672a0..66d0c4a 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ ion_page_pool.o ion_system_heap.o \ - ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o + ion_carveout_heap.o ion_chunk_heap.o +obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o ifdef CONFIG_COMPAT obj-$(CONFIG_ION) += compat_ion.o endif diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index d562fd7..f3e0f59 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -19,24 +19,19 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/err.h> -#include <linux/dma-mapping.h> +#include <linux/cma.h> +#include <linux/scatterlist.h>
#include "ion.h" #include "ion_priv.h"
struct ion_cma_heap { struct ion_heap heap; - struct device *dev; + struct cma *cma; };
#define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap)
-struct ion_cma_buffer_info { - void *cpu_addr; - dma_addr_t handle; - struct sg_table *table; -}; -
/* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, @@ -44,93 +39,53 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); - struct device *dev = cma_heap->dev; - struct ion_cma_buffer_info *info; - - dev_dbg(dev, "Request buffer allocation len %ld\n", len); - - if (buffer->flags & ION_FLAG_CACHED) - return -EINVAL; + struct sg_table *table; + struct page *pages; + int ret;
- info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + pages = cma_alloc(cma_heap->cma, len, 0, GFP_KERNEL); + if (!pages) return -ENOMEM;
- info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), - GFP_HIGHUSER | __GFP_ZERO); - - if (!info->cpu_addr) { - dev_err(dev, "Fail to allocate buffer\n"); + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) goto err; - }
- info->table = kmalloc(sizeof(*info->table), GFP_KERNEL); - if (!info->table) + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) goto free_mem;
- if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle, - len)) - goto free_table; - /* keep this for memory release */ - buffer->priv_virt = info; - buffer->sg_table = info->table; - dev_dbg(dev, "Allocate buffer %p\n", buffer); + sg_set_page(table->sgl, pages, len, 0); + + buffer->priv_virt = pages; + buffer->sg_table = table; return 0;
-free_table: - kfree(info->table); free_mem: - dma_free_coherent(dev, len, info->cpu_addr, info->handle); + kfree(table); err: - kfree(info); + cma_release(cma_heap->cma, pages, buffer->size); return -ENOMEM; }
static void ion_cma_free(struct ion_buffer *buffer) { struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); - struct device *dev = cma_heap->dev; - struct ion_cma_buffer_info *info = buffer->priv_virt; + struct page *pages = buffer->priv_virt;
- dev_dbg(dev, "Release buffer %p\n", buffer); /* release memory */ - dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle); + cma_release(cma_heap->cma, pages, buffer->size); /* release sg table */ - sg_free_table(info->table); - kfree(info->table); - kfree(info); -} - -static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); - struct device *dev = cma_heap->dev; - struct ion_cma_buffer_info *info = buffer->priv_virt; - - return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle, - buffer->size); -} - -static void *ion_cma_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct ion_cma_buffer_info *info = buffer->priv_virt; - /* kernel memory mapping has been done at allocation time */ - return info->cpu_addr; -} - -static void ion_cma_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ + sg_free_table(buffer->sg_table); + kfree(buffer->sg_table); }
static struct ion_heap_ops ion_cma_ops = { .allocate = ion_cma_allocate, .free = ion_cma_free, - .map_user = ion_cma_mmap, - .map_kernel = ion_cma_map_kernel, - .unmap_kernel = ion_cma_unmap_kernel, + .map_user = ion_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, };
struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) @@ -147,7 +102,7 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) * get device from private heaps data, later it will be * used to make the link with reserved CMA memory */ - cma_heap->dev = data->priv; + cma_heap->cma = data->priv; cma_heap->heap.type = ION_HEAP_TYPE_DMA; return &cma_heap->heap; } diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index c69d0bd..66f8fc5 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -333,9 +333,11 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) case ION_HEAP_TYPE_CHUNK: heap = ion_chunk_heap_create(heap_data); break; +#ifdef CONFIG_ION_CMA_HEAP case ION_HEAP_TYPE_DMA: heap = ion_cma_heap_create(heap_data); break; +#endif default: pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type); @@ -373,9 +375,11 @@ void ion_heap_destroy(struct ion_heap *heap) case ION_HEAP_TYPE_CHUNK: ion_chunk_heap_destroy(heap); break; +#ifdef CONFIG_ION_CMA_HEAP case ION_HEAP_TYPE_DMA: ion_cma_heap_destroy(heap); break; +#endif default: pr_err("%s: Invalid heap type %d\n", __func__, heap->type);
Now that we have proper caching, stop setting the DMA address manually. It should be set after properly calling dma_map.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/ion.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3d979ef5..65638f5 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -81,8 +81,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, { struct ion_buffer *buffer; struct sg_table *table; - struct scatterlist *sg; - int i, ret; + int ret;
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) @@ -119,20 +118,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, INIT_LIST_HEAD(&buffer->vmas); INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); - /* - * this will set up dma addresses for the sglist -- it is not - * technically correct as per the dma api -- a specific - * device isn't really taking ownership here. However, in practice on - * our systems the only dma_address space is physical addresses. - * Additionally, we can't afford the overhead of invalidating every - * allocation via dma_map_sg. The implicit contract here is that - * memory coming from the heaps is ready for dma, ie if it has a - * cached mapping that mapping has been invalidated - */ - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { - sg_dma_address(sg) = sg_phys(sg); - sg_dma_len(sg) = sg->length; - } mutex_lock(&dev->buffer_lock); ion_buffer_add(dev, buffer); mutex_unlock(&dev->buffer_lock);
Several of the Ion ioctls were designed in such a way that they necessitate compat ioctls. We're breaking a bunch of other ABIs and cleaning stuff up anyway so let's follow the ioctl guidelines and clean things up while everyone is busy converting things over anyway. As part of this, also remove the useless alignment field from the allocation structure.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/Makefile | 3 - drivers/staging/android/ion/compat_ion.c | 152 ------------------------------- drivers/staging/android/ion/compat_ion.h | 29 ------ drivers/staging/android/ion/ion-ioctl.c | 1 - drivers/staging/android/ion/ion.c | 5 +- drivers/staging/android/uapi/ion.h | 19 ++-- 6 files changed, 11 insertions(+), 198 deletions(-) delete mode 100644 drivers/staging/android/ion/compat_ion.c delete mode 100644 drivers/staging/android/ion/compat_ion.h
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 66d0c4a..a892afa 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -2,6 +2,3 @@ obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -ifdef CONFIG_COMPAT -obj-$(CONFIG_ION) += compat_ion.o -endif diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c deleted file mode 100644 index 5037ddd..0000000 --- a/drivers/staging/android/ion/compat_ion.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * drivers/staging/android/ion/compat_ion.c - * - * Copyright (C) 2013 Google, Inc. - * - * 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 <linux/compat.h> -#include <linux/fs.h> -#include <linux/uaccess.h> - -#include "ion.h" -#include "compat_ion.h" - -/* See drivers/staging/android/uapi/ion.h for the definition of these structs */ -struct compat_ion_allocation_data { - compat_size_t len; - compat_size_t align; - compat_uint_t heap_id_mask; - compat_uint_t flags; - compat_int_t handle; -}; - -struct compat_ion_handle_data { - compat_int_t handle; -}; - -#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ - struct compat_ion_allocation_data) -#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, \ - struct compat_ion_handle_data) - -static int compat_get_ion_allocation_data( - struct compat_ion_allocation_data __user *data32, - struct ion_allocation_data __user *data) -{ - compat_size_t s; - compat_uint_t u; - compat_int_t i; - int err; - - err = get_user(s, &data32->len); - err |= put_user(s, &data->len); - err |= get_user(s, &data32->align); - err |= put_user(s, &data->align); - err |= get_user(u, &data32->heap_id_mask); - err |= put_user(u, &data->heap_id_mask); - err |= get_user(u, &data32->flags); - err |= put_user(u, &data->flags); - err |= get_user(i, &data32->handle); - err |= put_user(i, &data->handle); - - return err; -} - -static int compat_get_ion_handle_data( - struct compat_ion_handle_data __user *data32, - struct ion_handle_data __user *data) -{ - compat_int_t i; - int err; - - err = get_user(i, &data32->handle); - err |= put_user(i, &data->handle); - - return err; -} - -static int compat_put_ion_allocation_data( - struct compat_ion_allocation_data __user *data32, - struct ion_allocation_data __user *data) -{ - compat_size_t s; - compat_uint_t u; - compat_int_t i; - int err; - - err = get_user(s, &data->len); - err |= put_user(s, &data32->len); - err |= get_user(s, &data->align); - err |= put_user(s, &data32->align); - err |= get_user(u, &data->heap_id_mask); - err |= put_user(u, &data32->heap_id_mask); - err |= get_user(u, &data->flags); - err |= put_user(u, &data32->flags); - err |= get_user(i, &data->handle); - err |= put_user(i, &data32->handle); - - return err; -} - -long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - long ret; - - if (!filp->f_op->unlocked_ioctl) - return -ENOTTY; - - switch (cmd) { - case COMPAT_ION_IOC_ALLOC: - { - struct compat_ion_allocation_data __user *data32; - struct ion_allocation_data __user *data; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - if (!data) - return -EFAULT; - - err = compat_get_ion_allocation_data(data32, data); - if (err) - return err; - ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC, - (unsigned long)data); - err = compat_put_ion_allocation_data(data32, data); - return ret ? ret : err; - } - case COMPAT_ION_IOC_FREE: - { - struct compat_ion_handle_data __user *data32; - struct ion_handle_data __user *data; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - if (!data) - return -EFAULT; - - err = compat_get_ion_handle_data(data32, data); - if (err) - return err; - - return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE, - (unsigned long)data); - } - case ION_IOC_SHARE: - return filp->f_op->unlocked_ioctl(filp, cmd, - (unsigned long)compat_ptr(arg)); - default: - return -ENOIOCTLCMD; - } -} diff --git a/drivers/staging/android/ion/compat_ion.h b/drivers/staging/android/ion/compat_ion.h deleted file mode 100644 index 9da8f91..0000000 --- a/drivers/staging/android/ion/compat_ion.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * drivers/staging/android/ion/compat_ion.h - * - * Copyright (C) 2013 Google, Inc. - * - * 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_COMPAT_ION_H -#define _LINUX_COMPAT_ION_H - -#if IS_ENABLED(CONFIG_COMPAT) - -long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); - -#else - -#define compat_ion_ioctl NULL - -#endif /* CONFIG_COMPAT */ -#endif /* _LINUX_COMPAT_ION_H */ diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index a361724..91b5c2b 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -20,7 +20,6 @@
#include "ion.h" #include "ion_priv.h" -#include "compat_ion.h"
union ion_ioctl_arg { struct ion_fd_data fd; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 65638f5..fbab1e3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -40,7 +40,6 @@
#include "ion.h" #include "ion_priv.h" -#include "compat_ion.h"
bool ion_buffer_cached(struct ion_buffer *buffer) { @@ -1065,7 +1064,9 @@ static const struct file_operations ion_fops = { .open = ion_open, .release = ion_release, .unlocked_ioctl = ion_ioctl, - .compat_ioctl = compat_ion_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ion_ioctl, +#endif };
static size_t ion_debug_heap_total(struct ion_client *client, diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index abd72fd..bba1c47 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -20,8 +20,6 @@ #include <linux/ioctl.h> #include <linux/types.h>
-typedef int ion_user_handle_t; - /** * enum ion_heap_types - list of all possible types of heaps * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc @@ -76,7 +74,6 @@ enum ion_heap_type { /** * struct ion_allocation_data - metadata passed from userspace for allocations * @len: size of the allocation - * @align: required alignment of the allocation * @heap_id_mask: mask of heap ids to allocate from * @flags: flags passed to heap * @handle: pointer that will be populated with a cookie to use to @@ -85,11 +82,11 @@ enum ion_heap_type { * Provided by userspace as an argument to the ioctl */ struct ion_allocation_data { - size_t len; - size_t align; - unsigned int heap_id_mask; - unsigned int flags; - ion_user_handle_t handle; + __u64 len; + __u32 heap_id_mask; + __u32 flags; + __u32 handle; + __u32 unused; };
/** @@ -103,8 +100,8 @@ struct ion_allocation_data { * provides the file descriptor and the kernel returns the handle. */ struct ion_fd_data { - ion_user_handle_t handle; - int fd; + __u32 handle; + __u32 fd; };
/** @@ -112,7 +109,7 @@ struct ion_fd_data { * @handle: a handle */ struct ion_handle_data { - ion_user_handle_t handle; + __u32 handle; };
#define MAX_HEAP_NAME 32
On Tue, Apr 18, 2017 at 11:27:07AM -0700, Laura Abbott wrote:
Several of the Ion ioctls were designed in such a way that they necessitate compat ioctls. We're breaking a bunch of other ABIs and cleaning stuff up anyway so let's follow the ioctl guidelines and clean things up while everyone is busy converting things over anyway. As part of this, also remove the useless alignment field from the allocation structure.
Signed-off-by: Laura Abbott labbott@redhat.com
Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch
drivers/staging/android/ion/Makefile | 3 - drivers/staging/android/ion/compat_ion.c | 152 ------------------------------- drivers/staging/android/ion/compat_ion.h | 29 ------ drivers/staging/android/ion/ion-ioctl.c | 1 - drivers/staging/android/ion/ion.c | 5 +- drivers/staging/android/uapi/ion.h | 19 ++-- 6 files changed, 11 insertions(+), 198 deletions(-) delete mode 100644 drivers/staging/android/ion/compat_ion.c delete mode 100644 drivers/staging/android/ion/compat_ion.h
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 66d0c4a..a892afa 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -2,6 +2,3 @@ obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -ifdef CONFIG_COMPAT -obj-$(CONFIG_ION) += compat_ion.o -endif diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c deleted file mode 100644 index 5037ddd..0000000 --- a/drivers/staging/android/ion/compat_ion.c +++ /dev/null @@ -1,152 +0,0 @@ -/*
- drivers/staging/android/ion/compat_ion.c
- Copyright (C) 2013 Google, Inc.
- 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 <linux/compat.h> -#include <linux/fs.h> -#include <linux/uaccess.h>
-#include "ion.h" -#include "compat_ion.h"
-/* See drivers/staging/android/uapi/ion.h for the definition of these structs */ -struct compat_ion_allocation_data {
- compat_size_t len;
- compat_size_t align;
- compat_uint_t heap_id_mask;
- compat_uint_t flags;
- compat_int_t handle;
-};
-struct compat_ion_handle_data {
- compat_int_t handle;
-};
-#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
struct compat_ion_allocation_data)
-#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, \
struct compat_ion_handle_data)
-static int compat_get_ion_allocation_data(
struct compat_ion_allocation_data __user *data32,
struct ion_allocation_data __user *data)
-{
- compat_size_t s;
- compat_uint_t u;
- compat_int_t i;
- int err;
- err = get_user(s, &data32->len);
- err |= put_user(s, &data->len);
- err |= get_user(s, &data32->align);
- err |= put_user(s, &data->align);
- err |= get_user(u, &data32->heap_id_mask);
- err |= put_user(u, &data->heap_id_mask);
- err |= get_user(u, &data32->flags);
- err |= put_user(u, &data->flags);
- err |= get_user(i, &data32->handle);
- err |= put_user(i, &data->handle);
- return err;
-}
-static int compat_get_ion_handle_data(
struct compat_ion_handle_data __user *data32,
struct ion_handle_data __user *data)
-{
- compat_int_t i;
- int err;
- err = get_user(i, &data32->handle);
- err |= put_user(i, &data->handle);
- return err;
-}
-static int compat_put_ion_allocation_data(
struct compat_ion_allocation_data __user *data32,
struct ion_allocation_data __user *data)
-{
- compat_size_t s;
- compat_uint_t u;
- compat_int_t i;
- int err;
- err = get_user(s, &data->len);
- err |= put_user(s, &data32->len);
- err |= get_user(s, &data->align);
- err |= put_user(s, &data32->align);
- err |= get_user(u, &data->heap_id_mask);
- err |= put_user(u, &data32->heap_id_mask);
- err |= get_user(u, &data->flags);
- err |= put_user(u, &data32->flags);
- err |= get_user(i, &data->handle);
- err |= put_user(i, &data32->handle);
- return err;
-}
-long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{
- long ret;
- if (!filp->f_op->unlocked_ioctl)
return -ENOTTY;
- switch (cmd) {
- case COMPAT_ION_IOC_ALLOC:
- {
struct compat_ion_allocation_data __user *data32;
struct ion_allocation_data __user *data;
int err;
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
if (!data)
return -EFAULT;
err = compat_get_ion_allocation_data(data32, data);
if (err)
return err;
ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
(unsigned long)data);
err = compat_put_ion_allocation_data(data32, data);
return ret ? ret : err;
- }
- case COMPAT_ION_IOC_FREE:
- {
struct compat_ion_handle_data __user *data32;
struct ion_handle_data __user *data;
int err;
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
if (!data)
return -EFAULT;
err = compat_get_ion_handle_data(data32, data);
if (err)
return err;
return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
(unsigned long)data);
- }
- case ION_IOC_SHARE:
return filp->f_op->unlocked_ioctl(filp, cmd,
(unsigned long)compat_ptr(arg));
- default:
return -ENOIOCTLCMD;
- }
-} diff --git a/drivers/staging/android/ion/compat_ion.h b/drivers/staging/android/ion/compat_ion.h deleted file mode 100644 index 9da8f91..0000000 --- a/drivers/staging/android/ion/compat_ion.h +++ /dev/null @@ -1,29 +0,0 @@ -/*
- drivers/staging/android/ion/compat_ion.h
- Copyright (C) 2013 Google, Inc.
- 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_COMPAT_ION_H -#define _LINUX_COMPAT_ION_H
-#if IS_ENABLED(CONFIG_COMPAT)
-long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-#else
-#define compat_ion_ioctl NULL
-#endif /* CONFIG_COMPAT */ -#endif /* _LINUX_COMPAT_ION_H */ diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index a361724..91b5c2b 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -20,7 +20,6 @@ #include "ion.h" #include "ion_priv.h" -#include "compat_ion.h" union ion_ioctl_arg { struct ion_fd_data fd; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 65638f5..fbab1e3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -40,7 +40,6 @@ #include "ion.h" #include "ion_priv.h" -#include "compat_ion.h" bool ion_buffer_cached(struct ion_buffer *buffer) { @@ -1065,7 +1064,9 @@ static const struct file_operations ion_fops = { .open = ion_open, .release = ion_release, .unlocked_ioctl = ion_ioctl,
- .compat_ioctl = compat_ion_ioctl,
+#ifdef CONFIG_COMPAT
- .compat_ioctl = ion_ioctl,
+#endif }; static size_t ion_debug_heap_total(struct ion_client *client, diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index abd72fd..bba1c47 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -20,8 +20,6 @@ #include <linux/ioctl.h> #include <linux/types.h> -typedef int ion_user_handle_t;
/**
- enum ion_heap_types - list of all possible types of heaps
- @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc
@@ -76,7 +74,6 @@ enum ion_heap_type { /**
- struct ion_allocation_data - metadata passed from userspace for allocations
- @len: size of the allocation
- @align: required alignment of the allocation
- @heap_id_mask: mask of heap ids to allocate from
- @flags: flags passed to heap
- @handle: pointer that will be populated with a cookie to use to
@@ -85,11 +82,11 @@ enum ion_heap_type {
- Provided by userspace as an argument to the ioctl
*/ struct ion_allocation_data {
- size_t len;
- size_t align;
- unsigned int heap_id_mask;
- unsigned int flags;
- ion_user_handle_t handle;
- __u64 len;
- __u32 heap_id_mask;
- __u32 flags;
- __u32 handle;
- __u32 unused;
}; /** @@ -103,8 +100,8 @@ struct ion_allocation_data {
- provides the file descriptor and the kernel returns the handle.
*/ struct ion_fd_data {
- ion_user_handle_t handle;
- int fd;
- __u32 handle;
- __u32 fd;
}; /** @@ -112,7 +109,7 @@ struct ion_fd_data {
- @handle: a handle
*/ struct ion_handle_data {
- ion_user_handle_t handle;
- __u32 handle;
};
#define MAX_HEAP_NAME 32
2.7.4
Linaro-mm-sig mailing list Linaro-mm-sig@lists.linaro.org https://lists.linaro.org/mailman/listinfo/linaro-mm-sig
Once upon a time, phys_addr_t was not everywhere in the kernel. These days it is used enough places that having a separate Ion type doesn't make sense. Remove the extra type and just use phys_addr_t directly.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/ion.h | 12 ++---------- drivers/staging/android/ion/ion_carveout_heap.c | 10 +++++----- drivers/staging/android/ion/ion_chunk_heap.c | 6 +++--- drivers/staging/android/ion/ion_heap.c | 4 ++-- 4 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 3b4bff5..e8a6ffe 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -28,14 +28,6 @@ struct ion_mapper; struct ion_client; struct ion_buffer;
-/* - * This should be removed some day when phys_addr_t's are fully - * plumbed in the kernel, and all instances of ion_phys_addr_t should - * be converted to phys_addr_t. For the time being many kernel interfaces - * do not accept phys_addr_t's that would have to - */ -#define ion_phys_addr_t unsigned long - /** * struct ion_platform_heap - defines a heap in the given platform * @type: type of the heap from ion_heap_type enum @@ -53,9 +45,9 @@ struct ion_platform_heap { enum ion_heap_type type; unsigned int id; const char *name; - ion_phys_addr_t base; + phys_addr_t base; size_t size; - ion_phys_addr_t align; + phys_addr_t align; void *priv; };
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index e0e360f..1419a89 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -30,10 +30,10 @@ struct ion_carveout_heap { struct ion_heap heap; struct gen_pool *pool; - ion_phys_addr_t base; + phys_addr_t base; };
-static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, +static phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size) { struct ion_carveout_heap *carveout_heap = @@ -46,7 +46,7 @@ static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, return offset; }
-static void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, +static void ion_carveout_free(struct ion_heap *heap, phys_addr_t addr, unsigned long size) { struct ion_carveout_heap *carveout_heap = @@ -63,7 +63,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, unsigned long flags) { struct sg_table *table; - ion_phys_addr_t paddr; + phys_addr_t paddr; int ret;
table = kmalloc(sizeof(*table), GFP_KERNEL); @@ -96,7 +96,7 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) struct ion_heap *heap = buffer->heap; struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); - ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
ion_heap_buffer_zero(buffer);
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 46e13f6..606f25f 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -27,7 +27,7 @@ struct ion_chunk_heap { struct ion_heap heap; struct gen_pool *pool; - ion_phys_addr_t base; + phys_addr_t base; unsigned long chunk_size; unsigned long size; unsigned long allocated; @@ -151,8 +151,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) 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 %lu size %zu \n", __func__, - chunk_heap->base, heap_data->size); + pr_debug("%s: base %pa size %zu \n", __func__, + &chunk_heap->base, heap_data->size);
return &chunk_heap->heap;
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 66f8fc5..c974623 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -345,9 +345,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) }
if (IS_ERR_OR_NULL(heap)) { - pr_err("%s: error creating heap %s type %d base %lu size %zu\n", + pr_err("%s: error creating heap %s type %d base %pa size %zu\n", __func__, heap_data->name, heap_data->type, - heap_data->base, heap_data->size); + &heap_data->base, heap_data->size); return ERR_PTR(-EINVAL); }
Ion current has ion_priv.h and ion.h as header files. ion.h was intended to be used for public APIs but Ion never ended up really having anything public. Combine the two headers so there is only one internal header.
Signed-off-by: Laura Abbott labbott@redhat.com --- v4: minor cleanup suggested by Emil Velikov --- drivers/staging/android/ion/ion-ioctl.c | 1 - drivers/staging/android/ion/ion.c | 1 - drivers/staging/android/ion/ion.h | 479 ++++++++++++++++++++---- drivers/staging/android/ion/ion_carveout_heap.c | 1 - drivers/staging/android/ion/ion_chunk_heap.c | 1 - drivers/staging/android/ion/ion_cma_heap.c | 1 - drivers/staging/android/ion/ion_heap.c | 1 - drivers/staging/android/ion/ion_page_pool.c | 3 +- drivers/staging/android/ion/ion_priv.h | 453 ---------------------- drivers/staging/android/ion/ion_system_heap.c | 1 - 10 files changed, 402 insertions(+), 540 deletions(-) delete mode 100644 drivers/staging/android/ion/ion_priv.h
diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 91b5c2b..4e7bf16 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -19,7 +19,6 @@ #include <linux/uaccess.h>
#include "ion.h" -#include "ion_priv.h"
union ion_ioctl_arg { struct ion_fd_data fd; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index fbab1e3..e1fb865 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -39,7 +39,6 @@ #include <linux/sched/task.h>
#include "ion.h" -#include "ion_priv.h"
bool ion_buffer_cached(struct ion_buffer *buffer) { diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index e8a6ffe..fd49403 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -14,24 +14,26 @@ * */
-#ifndef _LINUX_ION_H -#define _LINUX_ION_H +#ifndef _ION_H +#define _ION_H
+#include <linux/device.h> +#include <linux/dma-direction.h> +#include <linux/kref.h> +#include <linux/mm_types.h> +#include <linux/mutex.h> +#include <linux/rbtree.h> +#include <linux/sched.h> +#include <linux/shrinker.h> #include <linux/types.h> +#include <linux/miscdevice.h>
#include "../uapi/ion.h"
-struct ion_handle; -struct ion_device; -struct ion_heap; -struct ion_mapper; -struct ion_client; -struct ion_buffer; - /** * struct ion_platform_heap - defines a heap in the given platform * @type: type of the heap from ion_heap_type enum - * @id: unique identifier for heap. When allocating higher numbers + * @id: unique identifier for heap. When allocating higher numb ers * will be allocated from first. At allocation these are passed * as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS. * @name: used for debug purposes @@ -52,114 +54,433 @@ struct ion_platform_heap { };
/** - * struct ion_platform_data - array of platform heaps passed from board file - * @nr: number of structures in the array - * @heaps: array of platform_heap structions + * struct ion_buffer - metadata for a particular buffer + * @ref: reference count + * @node: node in the ion_device buffers tree + * @dev: back pointer to the ion_device + * @heap: back pointer to the heap the buffer came from + * @flags: buffer specific flags + * @private_flags: internal buffer specific flags + * @size: size of the buffer + * @priv_virt: private data to the buffer representable as + * a void * + * @lock: protects the buffers cnt fields + * @kmap_cnt: number of times the buffer is mapped to the kernel + * @vaddr: the kernel mapping if kmap_cnt is not zero + * @sg_table: the sg table for the buffer if dmap_cnt is not zero + * @pages: flat array of pages in the buffer -- used by fault + * handler and only valid for buffers that are faulted in + * @vmas: list of vma's mapping this buffer + * @handle_count: count of handles referencing this buffer + * @task_comm: taskcomm of last client to reference this buffer in a + * handle, used for debugging + * @pid: pid of last client to reference this buffer in a + * handle, used for debugging + */ +struct ion_buffer { + struct kref ref; + union { + struct rb_node node; + struct list_head list; + }; + struct ion_device *dev; + struct ion_heap *heap; + unsigned long flags; + unsigned long private_flags; + size_t size; + void *priv_virt; + struct mutex lock; + int kmap_cnt; + void *vaddr; + struct sg_table *sg_table; + struct page **pages; + struct list_head vmas; + struct list_head attachments; + /* used to track orphaned buffers */ + int handle_count; + char task_comm[TASK_COMM_LEN]; + pid_t pid; +}; +void ion_buffer_destroy(struct ion_buffer *buffer); + +/** + * struct ion_device - the metadata of the ion device node + * @dev: the actual misc device + * @buffers: an rb tree of all the existing buffers + * @buffer_lock: lock protecting the tree of buffers + * @lock: rwsem protecting the tree of heaps and clients + * @heaps: list of all the heaps in the system + * @user_clients: list of all the clients created from userspace + */ +struct ion_device { + struct miscdevice dev; + struct rb_root buffers; + struct mutex buffer_lock; + struct rw_semaphore lock; + struct plist_head heaps; + struct rb_root clients; + struct dentry *debug_root; + struct dentry *heaps_debug_root; + struct dentry *clients_debug_root; + int heap_cnt; +}; + +/** + * struct ion_client - a process/hw block local address space + * @node: node in the tree of all clients + * @dev: backpointer to ion device + * @handles: an rb tree of all the handles in this client + * @idr: an idr space for allocating handle ids + * @lock: lock protecting the tree of handles + * @name: used for debugging + * @display_name: used for debugging (unique version of @name) + * @display_serial: used for debugging (to make display_name unique) + * @task: used for debugging + * + * A client represents a list of buffers this client may access. + * The mutex stored here is used to protect both handles tree + * as well as the handles themselves, and should be held while modifying either. + */ +struct ion_client { + struct rb_node node; + struct ion_device *dev; + struct rb_root handles; + struct idr idr; + struct mutex lock; + const char *name; + char *display_name; + int display_serial; + struct task_struct *task; + pid_t pid; + struct dentry *debug_root; +}; + +/** + * ion_handle - a client local reference to a buffer + * @ref: reference count + * @client: back pointer to the client the buffer resides in + * @buffer: pointer to the buffer + * @node: node in the client's handle rbtree + * @kmap_cnt: count of times this client has mapped to kernel + * @id: client-unique id allocated by client->idr + * + * Modifications to node, map_cnt or mapping should be protected by the + * lock in the client. Other fields are never changed after initialization. + */ +struct ion_handle { + struct kref ref; + struct ion_client *client; + struct ion_buffer *buffer; + struct rb_node node; + unsigned int kmap_cnt; + int id; +}; + +/** + * struct ion_heap_ops - ops to operate on a given heap + * @allocate: allocate memory + * @free: free memory + * @map_kernel map memory to the kernel + * @unmap_kernel unmap memory to the kernel + * @map_user map memory to userspace * - * Provided by the board file in the form of platform data to a platform device. + * allocate, phys, and map_user return 0 on success, -errno on error. + * map_dma and map_kernel return pointer on success, ERR_PTR on + * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in + * the buffer's private_flags when called from a shrinker. In that + * case, the pages being free'd must be truly free'd back to the + * system, not put in a page pool or otherwise cached. */ -struct ion_platform_data { - int nr; - struct ion_platform_heap *heaps; +struct ion_heap_ops { + int (*allocate)(struct ion_heap *heap, + struct ion_buffer *buffer, unsigned long len, + unsigned long flags); + void (*free)(struct ion_buffer *buffer); + void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); + void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); + int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, + struct vm_area_struct *vma); + int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); };
/** - * ion_client_create() - allocate a client and returns it - * @dev: the global ion device + * heap flags - flags between the heaps and core ion code + */ +#define ION_HEAP_FLAG_DEFER_FREE (1 << 0) + +/** + * private flags - flags internal to ion + */ +/* + * Buffer is being freed from a shrinker function. Skip any possible + * heap-specific caching mechanism (e.g. page pools). Guarantees that + * any buffer storage that came from the system allocator will be + * returned to the system allocator. + */ +#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0) + +/** + * struct ion_heap - represents a heap in the system + * @node: rb node to put the heap on the device's tree of heaps + * @dev: back pointer to the ion_device + * @type: type of heap + * @ops: ops struct as above + * @flags: flags + * @id: id of heap, also indicates priority of this heap when + * allocating. These are specified by platform data and + * MUST be unique * @name: used for debugging + * @shrinker: a shrinker for the heap + * @free_list: free list head if deferred free is used + * @free_list_size size of the deferred free list in bytes + * @lock: protects the free list + * @waitqueue: queue to wait on from deferred free thread + * @task: task struct of deferred free thread + * @debug_show: called when heap debug file is read to add any + * heap specific debug info to output + * + * Represents a pool of memory from which buffers can be made. In some + * systems the only heap is regular system memory allocated via vmalloc. + * On others, some blocks might require large physically contiguous buffers + * that are allocated from a specially reserved heap. */ -struct ion_client *ion_client_create(struct ion_device *dev, - const char *name); +struct ion_heap { + struct plist_node node; + struct ion_device *dev; + enum ion_heap_type type; + struct ion_heap_ops *ops; + unsigned long flags; + unsigned int id; + const char *name; + struct shrinker shrinker; + struct list_head free_list; + size_t free_list_size; + spinlock_t free_lock; + wait_queue_head_t waitqueue; + struct task_struct *task; + + int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); +};
/** - * ion_client_destroy() - free's a client and all it's handles - * @client: the client + * ion_buffer_cached - this ion buffer is cached + * @buffer: buffer * - * Free the provided client and all it's resources including - * any handles it is holding. + * indicates whether this ion buffer is cached */ -void ion_client_destroy(struct ion_client *client); +bool ion_buffer_cached(struct ion_buffer *buffer);
/** - * ion_alloc - allocate ion memory - * @client: the client - * @len: size of the allocation - * @heap_id_mask: mask of heaps to allocate from, if multiple bits are set - * heaps will be tried in order from highest to lowest - * id - * @flags: heap flags, the low 16 bits are consumed by ion, the - * high 16 bits are passed on to the respective heap and - * can be heap custom + * ion_buffer_fault_user_mappings - fault in user mappings of this buffer + * @buffer: buffer * - * Allocate memory in one of the heaps provided in heap mask and return - * an opaque handle to it. + * indicates whether userspace mappings of this buffer will be faulted + * in, this can affect how buffers are allocated from the heap. */ -struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - unsigned int heap_id_mask, - unsigned int flags); +bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
/** - * ion_free - free a handle - * @client: the client - * @handle: the handle to free + * ion_device_create - allocates and returns an ion device * - * Free the provided handle. + * returns a valid device or -PTR_ERR + */ +struct ion_device *ion_device_create(void); + +/** + * ion_device_destroy - free and device and it's resource + * @dev: the device + */ +void ion_device_destroy(struct ion_device *dev); + +/** + * ion_device_add_heap - adds a heap to the ion device + * @dev: the device + * @heap: the heap to add */ +void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); + +/** + * some helpers for common operations on buffers using the sg_table + * and vaddr fields + */ +void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer); +void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer); +int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, + struct vm_area_struct *vma); +int ion_heap_buffer_zero(struct ion_buffer *buffer); +int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); + +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + unsigned int heap_id_mask, + unsigned int flags); + void ion_free(struct ion_client *client, struct ion_handle *handle);
+int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); + /** - * ion_map_kernel - create mapping for the given handle - * @client: the client - * @handle: handle to map + * ion_heap_init_shrinker + * @heap: the heap * - * Map the given handle into the kernel and return a kernel address that - * can be used to access this address. + * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op + * this function will be called to setup a shrinker to shrink the freelists + * and call the heap's shrink op. */ -void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle); +void ion_heap_init_shrinker(struct ion_heap *heap);
/** - * ion_unmap_kernel() - destroy a kernel mapping for a handle - * @client: the client - * @handle: handle to unmap + * ion_heap_init_deferred_free -- initialize deferred free functionality + * @heap: the heap + * + * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will + * be called to setup deferred frees. Calls to free the buffer will + * return immediately and the actual free will occur some time later */ -void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); +int ion_heap_init_deferred_free(struct ion_heap *heap);
/** - * ion_share_dma_buf() - share buffer as dma-buf - * @client: the client - * @handle: the handle + * ion_heap_freelist_add - add a buffer to the deferred free list + * @heap: the heap + * @buffer: the buffer + * + * Adds an item to the deferred freelist. */ -struct dma_buf *ion_share_dma_buf(struct ion_client *client, - struct ion_handle *handle); +void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer);
/** - * ion_share_dma_buf_fd() - given an ion client, create a dma-buf fd - * @client: the client - * @handle: the handle + * ion_heap_freelist_drain - drain the deferred free list + * @heap: the heap + * @size: amount of memory to drain in bytes + * + * Drains the indicated amount of memory from the deferred freelist immediately. + * Returns the total amount freed. The total freed may be higher depending + * on the size of the items in the list, or lower if there is insufficient + * total memory on the freelist. */ -int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); +size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size);
/** - * ion_import_dma_buf() - get ion_handle from dma-buf - * @client: the client - * @dmabuf: the dma-buf + * ion_heap_freelist_shrink - drain the deferred free + * list, skipping any heap-specific + * pooling or caching mechanisms + * + * @heap: the heap + * @size: amount of memory to drain in bytes + * + * Drains the indicated amount of memory from the deferred freelist immediately. + * Returns the total amount freed. The total freed may be higher depending + * on the size of the items in the list, or lower if there is insufficient + * total memory on the freelist. * - * Get the ion_buffer associated with the dma-buf and return the ion_handle. - * If no ion_handle exists for this buffer, return newly created ion_handle. - * If dma-buf from another exporter is passed, return ERR_PTR(-EINVAL) + * Unlike with @ion_heap_freelist_drain, don't put any pages back into + * page pools or otherwise cache the pages. Everything must be + * genuinely free'd back to the system. If you're free'ing from a + * shrinker you probably want to use this. Note that this relies on + * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE + * flag. + */ +size_t ion_heap_freelist_shrink(struct ion_heap *heap, + size_t size); + +/** + * ion_heap_freelist_size - returns the size of the freelist in bytes + * @heap: the heap + */ +size_t ion_heap_freelist_size(struct ion_heap *heap); + + +/** + * functions for creating and destroying the built in ion heaps. + * architectures can add their own custom architecture specific + * heaps as appropriate. */ -struct ion_handle *ion_import_dma_buf(struct ion_client *client, - struct dma_buf *dmabuf); + + +struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data); +void ion_heap_destroy(struct ion_heap *heap); + +struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused); +void ion_system_heap_destroy(struct ion_heap *heap); +struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap); +void ion_system_contig_heap_destroy(struct ion_heap *heap); + +struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data); +void ion_carveout_heap_destroy(struct ion_heap *heap); + +struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data); +void ion_chunk_heap_destroy(struct ion_heap *heap); + +struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data); +void ion_cma_heap_destroy(struct ion_heap *heap);
/** - * ion_import_dma_buf_fd() - given a dma-buf fd from the ion exporter get handle - * @client: the client - * @fd: the dma-buf fd + * functions for creating and destroying a heap pool -- allows you + * to keep a pool of pre allocated memory to use from your heap. Keeping + * a pool of memory that is ready for dma, ie any cached mapping have been + * invalidated from the cache, provides a significant performance benefit on + * many systems + */ + +/** + * struct ion_page_pool - pagepool struct + * @high_count: number of highmem items in the pool + * @low_count: number of lowmem items in the pool + * @high_items: list of highmem items + * @low_items: list of lowmem items + * @mutex: lock protecting this struct and especially the count + * item list + * @gfp_mask: gfp_mask to use from alloc + * @order: order of pages in the pool + * @list: plist node for list of pools + * @cached: it's cached pool or not * - * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf_fd, - * import that fd and return a handle representing it. If a dma-buf from - * another exporter is passed in this function will return ERR_PTR(-EINVAL) + * Allows you to keep a pool of pre allocated pages to use from your heap. + * Keeping a pool of pages that is ready for dma, ie any cached mapping have + * been invalidated from the cache, provides a significant performance benefit + * on many systems */ -struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd); +struct ion_page_pool { + int high_count; + int low_count; + bool cached; + struct list_head high_items; + struct list_head low_items; + struct mutex mutex; + gfp_t gfp_mask; + unsigned int order; + struct plist_node list; +}; + +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, + bool cached); +void ion_page_pool_destroy(struct ion_page_pool *pool); +struct page *ion_page_pool_alloc(struct ion_page_pool *pool); +void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); + +/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool + * @pool: the pool + * @gfp_mask: the memory type to reclaim + * @nr_to_scan: number of items to shrink in pages + * + * returns the number of items freed in pages + */ +int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, + int nr_to_scan); + +long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); + +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id); + +void ion_free_nolock(struct ion_client *client, struct ion_handle *handle); + +int ion_handle_put_nolock(struct ion_handle *handle); + +struct ion_handle *ion_handle_get_by_id(struct ion_client *client, + int id); + +int ion_handle_put(struct ion_handle *handle); + +int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
-#endif /* _LINUX_ION_H */ +#endif /* _ION_H */ diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 1419a89..7287279 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -23,7 +23,6 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include "ion.h" -#include "ion_priv.h"
#define ION_CARVEOUT_ALLOCATE_FAIL -1
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 606f25f..9210bfe 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -22,7 +22,6 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include "ion.h" -#include "ion_priv.h"
struct ion_chunk_heap { struct ion_heap heap; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index f3e0f59..e67e78d 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -23,7 +23,6 @@ #include <linux/scatterlist.h>
#include "ion.h" -#include "ion_priv.h"
struct ion_cma_heap { struct ion_heap heap; diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index c974623..d8d057c 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -24,7 +24,6 @@ #include <linux/scatterlist.h> #include <linux/vmalloc.h> #include "ion.h" -#include "ion_priv.h"
void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 532eda7..817849d 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -22,7 +22,8 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/swap.h> -#include "ion_priv.h" + +#include "ion.h"
static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) { diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h deleted file mode 100644 index a86866a..0000000 --- a/drivers/staging/android/ion/ion_priv.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * drivers/staging/android/ion/ion_priv.h - * - * Copyright (C) 2011 Google, Inc. - * - * 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 _ION_PRIV_H -#define _ION_PRIV_H - -#include <linux/device.h> -#include <linux/dma-direction.h> -#include <linux/kref.h> -#include <linux/mm_types.h> -#include <linux/mutex.h> -#include <linux/rbtree.h> -#include <linux/sched.h> -#include <linux/shrinker.h> -#include <linux/types.h> -#include <linux/miscdevice.h> - -#include "ion.h" - -/** - * struct ion_buffer - metadata for a particular buffer - * @ref: reference count - * @node: node in the ion_device buffers tree - * @dev: back pointer to the ion_device - * @heap: back pointer to the heap the buffer came from - * @flags: buffer specific flags - * @private_flags: internal buffer specific flags - * @size: size of the buffer - * @priv_virt: private data to the buffer representable as - * a void * - * @lock: protects the buffers cnt fields - * @kmap_cnt: number of times the buffer is mapped to the kernel - * @vaddr: the kernel mapping if kmap_cnt is not zero - * @sg_table: the sg table for the buffer if dmap_cnt is not zero - * @pages: flat array of pages in the buffer -- used by fault - * handler and only valid for buffers that are faulted in - * @vmas: list of vma's mapping this buffer - * @handle_count: count of handles referencing this buffer - * @task_comm: taskcomm of last client to reference this buffer in a - * handle, used for debugging - * @pid: pid of last client to reference this buffer in a - * handle, used for debugging - */ -struct ion_buffer { - struct kref ref; - union { - struct rb_node node; - struct list_head list; - }; - struct ion_device *dev; - struct ion_heap *heap; - unsigned long flags; - unsigned long private_flags; - size_t size; - void *priv_virt; - struct mutex lock; - int kmap_cnt; - void *vaddr; - struct sg_table *sg_table; - struct page **pages; - struct list_head vmas; - struct list_head attachments; - /* used to track orphaned buffers */ - int handle_count; - char task_comm[TASK_COMM_LEN]; - pid_t pid; -}; -void ion_buffer_destroy(struct ion_buffer *buffer); - -/** - * struct ion_device - the metadata of the ion device node - * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers - * @lock: rwsem protecting the tree of heaps and clients - * @heaps: list of all the heaps in the system - * @user_clients: list of all the clients created from userspace - */ -struct ion_device { - struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; - struct rw_semaphore lock; - struct plist_head heaps; - struct rb_root clients; - struct dentry *debug_root; - struct dentry *heaps_debug_root; - struct dentry *clients_debug_root; - int heap_cnt; -}; - -/** - * struct ion_client - a process/hw block local address space - * @node: node in the tree of all clients - * @dev: backpointer to ion device - * @handles: an rb tree of all the handles in this client - * @idr: an idr space for allocating handle ids - * @lock: lock protecting the tree of handles - * @name: used for debugging - * @display_name: used for debugging (unique version of @name) - * @display_serial: used for debugging (to make display_name unique) - * @task: used for debugging - * - * A client represents a list of buffers this client may access. - * The mutex stored here is used to protect both handles tree - * as well as the handles themselves, and should be held while modifying either. - */ -struct ion_client { - struct rb_node node; - struct ion_device *dev; - struct rb_root handles; - struct idr idr; - struct mutex lock; - const char *name; - char *display_name; - int display_serial; - struct task_struct *task; - pid_t pid; - struct dentry *debug_root; -}; - -/** - * ion_handle - a client local reference to a buffer - * @ref: reference count - * @client: back pointer to the client the buffer resides in - * @buffer: pointer to the buffer - * @node: node in the client's handle rbtree - * @kmap_cnt: count of times this client has mapped to kernel - * @id: client-unique id allocated by client->idr - * - * Modifications to node, map_cnt or mapping should be protected by the - * lock in the client. Other fields are never changed after initialization. - */ -struct ion_handle { - struct kref ref; - struct ion_client *client; - struct ion_buffer *buffer; - struct rb_node node; - unsigned int kmap_cnt; - int id; -}; - -/** - * struct ion_heap_ops - ops to operate on a given heap - * @allocate: allocate memory - * @free: free memory - * @map_kernel map memory to the kernel - * @unmap_kernel unmap memory to the kernel - * @map_user map memory to userspace - * - * allocate, phys, and map_user return 0 on success, -errno on error. - * map_dma and map_kernel return pointer on success, ERR_PTR on - * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in - * the buffer's private_flags when called from a shrinker. In that - * case, the pages being free'd must be truly free'd back to the - * system, not put in a page pool or otherwise cached. - */ -struct ion_heap_ops { - int (*allocate)(struct ion_heap *heap, - struct ion_buffer *buffer, unsigned long len, - unsigned long flags); - void (*free)(struct ion_buffer *buffer); - void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); - void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); - int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, - struct vm_area_struct *vma); - int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); -}; - -/** - * heap flags - flags between the heaps and core ion code - */ -#define ION_HEAP_FLAG_DEFER_FREE (1 << 0) - -/** - * private flags - flags internal to ion - */ -/* - * Buffer is being freed from a shrinker function. Skip any possible - * heap-specific caching mechanism (e.g. page pools). Guarantees that - * any buffer storage that came from the system allocator will be - * returned to the system allocator. - */ -#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0) - -/** - * struct ion_heap - represents a heap in the system - * @node: rb node to put the heap on the device's tree of heaps - * @dev: back pointer to the ion_device - * @type: type of heap - * @ops: ops struct as above - * @flags: flags - * @id: id of heap, also indicates priority of this heap when - * allocating. These are specified by platform data and - * MUST be unique - * @name: used for debugging - * @shrinker: a shrinker for the heap - * @free_list: free list head if deferred free is used - * @free_list_size size of the deferred free list in bytes - * @lock: protects the free list - * @waitqueue: queue to wait on from deferred free thread - * @task: task struct of deferred free thread - * @debug_show: called when heap debug file is read to add any - * heap specific debug info to output - * - * Represents a pool of memory from which buffers can be made. In some - * systems the only heap is regular system memory allocated via vmalloc. - * On others, some blocks might require large physically contiguous buffers - * that are allocated from a specially reserved heap. - */ -struct ion_heap { - struct plist_node node; - struct ion_device *dev; - enum ion_heap_type type; - struct ion_heap_ops *ops; - unsigned long flags; - unsigned int id; - const char *name; - struct shrinker shrinker; - struct list_head free_list; - size_t free_list_size; - spinlock_t free_lock; - wait_queue_head_t waitqueue; - struct task_struct *task; - - int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); -}; - -/** - * ion_buffer_cached - this ion buffer is cached - * @buffer: buffer - * - * indicates whether this ion buffer is cached - */ -bool ion_buffer_cached(struct ion_buffer *buffer); - -/** - * ion_buffer_fault_user_mappings - fault in user mappings of this buffer - * @buffer: buffer - * - * indicates whether userspace mappings of this buffer will be faulted - * in, this can affect how buffers are allocated from the heap. - */ -bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer); - -/** - * ion_device_create - allocates and returns an ion device - * - * returns a valid device or -PTR_ERR - */ -struct ion_device *ion_device_create(void); - -/** - * ion_device_destroy - free and device and it's resource - * @dev: the device - */ -void ion_device_destroy(struct ion_device *dev); - -/** - * ion_device_add_heap - adds a heap to the ion device - * @dev: the device - * @heap: the heap to add - */ -void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); - -/** - * some helpers for common operations on buffers using the sg_table - * and vaddr fields - */ -void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer); -void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer); -int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma); -int ion_heap_buffer_zero(struct ion_buffer *buffer); -int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); - -/** - * ion_heap_init_shrinker - * @heap: the heap - * - * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op - * this function will be called to setup a shrinker to shrink the freelists - * and call the heap's shrink op. - */ -void ion_heap_init_shrinker(struct ion_heap *heap); - -/** - * ion_heap_init_deferred_free -- initialize deferred free functionality - * @heap: the heap - * - * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will - * be called to setup deferred frees. Calls to free the buffer will - * return immediately and the actual free will occur some time later - */ -int ion_heap_init_deferred_free(struct ion_heap *heap); - -/** - * ion_heap_freelist_add - add a buffer to the deferred free list - * @heap: the heap - * @buffer: the buffer - * - * Adds an item to the deferred freelist. - */ -void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); - -/** - * ion_heap_freelist_drain - drain the deferred free list - * @heap: the heap - * @size: amount of memory to drain in bytes - * - * Drains the indicated amount of memory from the deferred freelist immediately. - * Returns the total amount freed. The total freed may be higher depending - * on the size of the items in the list, or lower if there is insufficient - * total memory on the freelist. - */ -size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); - -/** - * ion_heap_freelist_shrink - drain the deferred free - * list, skipping any heap-specific - * pooling or caching mechanisms - * - * @heap: the heap - * @size: amount of memory to drain in bytes - * - * Drains the indicated amount of memory from the deferred freelist immediately. - * Returns the total amount freed. The total freed may be higher depending - * on the size of the items in the list, or lower if there is insufficient - * total memory on the freelist. - * - * Unlike with @ion_heap_freelist_drain, don't put any pages back into - * page pools or otherwise cache the pages. Everything must be - * genuinely free'd back to the system. If you're free'ing from a - * shrinker you probably want to use this. Note that this relies on - * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE - * flag. - */ -size_t ion_heap_freelist_shrink(struct ion_heap *heap, - size_t size); - -/** - * ion_heap_freelist_size - returns the size of the freelist in bytes - * @heap: the heap - */ -size_t ion_heap_freelist_size(struct ion_heap *heap); - - -/** - * functions for creating and destroying the built in ion heaps. - * architectures can add their own custom architecture specific - * heaps as appropriate. - */ - -struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data); -void ion_heap_destroy(struct ion_heap *heap); -struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused); -void ion_system_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap); -void ion_system_contig_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data); -void ion_carveout_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data); -void ion_chunk_heap_destroy(struct ion_heap *heap); -struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data); -void ion_cma_heap_destroy(struct ion_heap *heap); - -/** - * functions for creating and destroying a heap pool -- allows you - * to keep a pool of pre allocated memory to use from your heap. Keeping - * a pool of memory that is ready for dma, ie any cached mapping have been - * invalidated from the cache, provides a significant performance benefit on - * many systems - */ - -/** - * struct ion_page_pool - pagepool struct - * @high_count: number of highmem items in the pool - * @low_count: number of lowmem items in the pool - * @high_items: list of highmem items - * @low_items: list of lowmem items - * @mutex: lock protecting this struct and especially the count - * item list - * @gfp_mask: gfp_mask to use from alloc - * @order: order of pages in the pool - * @list: plist node for list of pools - * @cached: it's cached pool or not - * - * Allows you to keep a pool of pre allocated pages to use from your heap. - * Keeping a pool of pages that is ready for dma, ie any cached mapping have - * been invalidated from the cache, provides a significant performance benefit - * on many systems - */ -struct ion_page_pool { - int high_count; - int low_count; - bool cached; - struct list_head high_items; - struct list_head low_items; - struct mutex mutex; - gfp_t gfp_mask; - unsigned int order; - struct plist_node list; -}; - -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, - bool cached); -void ion_page_pool_destroy(struct ion_page_pool *pool); -struct page *ion_page_pool_alloc(struct ion_page_pool *pool); -void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); - -/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool - * @pool: the pool - * @gfp_mask: the memory type to reclaim - * @nr_to_scan: number of items to shrink in pages - * - * returns the number of items freed in pages - */ -int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, - int nr_to_scan); - -long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); - -struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id); - -void ion_free_nolock(struct ion_client *client, struct ion_handle *handle); - -int ion_handle_put_nolock(struct ion_handle *handle); - -struct ion_handle *ion_handle_get_by_id(struct ion_client *client, - int id); - -int ion_handle_put(struct ion_handle *handle); - -int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query); - -#endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index a33331b..4e6fe37 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -24,7 +24,6 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include "ion.h" -#include "ion_priv.h"
#define NUM_ORDERS ARRAY_SIZE(orders)
The current model of Ion heap registration is based on the outdated model of board files. The replacement for board files (devicetree) isn't a good replacement for what Ion wants to do. In actuality, Ion wants to show what memory is available in the system for something else to figure out what to use. Switch to a model where Ion creates its device unconditionally and heaps are registed as available regions. Currently, only system and CMA heaps are converted over to the new model. Carveout and chunk heaps can be converted over when someone wants to figure out how.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/Kconfig | 25 +++++++++ drivers/staging/android/ion/Makefile | 7 +-- drivers/staging/android/ion/ion.c | 28 +++++----- drivers/staging/android/ion/ion.h | 40 +------------- drivers/staging/android/ion/ion_carveout_heap.c | 10 ---- drivers/staging/android/ion/ion_chunk_heap.c | 9 ---- drivers/staging/android/ion/ion_cma_heap.c | 24 +++++++-- drivers/staging/android/ion/ion_heap.c | 71 ------------------------- drivers/staging/android/ion/ion_system_heap.c | 38 ++++++++----- 9 files changed, 85 insertions(+), 167 deletions(-)
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 15108c4..a517b2d 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -10,6 +10,31 @@ menuconfig ION If you're not using Android its probably safe to say N here.
+config ION_SYSTEM_HEAP + bool "Ion system heap" + depends on ION + help + Choose this option to enable the Ion system heap. The system heap + is backed by pages from the buddy allocator. If in doubt, say Y. + +config ION_CARVEOUT_HEAP + bool "Ion carveout heap support" + depends on ION + help + Choose this option to enable carveout heaps with Ion. Carveout heaps + are backed by memory reserved from the system. Allocation times are + typically faster at the cost of memory not being used. Unless you + know your system has these regions, you should say N here. + +config ION_CHUNK_HEAP + bool "Ion chunk heap support" + depends on ION + help + Choose this option to enable chunk heaps with Ion. This heap is + similar in function the carveout heap but memory is broken down + into smaller chunk sizes, typically corresponding to a TLB size. + Unless you know your system has these regions, you should say N here. + config ION_CMA_HEAP bool "Ion CMA heap support" depends on ION && CMA diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index a892afa..eb7eeed 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ - ion_page_pool.o ion_system_heap.o \ - ion_carveout_heap.o ion_chunk_heap.o +obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o +obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o +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 diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e1fb865..7d40233 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -40,6 +40,9 @@
#include "ion.h"
+static struct ion_device *internal_dev; +static int heap_id = 0; + bool ion_buffer_cached(struct ion_buffer *buffer) { return !!(buffer->flags & ION_FLAG_CACHED); @@ -1198,9 +1201,10 @@ static int debug_shrink_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, debug_shrink_set, "%llu\n");
-void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) +void ion_device_add_heap(struct ion_heap *heap) { struct dentry *debug_file; + struct ion_device *dev = internal_dev;
if (!heap->ops->allocate || !heap->ops->free) pr_err("%s: can not add heap with invalid ops struct.\n", @@ -1217,6 +1221,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
heap->dev = dev; down_write(&dev->lock); + heap->id = heap_id++; /* * use negative heap->id to reverse the priority -- when traversing * the list later attempt higher id numbers first @@ -1256,14 +1261,14 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) } EXPORT_SYMBOL(ion_device_add_heap);
-struct ion_device *ion_device_create(void) +int ion_device_create(void) { struct ion_device *idev; int ret;
idev = kzalloc(sizeof(*idev), GFP_KERNEL); if (!idev) - return ERR_PTR(-ENOMEM); + return -ENOMEM;
idev->dev.minor = MISC_DYNAMIC_MINOR; idev->dev.name = "ion"; @@ -1273,7 +1278,7 @@ struct ion_device *ion_device_create(void) if (ret) { pr_err("ion: failed to register misc device.\n"); kfree(idev); - return ERR_PTR(ret); + return ret; }
idev->debug_root = debugfs_create_dir("ion", NULL); @@ -1292,7 +1297,6 @@ struct ion_device *ion_device_create(void) pr_err("ion: failed to create debugfs clients directory.\n");
debugfs_done: - idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); @@ -1300,15 +1304,7 @@ struct ion_device *ion_device_create(void) idev->clients = RB_ROOT; ion_root_client = &idev->clients; mutex_init(&debugfs_mutex); - return idev; -} -EXPORT_SYMBOL(ion_device_create); - -void ion_device_destroy(struct ion_device *dev) -{ - misc_deregister(&dev->dev); - debugfs_remove_recursive(dev->debug_root); - /* XXX need to free the heaps and clients ? */ - kfree(dev); + internal_dev = idev; + return 0; } -EXPORT_SYMBOL(ion_device_destroy); +subsys_initcall(ion_device_create); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index fd49403..36a1587 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -280,24 +280,10 @@ bool ion_buffer_cached(struct ion_buffer *buffer); bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
/** - * ion_device_create - allocates and returns an ion device - * - * returns a valid device or -PTR_ERR - */ -struct ion_device *ion_device_create(void); - -/** - * ion_device_destroy - free and device and it's resource - * @dev: the device - */ -void ion_device_destroy(struct ion_device *dev); - -/** * ion_device_add_heap - adds a heap to the ion device - * @dev: the device * @heap: the heap to add */ -void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); +void ion_device_add_heap(struct ion_heap *heap);
/** * some helpers for common operations on buffers using the sg_table @@ -390,30 +376,6 @@ size_t ion_heap_freelist_size(struct ion_heap *heap);
/** - * functions for creating and destroying the built in ion heaps. - * architectures can add their own custom architecture specific - * heaps as appropriate. - */ - - -struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data); -void ion_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused); -void ion_system_heap_destroy(struct ion_heap *heap); -struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap); -void ion_system_contig_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data); -void ion_carveout_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data); -void ion_chunk_heap_destroy(struct ion_heap *heap); - -struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data); -void ion_cma_heap_destroy(struct ion_heap *heap); - -/** * functions for creating and destroying a heap pool -- allows you * to keep a pool of pre allocated memory to use from your heap. Keeping * a pool of memory that is ready for dma, ie any cached mapping have been diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 7287279..5fdc1f3 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -145,13 +145,3 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
return &carveout_heap->heap; } - -void ion_carveout_heap_destroy(struct ion_heap *heap) -{ - struct ion_carveout_heap *carveout_heap = - container_of(heap, struct ion_carveout_heap, heap); - - gen_pool_destroy(carveout_heap->pool); - kfree(carveout_heap); - carveout_heap = NULL; -} diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 9210bfe..9c257c7 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -160,12 +160,3 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) return ERR_PTR(ret); }
-void ion_chunk_heap_destroy(struct ion_heap *heap) -{ - struct ion_chunk_heap *chunk_heap = - container_of(heap, struct ion_chunk_heap, heap); - - gen_pool_destroy(chunk_heap->pool); - kfree(chunk_heap); - chunk_heap = NULL; -} diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index e67e78d..dc2a913 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -87,7 +87,7 @@ static struct ion_heap_ops ion_cma_ops = { .unmap_kernel = ion_heap_unmap_kernel, };
-struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) +static struct ion_heap *__ion_cma_heap_create(struct cma *cma) { struct ion_cma_heap *cma_heap;
@@ -101,14 +101,28 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) * get device from private heaps data, later it will be * used to make the link with reserved CMA memory */ - cma_heap->cma = data->priv; + cma_heap->cma = cma; cma_heap->heap.type = ION_HEAP_TYPE_DMA; return &cma_heap->heap; }
-void ion_cma_heap_destroy(struct ion_heap *heap) +int __ion_add_cma_heaps(struct cma *cma, void *data) { - struct ion_cma_heap *cma_heap = to_cma_heap(heap); + struct ion_heap *heap; + + heap = __ion_cma_heap_create(cma); + if (IS_ERR(heap)) + return PTR_ERR(heap);
- kfree(cma_heap); + heap->name = cma_get_name(cma); + + ion_device_add_heap(heap); + return 0; +} + +static int ion_add_cma_heaps(void) +{ + cma_for_each_area(__ion_add_cma_heaps, NULL); + return 0; } +device_initcall(ion_add_cma_heaps); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index d8d057c..91faa7f 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -314,74 +314,3 @@ void ion_heap_init_shrinker(struct ion_heap *heap) heap->shrinker.batch = 0; register_shrinker(&heap->shrinker); } - -struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) -{ - struct ion_heap *heap = NULL; - - switch (heap_data->type) { - case ION_HEAP_TYPE_SYSTEM_CONTIG: - heap = ion_system_contig_heap_create(heap_data); - break; - case ION_HEAP_TYPE_SYSTEM: - heap = ion_system_heap_create(heap_data); - break; - case ION_HEAP_TYPE_CARVEOUT: - heap = ion_carveout_heap_create(heap_data); - break; - case ION_HEAP_TYPE_CHUNK: - heap = ion_chunk_heap_create(heap_data); - break; -#ifdef CONFIG_ION_CMA_HEAP - case ION_HEAP_TYPE_DMA: - heap = ion_cma_heap_create(heap_data); - break; -#endif - default: - pr_err("%s: Invalid heap type %d\n", __func__, - heap_data->type); - return ERR_PTR(-EINVAL); - } - - if (IS_ERR_OR_NULL(heap)) { - pr_err("%s: error creating heap %s type %d base %pa size %zu\n", - __func__, heap_data->name, heap_data->type, - &heap_data->base, heap_data->size); - return ERR_PTR(-EINVAL); - } - - heap->name = heap_data->name; - heap->id = heap_data->id; - return heap; -} -EXPORT_SYMBOL(ion_heap_create); - -void ion_heap_destroy(struct ion_heap *heap) -{ - if (!heap) - return; - - switch (heap->type) { - case ION_HEAP_TYPE_SYSTEM_CONTIG: - ion_system_contig_heap_destroy(heap); - break; - case ION_HEAP_TYPE_SYSTEM: - ion_system_heap_destroy(heap); - break; - case ION_HEAP_TYPE_CARVEOUT: - ion_carveout_heap_destroy(heap); - break; - case ION_HEAP_TYPE_CHUNK: - ion_chunk_heap_destroy(heap); - break; -#ifdef CONFIG_ION_CMA_HEAP - case ION_HEAP_TYPE_DMA: - ion_cma_heap_destroy(heap); - break; -#endif - default: - pr_err("%s: Invalid heap type %d\n", __func__, - heap->type); - } -} -EXPORT_SYMBOL(ion_heap_destroy); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 4e6fe37..c50f2d9 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -320,7 +320,7 @@ static int ion_system_heap_create_pools(struct ion_page_pool **pools, return -ENOMEM; }
-struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) +static struct ion_heap *__ion_system_heap_create(void) { struct ion_system_heap *heap;
@@ -348,19 +348,19 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) return ERR_PTR(-ENOMEM); }
-void ion_system_heap_destroy(struct ion_heap *heap) +static int ion_system_heap_create(void) { - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - int i; + struct ion_heap *heap;
- for (i = 0; i < NUM_ORDERS; i++) { - ion_page_pool_destroy(sys_heap->uncached_pools[i]); - ion_page_pool_destroy(sys_heap->cached_pools[i]); - } - kfree(sys_heap); + heap = __ion_system_heap_create(); + if (IS_ERR(heap)) + return PTR_ERR(heap); + heap->name = "ion_system_heap"; + + ion_device_add_heap(heap); + return 0; } +device_initcall(ion_system_heap_create);
static int ion_system_contig_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, @@ -429,7 +429,7 @@ static struct ion_heap_ops kmalloc_ops = { .map_user = ion_heap_map_user, };
-struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused) +static struct ion_heap *__ion_system_contig_heap_create(void) { struct ion_heap *heap;
@@ -438,10 +438,20 @@ struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused) return ERR_PTR(-ENOMEM); heap->ops = &kmalloc_ops; heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; + heap->name = "ion_system_contig_heap"; return heap; }
-void ion_system_contig_heap_destroy(struct ion_heap *heap) +static int ion_system_contig_heap_create(void) { - kfree(heap); + struct ion_heap *heap; + + heap = __ion_system_contig_heap_create(); + if (IS_ERR(heap)) + return PTR_ERR(heap); + + ion_device_add_heap(heap); + return 0; } +device_initcall(ion_system_contig_heap_create); +
Nobody uses this interface externally. Drop it.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/ion.c | 59 --------------------------------------- 1 file changed, 59 deletions(-)
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7d40233..5a82bea 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -424,22 +424,6 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) return vaddr; }
-static void *ion_handle_kmap_get(struct ion_handle *handle) -{ - struct ion_buffer *buffer = handle->buffer; - void *vaddr; - - if (handle->kmap_cnt) { - handle->kmap_cnt++; - return buffer->vaddr; - } - vaddr = ion_buffer_kmap_get(buffer); - if (IS_ERR(vaddr)) - return vaddr; - handle->kmap_cnt++; - return vaddr; -} - static void ion_buffer_kmap_put(struct ion_buffer *buffer) { buffer->kmap_cnt--; @@ -462,49 +446,6 @@ static void ion_handle_kmap_put(struct ion_handle *handle) ion_buffer_kmap_put(buffer); }
-void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) -{ - struct ion_buffer *buffer; - void *vaddr; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_kernel.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); - } - - buffer = handle->buffer; - - if (!handle->buffer->heap->ops->map_kernel) { - pr_err("%s: map_kernel is not implemented by this heap.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-ENODEV); - } - - mutex_lock(&buffer->lock); - vaddr = ion_handle_kmap_get(handle); - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); - return vaddr; -} -EXPORT_SYMBOL(ion_map_kernel); - -void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) -{ - struct ion_buffer *buffer; - - mutex_lock(&client->lock); - buffer = handle->buffer; - mutex_lock(&buffer->lock); - ion_handle_kmap_put(handle); - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); -} -EXPORT_SYMBOL(ion_unmap_kernel); - static struct mutex debugfs_mutex; static struct rb_root *ion_root_client; static int is_client_alive(struct ion_client *client)
ion_handle was introduced as an abstraction to represent a reference to a buffer via an ion_client. As frameworks outside of Ion evolved, the dmabuf emerged as the preferred standard for use in the kernel. This has made the ion_handle an unnecessary abstraction and prone to race conditions. ion_client is also now only used internally. We have enough mechanisms for race conditions and leaks already so just drop ion_handle and ion_client. This also includes ripping out most of the debugfs infrastructure since much of that was tied to clients and handles. The debugfs infrastructure was prone to give confusing data (orphaned allocations) so it can be replaced with something better if people actually want it.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/ion-ioctl.c | 53 +-- drivers/staging/android/ion/ion.c | 701 ++------------------------------ drivers/staging/android/ion/ion.h | 77 +--- drivers/staging/android/uapi/ion.h | 25 +- 4 files changed, 51 insertions(+), 805 deletions(-)
diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 4e7bf16..76427e4 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -21,9 +21,7 @@ #include "ion.h"
union ion_ioctl_arg { - struct ion_fd_data fd; struct ion_allocation_data allocation; - struct ion_handle_data handle; struct ion_heap_query query; };
@@ -48,8 +46,6 @@ static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) static unsigned int ion_ioctl_dir(unsigned int cmd) { switch (cmd) { - case ION_IOC_FREE: - return _IOC_WRITE; default: return _IOC_DIR(cmd); } @@ -57,8 +53,6 @@ static unsigned int ion_ioctl_dir(unsigned int cmd)
long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct ion_client *client = filp->private_data; - struct ion_handle *cleanup_handle = NULL; int ret = 0; unsigned int dir; union ion_ioctl_arg data; @@ -86,61 +80,28 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case ION_IOC_ALLOC: { - struct ion_handle *handle; + int fd;
- handle = ion_alloc(client, data.allocation.len, + fd = ion_alloc(data.allocation.len, data.allocation.heap_id_mask, data.allocation.flags); - if (IS_ERR(handle)) - return PTR_ERR(handle); + if (fd < 0) + return fd;
- data.allocation.handle = handle->id; + data.allocation.fd = fd;
- cleanup_handle = handle; - break; - } - case ION_IOC_FREE: - { - struct ion_handle *handle; - - mutex_lock(&client->lock); - handle = ion_handle_get_by_id_nolock(client, - data.handle.handle); - if (IS_ERR(handle)) { - mutex_unlock(&client->lock); - return PTR_ERR(handle); - } - ion_free_nolock(client, handle); - ion_handle_put_nolock(handle); - mutex_unlock(&client->lock); - break; - } - case ION_IOC_SHARE: - { - struct ion_handle *handle; - - handle = ion_handle_get_by_id(client, data.handle.handle); - if (IS_ERR(handle)) - return PTR_ERR(handle); - data.fd.fd = ion_share_dma_buf_fd(client, handle); - ion_handle_put(handle); - if (data.fd.fd < 0) - ret = data.fd.fd; break; } case ION_IOC_HEAP_QUERY: - ret = ion_query_heaps(client, &data.query); + ret = ion_query_heaps(&data.query); break; default: return -ENOTTY; }
if (dir & _IOC_READ) { - if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { - if (cleanup_handle) - ion_free(client, cleanup_handle); + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) return -EFAULT; - } } return ret; } diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 5a82bea..9eeb06f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -90,7 +90,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
buffer->heap = heap; buffer->flags = flags; - kref_init(&buffer->ref);
ret = heap->ops->allocate(heap, buffer, len, flags);
@@ -140,9 +139,8 @@ void ion_buffer_destroy(struct ion_buffer *buffer) kfree(buffer); }
-static void _ion_buffer_destroy(struct kref *kref) +static void _ion_buffer_destroy(struct ion_buffer *buffer) { - struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); struct ion_heap *heap = buffer->heap; struct ion_device *dev = buffer->dev;
@@ -156,255 +154,6 @@ static void _ion_buffer_destroy(struct kref *kref) ion_buffer_destroy(buffer); }
-static void ion_buffer_get(struct ion_buffer *buffer) -{ - kref_get(&buffer->ref); -} - -static int ion_buffer_put(struct ion_buffer *buffer) -{ - return kref_put(&buffer->ref, _ion_buffer_destroy); -} - -static void ion_buffer_add_to_handle(struct ion_buffer *buffer) -{ - mutex_lock(&buffer->lock); - buffer->handle_count++; - mutex_unlock(&buffer->lock); -} - -static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) -{ - /* - * when a buffer is removed from a handle, if it is not in - * any other handles, copy the taskcomm and the pid of the - * process it's being removed from into the buffer. At this - * point there will be no way to track what processes this buffer is - * being used by, it only exists as a dma_buf file descriptor. - * The taskcomm and pid can provide a debug hint as to where this fd - * is in the system - */ - mutex_lock(&buffer->lock); - buffer->handle_count--; - BUG_ON(buffer->handle_count < 0); - if (!buffer->handle_count) { - struct task_struct *task; - - task = current->group_leader; - get_task_comm(buffer->task_comm, task); - buffer->pid = task_pid_nr(task); - } - mutex_unlock(&buffer->lock); -} - -static struct ion_handle *ion_handle_create(struct ion_client *client, - struct ion_buffer *buffer) -{ - struct ion_handle *handle; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return ERR_PTR(-ENOMEM); - kref_init(&handle->ref); - RB_CLEAR_NODE(&handle->node); - handle->client = client; - ion_buffer_get(buffer); - ion_buffer_add_to_handle(buffer); - handle->buffer = buffer; - - return handle; -} - -static void ion_handle_kmap_put(struct ion_handle *); - -static void ion_handle_destroy(struct kref *kref) -{ - struct ion_handle *handle = container_of(kref, struct ion_handle, ref); - struct ion_client *client = handle->client; - struct ion_buffer *buffer = handle->buffer; - - mutex_lock(&buffer->lock); - while (handle->kmap_cnt) - ion_handle_kmap_put(handle); - mutex_unlock(&buffer->lock); - - idr_remove(&client->idr, handle->id); - if (!RB_EMPTY_NODE(&handle->node)) - rb_erase(&handle->node, &client->handles); - - ion_buffer_remove_from_handle(buffer); - ion_buffer_put(buffer); - - kfree(handle); -} - -static void ion_handle_get(struct ion_handle *handle) -{ - kref_get(&handle->ref); -} - -int ion_handle_put_nolock(struct ion_handle *handle) -{ - return kref_put(&handle->ref, ion_handle_destroy); -} - -int ion_handle_put(struct ion_handle *handle) -{ - struct ion_client *client = handle->client; - int ret; - - mutex_lock(&client->lock); - ret = ion_handle_put_nolock(handle); - mutex_unlock(&client->lock); - - return ret; -} - -struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id) -{ - struct ion_handle *handle; - - handle = idr_find(&client->idr, id); - if (handle) - ion_handle_get(handle); - - return handle ? handle : ERR_PTR(-EINVAL); -} - -struct ion_handle *ion_handle_get_by_id(struct ion_client *client, - int id) -{ - struct ion_handle *handle; - - mutex_lock(&client->lock); - handle = ion_handle_get_by_id_nolock(client, id); - mutex_unlock(&client->lock); - - return handle; -} - -static bool ion_handle_validate(struct ion_client *client, - struct ion_handle *handle) -{ - WARN_ON(!mutex_is_locked(&client->lock)); - return idr_find(&client->idr, handle->id) == handle; -} - -static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) -{ - int id; - struct rb_node **p = &client->handles.rb_node; - struct rb_node *parent = NULL; - struct ion_handle *entry; - - id = idr_alloc(&client->idr, handle, 1, 0, GFP_KERNEL); - if (id < 0) - return id; - - handle->id = id; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_handle, node); - - if (handle->buffer < entry->buffer) - p = &(*p)->rb_left; - else if (handle->buffer > entry->buffer) - p = &(*p)->rb_right; - else - WARN(1, "%s: buffer already found.", __func__); - } - - rb_link_node(&handle->node, parent, p); - rb_insert_color(&handle->node, &client->handles); - - return 0; -} - -struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - unsigned int heap_id_mask, - unsigned int flags) -{ - struct ion_handle *handle; - struct ion_device *dev = client->dev; - struct ion_buffer *buffer = NULL; - struct ion_heap *heap; - int ret; - - pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, - len, heap_id_mask, flags); - /* - * traverse the list of heaps available in this system in priority - * order. If the heap type is supported by the client, and matches the - * request of the caller allocate from it. Repeat until allocate has - * succeeded or all heaps have been tried - */ - len = PAGE_ALIGN(len); - - if (!len) - return ERR_PTR(-EINVAL); - - down_read(&dev->lock); - plist_for_each_entry(heap, &dev->heaps, node) { - /* if the caller didn't specify this heap id */ - if (!((1 << heap->id) & heap_id_mask)) - continue; - buffer = ion_buffer_create(heap, dev, len, flags); - if (!IS_ERR(buffer)) - break; - } - up_read(&dev->lock); - - if (buffer == NULL) - return ERR_PTR(-ENODEV); - - if (IS_ERR(buffer)) - return ERR_CAST(buffer); - - handle = ion_handle_create(client, buffer); - - /* - * ion_buffer_create will create a buffer with a ref_cnt of 1, - * and ion_handle_create will take a second reference, drop one here - */ - ion_buffer_put(buffer); - - if (IS_ERR(handle)) - return handle; - - mutex_lock(&client->lock); - ret = ion_handle_add(client, handle); - mutex_unlock(&client->lock); - if (ret) { - ion_handle_put(handle); - handle = ERR_PTR(ret); - } - - return handle; -} -EXPORT_SYMBOL(ion_alloc); - -void ion_free_nolock(struct ion_client *client, - struct ion_handle *handle) -{ - if (!ion_handle_validate(client, handle)) { - WARN(1, "%s: invalid handle passed to free.\n", __func__); - return; - } - ion_handle_put_nolock(handle); -} - -void ion_free(struct ion_client *client, struct ion_handle *handle) -{ - BUG_ON(client != handle->client); - - mutex_lock(&client->lock); - ion_free_nolock(client, handle); - mutex_unlock(&client->lock); -} -EXPORT_SYMBOL(ion_free); - static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { void *vaddr; @@ -433,234 +182,6 @@ static void ion_buffer_kmap_put(struct ion_buffer *buffer) } }
-static void ion_handle_kmap_put(struct ion_handle *handle) -{ - struct ion_buffer *buffer = handle->buffer; - - if (!handle->kmap_cnt) { - WARN(1, "%s: Double unmap detected! bailing...\n", __func__); - return; - } - handle->kmap_cnt--; - if (!handle->kmap_cnt) - ion_buffer_kmap_put(buffer); -} - -static struct mutex debugfs_mutex; -static struct rb_root *ion_root_client; -static int is_client_alive(struct ion_client *client) -{ - struct rb_node *node; - struct ion_client *tmp; - struct ion_device *dev; - - node = ion_root_client->rb_node; - dev = container_of(ion_root_client, struct ion_device, clients); - - down_read(&dev->lock); - while (node) { - tmp = rb_entry(node, struct ion_client, node); - if (client < tmp) { - node = node->rb_left; - } else if (client > tmp) { - node = node->rb_right; - } else { - up_read(&dev->lock); - return 1; - } - } - - up_read(&dev->lock); - return 0; -} - -static int ion_debug_client_show(struct seq_file *s, void *unused) -{ - struct ion_client *client = s->private; - struct rb_node *n; - size_t sizes[ION_NUM_HEAP_IDS] = {0}; - const char *names[ION_NUM_HEAP_IDS] = {NULL}; - int i; - - mutex_lock(&debugfs_mutex); - if (!is_client_alive(client)) { - seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n", - client); - mutex_unlock(&debugfs_mutex); - return 0; - } - - mutex_lock(&client->lock); - for (n = rb_first(&client->handles); n; n = rb_next(n)) { - struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); - unsigned int id = handle->buffer->heap->id; - - if (!names[id]) - names[id] = handle->buffer->heap->name; - sizes[id] += handle->buffer->size; - } - mutex_unlock(&client->lock); - mutex_unlock(&debugfs_mutex); - - seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes"); - for (i = 0; i < ION_NUM_HEAP_IDS; i++) { - if (!names[i]) - continue; - seq_printf(s, "%16.16s: %16zu\n", names[i], sizes[i]); - } - return 0; -} - -static int ion_debug_client_open(struct inode *inode, struct file *file) -{ - return single_open(file, ion_debug_client_show, inode->i_private); -} - -static const struct file_operations debug_client_fops = { - .open = ion_debug_client_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int ion_get_client_serial(const struct rb_root *root, - const unsigned char *name) -{ - int serial = -1; - struct rb_node *node; - - for (node = rb_first(root); node; node = rb_next(node)) { - struct ion_client *client = rb_entry(node, struct ion_client, - node); - - if (strcmp(client->name, name)) - continue; - serial = max(serial, client->display_serial); - } - return serial + 1; -} - -struct ion_client *ion_client_create(struct ion_device *dev, - const char *name) -{ - struct ion_client *client; - struct task_struct *task; - struct rb_node **p; - struct rb_node *parent = NULL; - struct ion_client *entry; - pid_t pid; - - if (!name) { - pr_err("%s: Name cannot be null\n", __func__); - return ERR_PTR(-EINVAL); - } - - get_task_struct(current->group_leader); - task_lock(current->group_leader); - pid = task_pid_nr(current->group_leader); - /* - * don't bother to store task struct for kernel threads, - * they can't be killed anyway - */ - if (current->group_leader->flags & PF_KTHREAD) { - put_task_struct(current->group_leader); - task = NULL; - } else { - task = current->group_leader; - } - task_unlock(current->group_leader); - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - goto err_put_task_struct; - - client->dev = dev; - client->handles = RB_ROOT; - idr_init(&client->idr); - mutex_init(&client->lock); - client->task = task; - client->pid = pid; - client->name = kstrdup(name, GFP_KERNEL); - if (!client->name) - goto err_free_client; - - down_write(&dev->lock); - client->display_serial = ion_get_client_serial(&dev->clients, name); - client->display_name = kasprintf( - GFP_KERNEL, "%s-%d", name, client->display_serial); - if (!client->display_name) { - up_write(&dev->lock); - goto err_free_client_name; - } - p = &dev->clients.rb_node; - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_client, node); - - if (client < entry) - p = &(*p)->rb_left; - else if (client > entry) - p = &(*p)->rb_right; - } - rb_link_node(&client->node, parent, p); - rb_insert_color(&client->node, &dev->clients); - - client->debug_root = debugfs_create_file(client->display_name, 0664, - dev->clients_debug_root, - client, &debug_client_fops); - if (!client->debug_root) { - char buf[256], *path; - - path = dentry_path(dev->clients_debug_root, buf, 256); - pr_err("Failed to create client debugfs at %s/%s\n", - path, client->display_name); - } - - up_write(&dev->lock); - - return client; - -err_free_client_name: - kfree(client->name); -err_free_client: - kfree(client); -err_put_task_struct: - if (task) - put_task_struct(current->group_leader); - return ERR_PTR(-ENOMEM); -} -EXPORT_SYMBOL(ion_client_create); - -void ion_client_destroy(struct ion_client *client) -{ - struct ion_device *dev = client->dev; - struct rb_node *n; - - pr_debug("%s: %d\n", __func__, __LINE__); - mutex_lock(&debugfs_mutex); - while ((n = rb_first(&client->handles))) { - struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); - ion_handle_destroy(&handle->ref); - } - - idr_destroy(&client->idr); - - down_write(&dev->lock); - if (client->task) - put_task_struct(client->task); - rb_erase(&client->node, &dev->clients); - debugfs_remove_recursive(client->debug_root); - up_write(&dev->lock); - - kfree(client->display_name); - kfree(client->name); - kfree(client); - mutex_unlock(&debugfs_mutex); -} -EXPORT_SYMBOL(ion_client_destroy); - static struct sg_table *dup_sg_table(struct sg_table *table) { struct sg_table *new_table; @@ -802,7 +323,7 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) { struct ion_buffer *buffer = dmabuf->priv;
- ion_buffer_put(buffer); + _ion_buffer_destroy(buffer); }
static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) @@ -881,24 +402,44 @@ static const struct dma_buf_ops dma_buf_ops = { .kunmap = ion_dma_buf_kunmap, };
-struct dma_buf *ion_share_dma_buf(struct ion_client *client, - struct ion_handle *handle) +int 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); - struct ion_buffer *buffer; + int fd; struct dma_buf *dmabuf; - bool valid_handle;
- mutex_lock(&client->lock); - valid_handle = ion_handle_validate(client, handle); - if (!valid_handle) { - WARN(1, "%s: invalid handle passed to share.\n", __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); + pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, + len, heap_id_mask, flags); + /* + * traverse the list of heaps available in this system in priority + * order. If the heap type is supported by the client, and matches the + * request of the caller allocate from it. Repeat until allocate has + * succeeded or all heaps have been tried + */ + len = PAGE_ALIGN(len); + + if (!len) + return -EINVAL; + + down_read(&dev->lock); + plist_for_each_entry(heap, &dev->heaps, node) { + /* if the caller didn't specify this heap id */ + if (!((1 << heap->id) & heap_id_mask)) + continue; + buffer = ion_buffer_create(heap, dev, len, flags); + if (!IS_ERR(buffer)) + break; } - buffer = handle->buffer; - ion_buffer_get(buffer); - mutex_unlock(&client->lock); + up_read(&dev->lock); + + if (buffer == NULL) + return -ENODEV; + + if (IS_ERR(buffer)) + return PTR_ERR(buffer);
exp_info.ops = &dma_buf_ops; exp_info.size = buffer->size; @@ -907,22 +448,9 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client,
dmabuf = dma_buf_export(&exp_info); if (IS_ERR(dmabuf)) { - ion_buffer_put(buffer); - return dmabuf; - } - - return dmabuf; -} -EXPORT_SYMBOL(ion_share_dma_buf); - -int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) -{ - struct dma_buf *dmabuf; - int fd; - - dmabuf = ion_share_dma_buf(client, handle); - if (IS_ERR(dmabuf)) + _ion_buffer_destroy(buffer); return PTR_ERR(dmabuf); + }
fd = dma_buf_fd(dmabuf, O_CLOEXEC); if (fd < 0) @@ -930,11 +458,10 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
return fd; } -EXPORT_SYMBOL(ion_share_dma_buf_fd);
-int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) +int ion_query_heaps(struct ion_heap_query *query) { - struct ion_device *dev = client->dev; + struct ion_device *dev = internal_dev; struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps); int ret = -EINVAL, cnt = 0, max_cnt; struct ion_heap *heap; @@ -976,137 +503,14 @@ int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) return ret; }
-static int ion_release(struct inode *inode, struct file *file) -{ - struct ion_client *client = file->private_data; - - pr_debug("%s: %d\n", __func__, __LINE__); - ion_client_destroy(client); - return 0; -} - -static int ion_open(struct inode *inode, struct file *file) -{ - struct miscdevice *miscdev = file->private_data; - struct ion_device *dev = container_of(miscdev, struct ion_device, dev); - struct ion_client *client; - char debug_name[64]; - - pr_debug("%s: %d\n", __func__, __LINE__); - snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader)); - client = ion_client_create(dev, debug_name); - if (IS_ERR(client)) - return PTR_ERR(client); - file->private_data = client; - - return 0; -} - static const struct file_operations ion_fops = { .owner = THIS_MODULE, - .open = ion_open, - .release = ion_release, .unlocked_ioctl = ion_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ion_ioctl, #endif };
-static size_t ion_debug_heap_total(struct ion_client *client, - unsigned int id) -{ - size_t size = 0; - struct rb_node *n; - - mutex_lock(&client->lock); - for (n = rb_first(&client->handles); n; n = rb_next(n)) { - struct ion_handle *handle = rb_entry(n, - struct ion_handle, - node); - if (handle->buffer->heap->id == id) - size += handle->buffer->size; - } - mutex_unlock(&client->lock); - return size; -} - -static int ion_debug_heap_show(struct seq_file *s, void *unused) -{ - struct ion_heap *heap = s->private; - struct ion_device *dev = heap->dev; - struct rb_node *n; - size_t total_size = 0; - size_t total_orphaned_size = 0; - - seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size"); - seq_puts(s, "----------------------------------------------------\n"); - - mutex_lock(&debugfs_mutex); - for (n = rb_first(&dev->clients); n; n = rb_next(n)) { - struct ion_client *client = rb_entry(n, struct ion_client, - node); - size_t size = ion_debug_heap_total(client, heap->id); - - if (!size) - continue; - if (client->task) { - char task_comm[TASK_COMM_LEN]; - - get_task_comm(task_comm, client->task); - seq_printf(s, "%16s %16u %16zu\n", task_comm, - client->pid, size); - } else { - seq_printf(s, "%16s %16u %16zu\n", client->name, - client->pid, size); - } - } - mutex_unlock(&debugfs_mutex); - - seq_puts(s, "----------------------------------------------------\n"); - seq_puts(s, "orphaned allocations (info is from last known client):\n"); - mutex_lock(&dev->buffer_lock); - for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { - struct ion_buffer *buffer = rb_entry(n, struct ion_buffer, - node); - if (buffer->heap->id != heap->id) - continue; - total_size += buffer->size; - if (!buffer->handle_count) { - seq_printf(s, "%16s %16u %16zu %d %d\n", - buffer->task_comm, buffer->pid, - buffer->size, buffer->kmap_cnt, - kref_read(&buffer->ref)); - total_orphaned_size += buffer->size; - } - } - mutex_unlock(&dev->buffer_lock); - seq_puts(s, "----------------------------------------------------\n"); - seq_printf(s, "%16s %16zu\n", "total orphaned", - total_orphaned_size); - seq_printf(s, "%16s %16zu\n", "total ", total_size); - if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) - seq_printf(s, "%16s %16zu\n", "deferred free", - heap->free_list_size); - seq_puts(s, "----------------------------------------------------\n"); - - if (heap->debug_show) - heap->debug_show(heap, s, unused); - - return 0; -} - -static int ion_debug_heap_open(struct inode *inode, struct file *file) -{ - return single_open(file, ion_debug_heap_show, inode->i_private); -} - -static const struct file_operations debug_heap_fops = { - .open = ion_debug_heap_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static int debug_shrink_set(void *data, u64 val) { struct ion_heap *heap = data; @@ -1169,29 +573,18 @@ void ion_device_add_heap(struct ion_heap *heap) */ plist_node_init(&heap->node, -heap->id); plist_add(&heap->node, &dev->heaps); - debug_file = debugfs_create_file(heap->name, 0664, - dev->heaps_debug_root, heap, - &debug_heap_fops); - - if (!debug_file) { - char buf[256], *path; - - path = dentry_path(dev->heaps_debug_root, buf, 256); - pr_err("Failed to create heap debugfs at %s/%s\n", - path, heap->name); - }
if (heap->shrinker.count_objects && heap->shrinker.scan_objects) { char debug_name[64];
snprintf(debug_name, 64, "%s_shrink", heap->name); debug_file = debugfs_create_file( - debug_name, 0644, dev->heaps_debug_root, heap, + debug_name, 0644, dev->debug_root, heap, &debug_shrink_fops); if (!debug_file) { char buf[256], *path;
- path = dentry_path(dev->heaps_debug_root, buf, 256); + path = dentry_path(dev->debug_root, buf, 256); pr_err("Failed to create heap shrinker debugfs at %s/%s\n", path, debug_name); } @@ -1227,24 +620,12 @@ int ion_device_create(void) pr_err("ion: failed to create debugfs root directory.\n"); goto debugfs_done; } - idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root); - if (!idev->heaps_debug_root) { - pr_err("ion: failed to create debugfs heaps directory.\n"); - goto debugfs_done; - } - idev->clients_debug_root = debugfs_create_dir("clients", - idev->debug_root); - if (!idev->clients_debug_root) - pr_err("ion: failed to create debugfs clients directory.\n");
debugfs_done: idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); - idev->clients = RB_ROOT; - ion_root_client = &idev->clients; - mutex_init(&debugfs_mutex); internal_dev = idev; return 0; } diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 36a1587..ace8416 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -78,7 +78,6 @@ struct ion_platform_heap { * handle, used for debugging */ struct ion_buffer { - struct kref ref; union { struct rb_node node; struct list_head list; @@ -109,8 +108,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer); * @buffers: an rb tree of all the existing buffers * @buffer_lock: lock protecting the tree of buffers * @lock: rwsem protecting the tree of heaps and clients - * @heaps: list of all the heaps in the system - * @user_clients: list of all the clients created from userspace */ struct ion_device { struct miscdevice dev; @@ -118,65 +115,11 @@ struct ion_device { struct mutex buffer_lock; struct rw_semaphore lock; struct plist_head heaps; - struct rb_root clients; struct dentry *debug_root; - struct dentry *heaps_debug_root; - struct dentry *clients_debug_root; int heap_cnt; };
/** - * struct ion_client - a process/hw block local address space - * @node: node in the tree of all clients - * @dev: backpointer to ion device - * @handles: an rb tree of all the handles in this client - * @idr: an idr space for allocating handle ids - * @lock: lock protecting the tree of handles - * @name: used for debugging - * @display_name: used for debugging (unique version of @name) - * @display_serial: used for debugging (to make display_name unique) - * @task: used for debugging - * - * A client represents a list of buffers this client may access. - * The mutex stored here is used to protect both handles tree - * as well as the handles themselves, and should be held while modifying either. - */ -struct ion_client { - struct rb_node node; - struct ion_device *dev; - struct rb_root handles; - struct idr idr; - struct mutex lock; - const char *name; - char *display_name; - int display_serial; - struct task_struct *task; - pid_t pid; - struct dentry *debug_root; -}; - -/** - * ion_handle - a client local reference to a buffer - * @ref: reference count - * @client: back pointer to the client the buffer resides in - * @buffer: pointer to the buffer - * @node: node in the client's handle rbtree - * @kmap_cnt: count of times this client has mapped to kernel - * @id: client-unique id allocated by client->idr - * - * Modifications to node, map_cnt or mapping should be protected by the - * lock in the client. Other fields are never changed after initialization. - */ -struct ion_handle { - struct kref ref; - struct ion_client *client; - struct ion_buffer *buffer; - struct rb_node node; - unsigned int kmap_cnt; - int id; -}; - -/** * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory * @free: free memory @@ -296,14 +239,10 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, int ion_heap_buffer_zero(struct ion_buffer *buffer); int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
-struct ion_handle *ion_alloc(struct ion_client *client, size_t len, +int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags);
-void ion_free(struct ion_client *client, struct ion_handle *handle); - -int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); - /** * ion_heap_init_shrinker * @heap: the heap @@ -431,18 +370,6 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id); - -void ion_free_nolock(struct ion_client *client, struct ion_handle *handle); - -int ion_handle_put_nolock(struct ion_handle *handle); - -struct ion_handle *ion_handle_get_by_id(struct ion_client *client, - int id); - -int ion_handle_put(struct ion_handle *handle); - -int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query); +int ion_query_heaps(struct ion_heap_query *query);
#endif /* _ION_H */ diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index bba1c47..b76db1b 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -85,31 +85,8 @@ struct ion_allocation_data { __u64 len; __u32 heap_id_mask; __u32 flags; - __u32 handle; - __u32 unused; -}; - -/** - * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair - * @handle: a handle - * @fd: a file descriptor representing that handle - * - * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with - * the handle returned from ion alloc, and the kernel returns the file - * descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace - * provides the file descriptor and the kernel returns the handle. - */ -struct ion_fd_data { - __u32 handle; __u32 fd; -}; - -/** - * struct ion_handle_data - a handle passed to/from the kernel - * @handle: a handle - */ -struct ion_handle_data { - __u32 handle; + __u32 unused; };
#define MAX_HEAP_NAME 32
On Tue, Apr 18, 2017 at 11:27:12AM -0700, Laura Abbott wrote:
ion_handle was introduced as an abstraction to represent a reference to a buffer via an ion_client. As frameworks outside of Ion evolved, the dmabuf emerged as the preferred standard for use in the kernel. This has made the ion_handle an unnecessary abstraction and prone to race conditions. ion_client is also now only used internally. We have enough mechanisms for race conditions and leaks already so just drop ion_handle and ion_client. This also includes ripping out most of the debugfs infrastructure since much of that was tied to clients and handles. The debugfs infrastructure was prone to give confusing data (orphaned allocations) so it can be replaced with something better if people actually want it.
Signed-off-by: Laura Abbott labbott@redhat.com
Yeah I think improving the dma-buf debugfs stuff (maybe with an allocator callback to dump additional data) is the better option.
Acked-by: Daniel Vetter daniel.vetter@ffwll.ch
drivers/staging/android/ion/ion-ioctl.c | 53 +-- drivers/staging/android/ion/ion.c | 701 ++------------------------------ drivers/staging/android/ion/ion.h | 77 +--- drivers/staging/android/uapi/ion.h | 25 +- 4 files changed, 51 insertions(+), 805 deletions(-)
diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 4e7bf16..76427e4 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -21,9 +21,7 @@ #include "ion.h" union ion_ioctl_arg {
- struct ion_fd_data fd; struct ion_allocation_data allocation;
- struct ion_handle_data handle; struct ion_heap_query query;
}; @@ -48,8 +46,6 @@ static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) static unsigned int ion_ioctl_dir(unsigned int cmd) { switch (cmd) {
- case ION_IOC_FREE:
default: return _IOC_DIR(cmd); }return _IOC_WRITE;
@@ -57,8 +53,6 @@ static unsigned int ion_ioctl_dir(unsigned int cmd) long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
- struct ion_client *client = filp->private_data;
- struct ion_handle *cleanup_handle = NULL; int ret = 0; unsigned int dir; union ion_ioctl_arg data;
@@ -86,61 +80,28 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case ION_IOC_ALLOC: {
struct ion_handle *handle;
int fd;
handle = ion_alloc(client, data.allocation.len,
fd = ion_alloc(data.allocation.len, data.allocation.heap_id_mask, data.allocation.flags);
if (IS_ERR(handle))
return PTR_ERR(handle);
if (fd < 0)
return fd;
data.allocation.handle = handle->id;
data.allocation.fd = fd;
cleanup_handle = handle;
break;
- }
- case ION_IOC_FREE:
- {
struct ion_handle *handle;
mutex_lock(&client->lock);
handle = ion_handle_get_by_id_nolock(client,
data.handle.handle);
if (IS_ERR(handle)) {
mutex_unlock(&client->lock);
return PTR_ERR(handle);
}
ion_free_nolock(client, handle);
ion_handle_put_nolock(handle);
mutex_unlock(&client->lock);
break;
- }
- case ION_IOC_SHARE:
- {
struct ion_handle *handle;
handle = ion_handle_get_by_id(client, data.handle.handle);
if (IS_ERR(handle))
return PTR_ERR(handle);
data.fd.fd = ion_share_dma_buf_fd(client, handle);
ion_handle_put(handle);
if (data.fd.fd < 0)
break; } case ION_IOC_HEAP_QUERY:ret = data.fd.fd;
ret = ion_query_heaps(client, &data.query);
break; default: return -ENOTTY; }ret = ion_query_heaps(&data.query);
if (dir & _IOC_READ) {
if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) {
if (cleanup_handle)
ion_free(client, cleanup_handle);
if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) return -EFAULT;
} return ret;}
} diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 5a82bea..9eeb06f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -90,7 +90,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->heap = heap; buffer->flags = flags;
- kref_init(&buffer->ref);
ret = heap->ops->allocate(heap, buffer, len, flags); @@ -140,9 +139,8 @@ void ion_buffer_destroy(struct ion_buffer *buffer) kfree(buffer); } -static void _ion_buffer_destroy(struct kref *kref) +static void _ion_buffer_destroy(struct ion_buffer *buffer) {
- struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); struct ion_heap *heap = buffer->heap; struct ion_device *dev = buffer->dev;
@@ -156,255 +154,6 @@ static void _ion_buffer_destroy(struct kref *kref) ion_buffer_destroy(buffer); } -static void ion_buffer_get(struct ion_buffer *buffer) -{
- kref_get(&buffer->ref);
-}
-static int ion_buffer_put(struct ion_buffer *buffer) -{
- return kref_put(&buffer->ref, _ion_buffer_destroy);
-}
-static void ion_buffer_add_to_handle(struct ion_buffer *buffer) -{
- mutex_lock(&buffer->lock);
- buffer->handle_count++;
- mutex_unlock(&buffer->lock);
-}
-static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) -{
- /*
* when a buffer is removed from a handle, if it is not in
* any other handles, copy the taskcomm and the pid of the
* process it's being removed from into the buffer. At this
* point there will be no way to track what processes this buffer is
* being used by, it only exists as a dma_buf file descriptor.
* The taskcomm and pid can provide a debug hint as to where this fd
* is in the system
*/
- mutex_lock(&buffer->lock);
- buffer->handle_count--;
- BUG_ON(buffer->handle_count < 0);
- if (!buffer->handle_count) {
struct task_struct *task;
task = current->group_leader;
get_task_comm(buffer->task_comm, task);
buffer->pid = task_pid_nr(task);
- }
- mutex_unlock(&buffer->lock);
-}
-static struct ion_handle *ion_handle_create(struct ion_client *client,
struct ion_buffer *buffer)
-{
- struct ion_handle *handle;
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle)
return ERR_PTR(-ENOMEM);
- kref_init(&handle->ref);
- RB_CLEAR_NODE(&handle->node);
- handle->client = client;
- ion_buffer_get(buffer);
- ion_buffer_add_to_handle(buffer);
- handle->buffer = buffer;
- return handle;
-}
-static void ion_handle_kmap_put(struct ion_handle *);
-static void ion_handle_destroy(struct kref *kref) -{
- struct ion_handle *handle = container_of(kref, struct ion_handle, ref);
- struct ion_client *client = handle->client;
- struct ion_buffer *buffer = handle->buffer;
- mutex_lock(&buffer->lock);
- while (handle->kmap_cnt)
ion_handle_kmap_put(handle);
- mutex_unlock(&buffer->lock);
- idr_remove(&client->idr, handle->id);
- if (!RB_EMPTY_NODE(&handle->node))
rb_erase(&handle->node, &client->handles);
- ion_buffer_remove_from_handle(buffer);
- ion_buffer_put(buffer);
- kfree(handle);
-}
-static void ion_handle_get(struct ion_handle *handle) -{
- kref_get(&handle->ref);
-}
-int ion_handle_put_nolock(struct ion_handle *handle) -{
- return kref_put(&handle->ref, ion_handle_destroy);
-}
-int ion_handle_put(struct ion_handle *handle) -{
- struct ion_client *client = handle->client;
- int ret;
- mutex_lock(&client->lock);
- ret = ion_handle_put_nolock(handle);
- mutex_unlock(&client->lock);
- return ret;
-}
-struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
int id)
-{
- struct ion_handle *handle;
- handle = idr_find(&client->idr, id);
- if (handle)
ion_handle_get(handle);
- return handle ? handle : ERR_PTR(-EINVAL);
-}
-struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
int id)
-{
- struct ion_handle *handle;
- mutex_lock(&client->lock);
- handle = ion_handle_get_by_id_nolock(client, id);
- mutex_unlock(&client->lock);
- return handle;
-}
-static bool ion_handle_validate(struct ion_client *client,
struct ion_handle *handle)
-{
- WARN_ON(!mutex_is_locked(&client->lock));
- return idr_find(&client->idr, handle->id) == handle;
-}
-static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) -{
- int id;
- struct rb_node **p = &client->handles.rb_node;
- struct rb_node *parent = NULL;
- struct ion_handle *entry;
- id = idr_alloc(&client->idr, handle, 1, 0, GFP_KERNEL);
- if (id < 0)
return id;
- handle->id = id;
- while (*p) {
parent = *p;
entry = rb_entry(parent, struct ion_handle, node);
if (handle->buffer < entry->buffer)
p = &(*p)->rb_left;
else if (handle->buffer > entry->buffer)
p = &(*p)->rb_right;
else
WARN(1, "%s: buffer already found.", __func__);
- }
- rb_link_node(&handle->node, parent, p);
- rb_insert_color(&handle->node, &client->handles);
- return 0;
-}
-struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
unsigned int heap_id_mask,
unsigned int flags)
-{
- struct ion_handle *handle;
- struct ion_device *dev = client->dev;
- struct ion_buffer *buffer = NULL;
- struct ion_heap *heap;
- int ret;
- pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__,
len, heap_id_mask, flags);
- /*
* traverse the list of heaps available in this system in priority
* order. If the heap type is supported by the client, and matches the
* request of the caller allocate from it. Repeat until allocate has
* succeeded or all heaps have been tried
*/
- len = PAGE_ALIGN(len);
- if (!len)
return ERR_PTR(-EINVAL);
- down_read(&dev->lock);
- plist_for_each_entry(heap, &dev->heaps, node) {
/* if the caller didn't specify this heap id */
if (!((1 << heap->id) & heap_id_mask))
continue;
buffer = ion_buffer_create(heap, dev, len, flags);
if (!IS_ERR(buffer))
break;
- }
- up_read(&dev->lock);
- if (buffer == NULL)
return ERR_PTR(-ENODEV);
- if (IS_ERR(buffer))
return ERR_CAST(buffer);
- handle = ion_handle_create(client, buffer);
- /*
* ion_buffer_create will create a buffer with a ref_cnt of 1,
* and ion_handle_create will take a second reference, drop one here
*/
- ion_buffer_put(buffer);
- if (IS_ERR(handle))
return handle;
- mutex_lock(&client->lock);
- ret = ion_handle_add(client, handle);
- mutex_unlock(&client->lock);
- if (ret) {
ion_handle_put(handle);
handle = ERR_PTR(ret);
- }
- return handle;
-} -EXPORT_SYMBOL(ion_alloc);
-void ion_free_nolock(struct ion_client *client,
struct ion_handle *handle)
-{
- if (!ion_handle_validate(client, handle)) {
WARN(1, "%s: invalid handle passed to free.\n", __func__);
return;
- }
- ion_handle_put_nolock(handle);
-}
-void ion_free(struct ion_client *client, struct ion_handle *handle) -{
- BUG_ON(client != handle->client);
- mutex_lock(&client->lock);
- ion_free_nolock(client, handle);
- mutex_unlock(&client->lock);
-} -EXPORT_SYMBOL(ion_free);
static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { void *vaddr; @@ -433,234 +182,6 @@ static void ion_buffer_kmap_put(struct ion_buffer *buffer) } } -static void ion_handle_kmap_put(struct ion_handle *handle) -{
- struct ion_buffer *buffer = handle->buffer;
- if (!handle->kmap_cnt) {
WARN(1, "%s: Double unmap detected! bailing...\n", __func__);
return;
- }
- handle->kmap_cnt--;
- if (!handle->kmap_cnt)
ion_buffer_kmap_put(buffer);
-}
-static struct mutex debugfs_mutex; -static struct rb_root *ion_root_client; -static int is_client_alive(struct ion_client *client) -{
- struct rb_node *node;
- struct ion_client *tmp;
- struct ion_device *dev;
- node = ion_root_client->rb_node;
- dev = container_of(ion_root_client, struct ion_device, clients);
- down_read(&dev->lock);
- while (node) {
tmp = rb_entry(node, struct ion_client, node);
if (client < tmp) {
node = node->rb_left;
} else if (client > tmp) {
node = node->rb_right;
} else {
up_read(&dev->lock);
return 1;
}
- }
- up_read(&dev->lock);
- return 0;
-}
-static int ion_debug_client_show(struct seq_file *s, void *unused) -{
- struct ion_client *client = s->private;
- struct rb_node *n;
- size_t sizes[ION_NUM_HEAP_IDS] = {0};
- const char *names[ION_NUM_HEAP_IDS] = {NULL};
- int i;
- mutex_lock(&debugfs_mutex);
- if (!is_client_alive(client)) {
seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n",
client);
mutex_unlock(&debugfs_mutex);
return 0;
- }
- mutex_lock(&client->lock);
- for (n = rb_first(&client->handles); n; n = rb_next(n)) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
node);
unsigned int id = handle->buffer->heap->id;
if (!names[id])
names[id] = handle->buffer->heap->name;
sizes[id] += handle->buffer->size;
- }
- mutex_unlock(&client->lock);
- mutex_unlock(&debugfs_mutex);
- seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes");
- for (i = 0; i < ION_NUM_HEAP_IDS; i++) {
if (!names[i])
continue;
seq_printf(s, "%16.16s: %16zu\n", names[i], sizes[i]);
- }
- return 0;
-}
-static int ion_debug_client_open(struct inode *inode, struct file *file) -{
- return single_open(file, ion_debug_client_show, inode->i_private);
-}
-static const struct file_operations debug_client_fops = {
- .open = ion_debug_client_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-static int ion_get_client_serial(const struct rb_root *root,
const unsigned char *name)
-{
- int serial = -1;
- struct rb_node *node;
- for (node = rb_first(root); node; node = rb_next(node)) {
struct ion_client *client = rb_entry(node, struct ion_client,
node);
if (strcmp(client->name, name))
continue;
serial = max(serial, client->display_serial);
- }
- return serial + 1;
-}
-struct ion_client *ion_client_create(struct ion_device *dev,
const char *name)
-{
- struct ion_client *client;
- struct task_struct *task;
- struct rb_node **p;
- struct rb_node *parent = NULL;
- struct ion_client *entry;
- pid_t pid;
- if (!name) {
pr_err("%s: Name cannot be null\n", __func__);
return ERR_PTR(-EINVAL);
- }
- get_task_struct(current->group_leader);
- task_lock(current->group_leader);
- pid = task_pid_nr(current->group_leader);
- /*
* don't bother to store task struct for kernel threads,
* they can't be killed anyway
*/
- if (current->group_leader->flags & PF_KTHREAD) {
put_task_struct(current->group_leader);
task = NULL;
- } else {
task = current->group_leader;
- }
- task_unlock(current->group_leader);
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (!client)
goto err_put_task_struct;
- client->dev = dev;
- client->handles = RB_ROOT;
- idr_init(&client->idr);
- mutex_init(&client->lock);
- client->task = task;
- client->pid = pid;
- client->name = kstrdup(name, GFP_KERNEL);
- if (!client->name)
goto err_free_client;
- down_write(&dev->lock);
- client->display_serial = ion_get_client_serial(&dev->clients, name);
- client->display_name = kasprintf(
GFP_KERNEL, "%s-%d", name, client->display_serial);
- if (!client->display_name) {
up_write(&dev->lock);
goto err_free_client_name;
- }
- p = &dev->clients.rb_node;
- while (*p) {
parent = *p;
entry = rb_entry(parent, struct ion_client, node);
if (client < entry)
p = &(*p)->rb_left;
else if (client > entry)
p = &(*p)->rb_right;
- }
- rb_link_node(&client->node, parent, p);
- rb_insert_color(&client->node, &dev->clients);
- client->debug_root = debugfs_create_file(client->display_name, 0664,
dev->clients_debug_root,
client, &debug_client_fops);
- if (!client->debug_root) {
char buf[256], *path;
path = dentry_path(dev->clients_debug_root, buf, 256);
pr_err("Failed to create client debugfs at %s/%s\n",
path, client->display_name);
- }
- up_write(&dev->lock);
- return client;
-err_free_client_name:
- kfree(client->name);
-err_free_client:
- kfree(client);
-err_put_task_struct:
- if (task)
put_task_struct(current->group_leader);
- return ERR_PTR(-ENOMEM);
-} -EXPORT_SYMBOL(ion_client_create);
-void ion_client_destroy(struct ion_client *client) -{
- struct ion_device *dev = client->dev;
- struct rb_node *n;
- pr_debug("%s: %d\n", __func__, __LINE__);
- mutex_lock(&debugfs_mutex);
- while ((n = rb_first(&client->handles))) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
node);
ion_handle_destroy(&handle->ref);
- }
- idr_destroy(&client->idr);
- down_write(&dev->lock);
- if (client->task)
put_task_struct(client->task);
- rb_erase(&client->node, &dev->clients);
- debugfs_remove_recursive(client->debug_root);
- up_write(&dev->lock);
- kfree(client->display_name);
- kfree(client->name);
- kfree(client);
- mutex_unlock(&debugfs_mutex);
-} -EXPORT_SYMBOL(ion_client_destroy);
static struct sg_table *dup_sg_table(struct sg_table *table) { struct sg_table *new_table; @@ -802,7 +323,7 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) { struct ion_buffer *buffer = dmabuf->priv;
- ion_buffer_put(buffer);
- _ion_buffer_destroy(buffer);
} static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) @@ -881,24 +402,44 @@ static const struct dma_buf_ops dma_buf_ops = { .kunmap = ion_dma_buf_kunmap, }; -struct dma_buf *ion_share_dma_buf(struct ion_client *client,
struct ion_handle *handle)
+int 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);
- struct ion_buffer *buffer;
- int fd; struct dma_buf *dmabuf;
- bool valid_handle;
- mutex_lock(&client->lock);
- valid_handle = ion_handle_validate(client, handle);
- if (!valid_handle) {
WARN(1, "%s: invalid handle passed to share.\n", __func__);
mutex_unlock(&client->lock);
return ERR_PTR(-EINVAL);
- pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__,
len, heap_id_mask, flags);
- /*
* traverse the list of heaps available in this system in priority
* order. If the heap type is supported by the client, and matches the
* request of the caller allocate from it. Repeat until allocate has
* succeeded or all heaps have been tried
*/
- len = PAGE_ALIGN(len);
- if (!len)
return -EINVAL;
- down_read(&dev->lock);
- plist_for_each_entry(heap, &dev->heaps, node) {
/* if the caller didn't specify this heap id */
if (!((1 << heap->id) & heap_id_mask))
continue;
buffer = ion_buffer_create(heap, dev, len, flags);
if (!IS_ERR(buffer))
}break;
- buffer = handle->buffer;
- ion_buffer_get(buffer);
- mutex_unlock(&client->lock);
- up_read(&dev->lock);
- if (buffer == NULL)
return -ENODEV;
- if (IS_ERR(buffer))
return PTR_ERR(buffer);
exp_info.ops = &dma_buf_ops; exp_info.size = buffer->size; @@ -907,22 +448,9 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client, dmabuf = dma_buf_export(&exp_info); if (IS_ERR(dmabuf)) {
ion_buffer_put(buffer);
return dmabuf;
- }
- return dmabuf;
-} -EXPORT_SYMBOL(ion_share_dma_buf);
-int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) -{
- struct dma_buf *dmabuf;
- int fd;
- dmabuf = ion_share_dma_buf(client, handle);
- if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);_ion_buffer_destroy(buffer);
- }
fd = dma_buf_fd(dmabuf, O_CLOEXEC); if (fd < 0) @@ -930,11 +458,10 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) return fd; } -EXPORT_SYMBOL(ion_share_dma_buf_fd); -int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) +int ion_query_heaps(struct ion_heap_query *query) {
- struct ion_device *dev = client->dev;
- struct ion_device *dev = internal_dev; struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps); int ret = -EINVAL, cnt = 0, max_cnt; struct ion_heap *heap;
@@ -976,137 +503,14 @@ int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) return ret; } -static int ion_release(struct inode *inode, struct file *file) -{
- struct ion_client *client = file->private_data;
- pr_debug("%s: %d\n", __func__, __LINE__);
- ion_client_destroy(client);
- return 0;
-}
-static int ion_open(struct inode *inode, struct file *file) -{
- struct miscdevice *miscdev = file->private_data;
- struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
- struct ion_client *client;
- char debug_name[64];
- pr_debug("%s: %d\n", __func__, __LINE__);
- snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader));
- client = ion_client_create(dev, debug_name);
- if (IS_ERR(client))
return PTR_ERR(client);
- file->private_data = client;
- return 0;
-}
static const struct file_operations ion_fops = { .owner = THIS_MODULE,
- .open = ion_open,
- .release = ion_release, .unlocked_ioctl = ion_ioctl,
#ifdef CONFIG_COMPAT .compat_ioctl = ion_ioctl, #endif }; -static size_t ion_debug_heap_total(struct ion_client *client,
unsigned int id)
-{
- size_t size = 0;
- struct rb_node *n;
- mutex_lock(&client->lock);
- for (n = rb_first(&client->handles); n; n = rb_next(n)) {
struct ion_handle *handle = rb_entry(n,
struct ion_handle,
node);
if (handle->buffer->heap->id == id)
size += handle->buffer->size;
- }
- mutex_unlock(&client->lock);
- return size;
-}
-static int ion_debug_heap_show(struct seq_file *s, void *unused) -{
- struct ion_heap *heap = s->private;
- struct ion_device *dev = heap->dev;
- struct rb_node *n;
- size_t total_size = 0;
- size_t total_orphaned_size = 0;
- seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
- seq_puts(s, "----------------------------------------------------\n");
- mutex_lock(&debugfs_mutex);
- for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
struct ion_client *client = rb_entry(n, struct ion_client,
node);
size_t size = ion_debug_heap_total(client, heap->id);
if (!size)
continue;
if (client->task) {
char task_comm[TASK_COMM_LEN];
get_task_comm(task_comm, client->task);
seq_printf(s, "%16s %16u %16zu\n", task_comm,
client->pid, size);
} else {
seq_printf(s, "%16s %16u %16zu\n", client->name,
client->pid, size);
}
- }
- mutex_unlock(&debugfs_mutex);
- seq_puts(s, "----------------------------------------------------\n");
- seq_puts(s, "orphaned allocations (info is from last known client):\n");
- mutex_lock(&dev->buffer_lock);
- for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
struct ion_buffer *buffer = rb_entry(n, struct ion_buffer,
node);
if (buffer->heap->id != heap->id)
continue;
total_size += buffer->size;
if (!buffer->handle_count) {
seq_printf(s, "%16s %16u %16zu %d %d\n",
buffer->task_comm, buffer->pid,
buffer->size, buffer->kmap_cnt,
kref_read(&buffer->ref));
total_orphaned_size += buffer->size;
}
- }
- mutex_unlock(&dev->buffer_lock);
- seq_puts(s, "----------------------------------------------------\n");
- seq_printf(s, "%16s %16zu\n", "total orphaned",
total_orphaned_size);
- seq_printf(s, "%16s %16zu\n", "total ", total_size);
- if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
seq_printf(s, "%16s %16zu\n", "deferred free",
heap->free_list_size);
- seq_puts(s, "----------------------------------------------------\n");
- if (heap->debug_show)
heap->debug_show(heap, s, unused);
- return 0;
-}
-static int ion_debug_heap_open(struct inode *inode, struct file *file) -{
- return single_open(file, ion_debug_heap_show, inode->i_private);
-}
-static const struct file_operations debug_heap_fops = {
- .open = ion_debug_heap_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
static int debug_shrink_set(void *data, u64 val) { struct ion_heap *heap = data; @@ -1169,29 +573,18 @@ void ion_device_add_heap(struct ion_heap *heap) */ plist_node_init(&heap->node, -heap->id); plist_add(&heap->node, &dev->heaps);
- debug_file = debugfs_create_file(heap->name, 0664,
dev->heaps_debug_root, heap,
&debug_heap_fops);
- if (!debug_file) {
char buf[256], *path;
path = dentry_path(dev->heaps_debug_root, buf, 256);
pr_err("Failed to create heap debugfs at %s/%s\n",
path, heap->name);
- }
if (heap->shrinker.count_objects && heap->shrinker.scan_objects) { char debug_name[64]; snprintf(debug_name, 64, "%s_shrink", heap->name); debug_file = debugfs_create_file(
debug_name, 0644, dev->heaps_debug_root, heap,
if (!debug_file) { char buf[256], *path;debug_name, 0644, dev->debug_root, heap, &debug_shrink_fops);
path = dentry_path(dev->heaps_debug_root, buf, 256);
}path = dentry_path(dev->debug_root, buf, 256); pr_err("Failed to create heap shrinker debugfs at %s/%s\n", path, debug_name);
@@ -1227,24 +620,12 @@ int ion_device_create(void) pr_err("ion: failed to create debugfs root directory.\n"); goto debugfs_done; }
- idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root);
- if (!idev->heaps_debug_root) {
pr_err("ion: failed to create debugfs heaps directory.\n");
goto debugfs_done;
- }
- idev->clients_debug_root = debugfs_create_dir("clients",
idev->debug_root);
- if (!idev->clients_debug_root)
pr_err("ion: failed to create debugfs clients directory.\n");
debugfs_done: idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); plist_head_init(&idev->heaps);
- idev->clients = RB_ROOT;
- ion_root_client = &idev->clients;
- mutex_init(&debugfs_mutex); internal_dev = idev; return 0;
} diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 36a1587..ace8416 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -78,7 +78,6 @@ struct ion_platform_heap {
handle, used for debugging
*/ struct ion_buffer {
- struct kref ref; union { struct rb_node node; struct list_head list;
@@ -109,8 +108,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer);
- @buffers: an rb tree of all the existing buffers
- @buffer_lock: lock protecting the tree of buffers
- @lock: rwsem protecting the tree of heaps and clients
- @heaps: list of all the heaps in the system
*/
- @user_clients: list of all the clients created from userspace
struct ion_device { struct miscdevice dev; @@ -118,65 +115,11 @@ struct ion_device { struct mutex buffer_lock; struct rw_semaphore lock; struct plist_head heaps;
- struct rb_root clients; struct dentry *debug_root;
- struct dentry *heaps_debug_root;
- struct dentry *clients_debug_root; int heap_cnt;
}; /**
- struct ion_client - a process/hw block local address space
- @node: node in the tree of all clients
- @dev: backpointer to ion device
- @handles: an rb tree of all the handles in this client
- @idr: an idr space for allocating handle ids
- @lock: lock protecting the tree of handles
- @name: used for debugging
- @display_name: used for debugging (unique version of @name)
- @display_serial: used for debugging (to make display_name unique)
- @task: used for debugging
- A client represents a list of buffers this client may access.
- The mutex stored here is used to protect both handles tree
- as well as the handles themselves, and should be held while modifying either.
- */
-struct ion_client {
- struct rb_node node;
- struct ion_device *dev;
- struct rb_root handles;
- struct idr idr;
- struct mutex lock;
- const char *name;
- char *display_name;
- int display_serial;
- struct task_struct *task;
- pid_t pid;
- struct dentry *debug_root;
-};
-/**
- ion_handle - a client local reference to a buffer
- @ref: reference count
- @client: back pointer to the client the buffer resides in
- @buffer: pointer to the buffer
- @node: node in the client's handle rbtree
- @kmap_cnt: count of times this client has mapped to kernel
- @id: client-unique id allocated by client->idr
- Modifications to node, map_cnt or mapping should be protected by the
- lock in the client. Other fields are never changed after initialization.
- */
-struct ion_handle {
- struct kref ref;
- struct ion_client *client;
- struct ion_buffer *buffer;
- struct rb_node node;
- unsigned int kmap_cnt;
- int id;
-};
-/**
- struct ion_heap_ops - ops to operate on a given heap
- @allocate: allocate memory
- @free: free memory
@@ -296,14 +239,10 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, int ion_heap_buffer_zero(struct ion_buffer *buffer); int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); -struct ion_handle *ion_alloc(struct ion_client *client, size_t len, +int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags); -void ion_free(struct ion_client *client, struct ion_handle *handle);
-int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle);
/**
- ion_heap_init_shrinker
- @heap: the heap
@@ -431,18 +370,6 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
int id);
-void ion_free_nolock(struct ion_client *client, struct ion_handle *handle);
-int ion_handle_put_nolock(struct ion_handle *handle);
-struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
int id);
-int ion_handle_put(struct ion_handle *handle);
-int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query); +int ion_query_heaps(struct ion_heap_query *query); #endif /* _ION_H */ diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index bba1c47..b76db1b 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -85,31 +85,8 @@ struct ion_allocation_data { __u64 len; __u32 heap_id_mask; __u32 flags;
- __u32 handle;
- __u32 unused;
-};
-/**
- struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair
- @handle: a handle
- @fd: a file descriptor representing that handle
- For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with
- the handle returned from ion alloc, and the kernel returns the file
- descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace
- provides the file descriptor and the kernel returns the handle.
- */
-struct ion_fd_data {
- __u32 handle; __u32 fd;
-};
-/**
- struct ion_handle_data - a handle passed to/from the kernel
- @handle: a handle
- */
-struct ion_handle_data {
- __u32 handle;
- __u32 unused;
};
#define MAX_HEAP_NAME 32
2.7.4
Linaro-mm-sig mailing list Linaro-mm-sig@lists.linaro.org https://lists.linaro.org/mailman/listinfo/linaro-mm-sig
This never got set in the ioctl. Properly set a return value of 0 on success.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/ion/ion.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 9eeb06f..d6fd350 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -498,6 +498,7 @@ int ion_query_heaps(struct ion_heap_query *query) }
query->cnt = cnt; + ret = 0; out: up_read(&dev->lock); return ret;
Most of the items have been taken care of by a clean up series. Remove the completed items and add a few new ones.
Signed-off-by: Laura Abbott labbott@redhat.com --- drivers/staging/android/TODO | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index 8f3ac37..5f14247 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO @@ -7,23 +7,10 @@ TODO:
ion/ - - Remove ION_IOC_SYNC: Flushing for devices should be purely a kernel internal - interface on top of dma-buf. flush_for_device needs to be added to dma-buf - first. - - Remove ION_IOC_CUSTOM: Atm used for cache flushing for cpu access in some - vendor trees. Should be replaced with an ioctl on the dma-buf to expose the - begin/end_cpu_access hooks to userspace. - - Clarify the tricks ion plays with explicitly managing coherency behind the - dma api's back (this is absolutely needed for high-perf gpu drivers): Add an - explicit coherency management mode to flush_for_device to be used by drivers - which want to manage caches themselves and which indicates whether cpu caches - need flushing. - - With those removed there's probably no use for ION_IOC_IMPORT anymore either - since ion would just be the central allocator for shared buffers. - - Add dt-binding to expose cma regions as ion heaps, with the rule that any - such cma regions must already be used by some device for dma. I.e. ion only - exposes existing cma regions and doesn't reserve unecessarily memory when - booting a system which doesn't use ion. + - Add dt-bindings for remaining heaps (chunk and carveout heaps). This would + involve putting appropriate bindings in a memory node for Ion to find. + - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0) + - Better test framework (integration with VGEM was suggested)
Please send patches to Greg Kroah-Hartman greg@kroah.com and Cc: Arve Hjønnevåg arve@android.com and Riley Andrews riandrews@android.com
On Tue, Apr 18, 2017 at 11:27:14AM -0700, Laura Abbott wrote:
Most of the items have been taken care of by a clean up series. Remove the completed items and add a few new ones.
Signed-off-by: Laura Abbott labbott@redhat.com
drivers/staging/android/TODO | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index 8f3ac37..5f14247 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO @@ -7,23 +7,10 @@ TODO: ion/
- Remove ION_IOC_SYNC: Flushing for devices should be purely a kernel internal
- interface on top of dma-buf. flush_for_device needs to be added to dma-buf
- first.
- Remove ION_IOC_CUSTOM: Atm used for cache flushing for cpu access in some
- vendor trees. Should be replaced with an ioctl on the dma-buf to expose the
- begin/end_cpu_access hooks to userspace.
- Clarify the tricks ion plays with explicitly managing coherency behind the
- dma api's back (this is absolutely needed for high-perf gpu drivers): Add an
- explicit coherency management mode to flush_for_device to be used by drivers
- which want to manage caches themselves and which indicates whether cpu caches
- need flushing.
- With those removed there's probably no use for ION_IOC_IMPORT anymore either
- since ion would just be the central allocator for shared buffers.
- Add dt-binding to expose cma regions as ion heaps, with the rule that any
- such cma regions must already be used by some device for dma. I.e. ion only
- exposes existing cma regions and doesn't reserve unecessarily memory when
- booting a system which doesn't use ion.
- Add dt-bindings for remaining heaps (chunk and carveout heaps). This would
- involve putting appropriate bindings in a memory node for Ion to find.
- Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0)
- Better test framework (integration with VGEM was suggested)
Found another one: Integrate the ion kernel-doc into Documenation/gpu/ion.rst and link it up within Documenation/gpu/index.rst. There's a lot of api and overview stuff already around, would be great to make this more accessible.
But I wouldn't put this as a de-staging blocker, just an idea.
On the series: Acked-by: Daniel Vetter daniel.vetter@ffwll.ch
No full review since a bunch of stuff I'm not too familiar with, but I like where this is going. -Daniel
Please send patches to Greg Kroah-Hartman greg@kroah.com and Cc: Arve Hjønnevåg arve@android.com and Riley Andrews riandrews@android.com -- 2.7.4
Linaro-mm-sig mailing list Linaro-mm-sig@lists.linaro.org https://lists.linaro.org/mailman/listinfo/linaro-mm-sig
Hi Daniel,
On Wednesday 19 Apr 2017 10:36:55 Daniel Vetter wrote:
On Tue, Apr 18, 2017 at 11:27:14AM -0700, Laura Abbott wrote:
Most of the items have been taken care of by a clean up series. Remove the completed items and add a few new ones.
Signed-off-by: Laura Abbott labbott@redhat.com
drivers/staging/android/TODO | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index 8f3ac37..5f14247 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO
@@ -7,23 +7,10 @@ TODO: ion/
- Remove ION_IOC_SYNC: Flushing for devices should be purely a kernel
internal - interface on top of dma-buf. flush_for_device needs to be added to dma-buf - first.
- Remove ION_IOC_CUSTOM: Atm used for cache flushing for cpu access in
some - vendor trees. Should be replaced with an ioctl on the dma-buf to expose the - begin/end_cpu_access hooks to userspace.
- Clarify the tricks ion plays with explicitly managing coherency behind
the - dma api's back (this is absolutely needed for high-perf gpu drivers): Add an - explicit coherency management mode to flush_for_device to be used by drivers - which want to manage caches themselves and which indicates whether cpu caches - need flushing.
- With those removed there's probably no use for ION_IOC_IMPORT anymore
either - since ion would just be the central allocator for shared buffers. - - Add dt-binding to expose cma regions as ion heaps, with the rule that any - such cma regions must already be used by some device for dma. I.e. ion only - exposes existing cma regions and doesn't reserve unecessarily memory when - booting a system which doesn't use ion.
- Add dt-bindings for remaining heaps (chunk and carveout heaps). This
would + involve putting appropriate bindings in a memory node for Ion to find. + - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0)
- Better test framework (integration with VGEM was suggested)
Found another one: Integrate the ion kernel-doc into Documenation/gpu/ion.rst and link it up within Documenation/gpu/index.rst.
If ion is a generic-purpose allocator, should its documentation really reside in Documentation/gpu/ ?
There's a lot of api and overview stuff already around, would be great to make this more accessible.
But I wouldn't put this as a de-staging blocker, just an idea.
On the series: Acked-by: Daniel Vetter daniel.vetter@ffwll.ch
No full review since a bunch of stuff I'm not too familiar with, but I like where this is going. -Daniel
Please send patches to Greg Kroah-Hartman greg@kroah.com and Cc: Arve Hjønnevåg arve@android.com and Riley Andrews riandrews@android.com
Hi Laura,
Thanks much for this series!
On 18 April 2017 at 23:57, Laura Abbott labbott@redhat.com wrote:
Hi,
This is v4 of the series to cleanup to Ion. Greg took some of the patches that weren't CMA related already. There was a minor bisectability problem with the CMA APIs so this is a new version to address that. I also addressed some minor comments on the patch to collapse header files.
For the series, please feel free to apply my Acked-by: Sumit Semwal sumit.semwal@linaro.org
Thanks, Laura
Laura Abbott (12): cma: Store a name in the cma structure cma: Introduce cma_for_each_area staging: android: ion: Use CMA APIs directly staging: android: ion: Stop butchering the DMA address staging: android: ion: Break the ABI in the name of forward progress staging: android: ion: Get rid of ion_phys_addr_t staging: android: ion: Collapse internal header files staging: android: ion: Rework heap registration/enumeration staging: android: ion: Drop ion_map_kernel interface staging: android: ion: Remove ion_handle and ion_client staging: android: ion: Set query return value staging/android: Update Ion TODO list
arch/powerpc/kvm/book3s_hv_builtin.c | 3 +- drivers/base/dma-contiguous.c | 5 +- drivers/staging/android/TODO | 21 +- drivers/staging/android/ion/Kconfig | 32 + drivers/staging/android/ion/Makefile | 11 +- drivers/staging/android/ion/compat_ion.c | 152 ----- drivers/staging/android/ion/compat_ion.h | 29 - drivers/staging/android/ion/ion-ioctl.c | 55 +- drivers/staging/android/ion/ion.c | 812 ++---------------------- drivers/staging/android/ion/ion.h | 386 ++++++++--- drivers/staging/android/ion/ion_carveout_heap.c | 21 +- drivers/staging/android/ion/ion_chunk_heap.c | 16 +- drivers/staging/android/ion/ion_cma_heap.c | 120 ++-- drivers/staging/android/ion/ion_heap.c | 68 -- drivers/staging/android/ion/ion_page_pool.c | 3 +- drivers/staging/android/ion/ion_priv.h | 453 ------------- drivers/staging/android/ion/ion_system_heap.c | 39 +- drivers/staging/android/uapi/ion.h | 36 +- include/linux/cma.h | 6 +- mm/cma.c | 31 +- mm/cma.h | 1 + mm/cma_debug.c | 2 +- 22 files changed, 524 insertions(+), 1778 deletions(-) delete mode 100644 drivers/staging/android/ion/compat_ion.c delete mode 100644 drivers/staging/android/ion/compat_ion.h delete mode 100644 drivers/staging/android/ion/ion_priv.h
-- 2.7.4
linaro-mm-sig@lists.linaro.org