From 5d41593935d91d362a683a93ed3afd7c0293d97e Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Thu, 8 Aug 2019 07:52:27 -0700 Subject: [PATCH] staging: ion: refactor ion's heap manipulators into a separate file. This patch is preparatory work for making ion heaps modular. The patch itself doesn't make any significant changes except for re-organizing the heap manipulator functions in a single file. This will be helpful later when we specifically export some of these functions to be used by a heap module. Bug: 133508579 Test: ion-unit-tests Change-Id: I19205b4874a3bf52408f1fa14c3e145de1293fb4 Co-developed-by: Isaac J. Manjarres Signed-off-by: Sandeep Patil --- drivers/staging/android/ion/ion.h | 11 +- drivers/staging/android/ion/ion_buffer.c | 17 ++ drivers/staging/android/ion/ion_heap.c | 245 +++++++++--------- drivers/staging/android/ion/ion_private.h | 1 - drivers/staging/android/ion/ion_system_heap.c | 2 +- 5 files changed, 144 insertions(+), 132 deletions(-) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index ec20a9ea13f9..6b7727f5736e 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -155,6 +155,14 @@ struct ion_heap { */ void ion_device_add_heap(struct ion_heap *heap); +/* ion_buffer_zero - zeroes out an ion buffer respecting the ION_FLAGs. + * + * @buffer: ion_buffer to zero + * + * Returns 0 on success, negative error otherwise. + */ +int ion_buffer_zero(struct ion_buffer *buffer); + /** * some helpers for common operations on buffers using the sg_table * and vaddr fields @@ -163,8 +171,9 @@ 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); +int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, + pgprot_t pgprot); /** * ion_heap_init_shrinker diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c index c10ea6672f1a..50c2dbc3ebec 100644 --- a/drivers/staging/android/ion/ion_buffer.c +++ b/drivers/staging/android/ion/ion_buffer.c @@ -133,6 +133,23 @@ struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len, return buffer; } +int ion_buffer_zero(struct ion_buffer *buffer) +{ + struct sg_table *table; + pgprot_t pgprot; + + if (!buffer) + return -EINVAL; + + table = buffer->sg_table; + if (buffer->flags & ION_FLAG_CACHED) + pgprot = PAGE_KERNEL; + else + pgprot = pgprot_writecombine(PAGE_KERNEL); + + return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); +} + void ion_buffer_release(struct ion_buffer *buffer) { if (buffer->kmap_cnt > 0) { diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 3b4f32b9cd2d..39eb60e4842e 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -17,6 +17,120 @@ #include "ion_private.h" +static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, + struct shrink_control *sc) +{ + struct ion_heap *heap = container_of(shrinker, struct ion_heap, + shrinker); + int total = 0; + + total = ion_heap_freelist_size(heap) / PAGE_SIZE; + + if (heap->ops->shrink) + total += heap->ops->shrink(heap, sc->gfp_mask, 0); + + return total; +} + +static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, + struct shrink_control *sc) +{ + struct ion_heap *heap = container_of(shrinker, struct ion_heap, + shrinker); + int freed = 0; + int to_scan = sc->nr_to_scan; + + if (to_scan == 0) + return 0; + + /* + * shrink the free list first, no point in zeroing the memory if we're + * just going to reclaim it. Also, skip any possible page pooling. + */ + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) + freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) / + PAGE_SIZE; + + to_scan -= freed; + if (to_scan <= 0) + return freed; + + if (heap->ops->shrink) + freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan); + + return freed; +} + +static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) +{ + void *addr = vm_map_ram(pages, num, -1, pgprot); + + if (!addr) + return -ENOMEM; + memset(addr, 0, PAGE_SIZE * num); + vm_unmap_ram(addr, num); + + return 0; +} + +static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, + bool skip_pools) +{ + struct ion_buffer *buffer; + size_t total_drained = 0; + + if (ion_heap_freelist_size(heap) == 0) + return 0; + + spin_lock(&heap->free_lock); + if (size == 0) + size = heap->free_list_size; + + while (!list_empty(&heap->free_list)) { + if (total_drained >= size) + break; + buffer = list_first_entry(&heap->free_list, struct ion_buffer, + list); + list_del(&buffer->list); + heap->free_list_size -= buffer->size; + if (skip_pools) + buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; + total_drained += buffer->size; + spin_unlock(&heap->free_lock); + ion_buffer_release(buffer); + spin_lock(&heap->free_lock); + } + spin_unlock(&heap->free_lock); + + return total_drained; +} + +static int ion_heap_deferred_free(void *data) +{ + struct ion_heap *heap = data; + + while (true) { + struct ion_buffer *buffer; + + wait_event_freezable(heap->waitqueue, + ion_heap_freelist_size(heap) > 0); + + spin_lock(&heap->free_lock); + if (list_empty(&heap->free_list)) { + spin_unlock(&heap->free_lock); + continue; + } + buffer = list_first_entry(&heap->free_list, struct ion_buffer, + list); + list_del(&buffer->list); + heap->free_list_size -= buffer->size; + spin_unlock(&heap->free_lock); + ion_buffer_release(buffer); + } + + return 0; +} + void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { @@ -97,20 +211,8 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } -static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) -{ - void *addr = vm_map_ram(pages, num, -1, pgprot); - - if (!addr) - return -ENOMEM; - memset(addr, 0, PAGE_SIZE * num); - vm_unmap_ram(addr, num); - - return 0; -} - -static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, - pgprot_t pgprot) +int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, + pgprot_t pgprot) { int p = 0; int ret = 0; @@ -132,19 +234,6 @@ static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, return ret; } -int ion_heap_buffer_zero(struct ion_buffer *buffer) -{ - struct sg_table *table = buffer->sg_table; - pgprot_t pgprot; - - if (buffer->flags & ION_FLAG_CACHED) - pgprot = PAGE_KERNEL; - else - pgprot = pgprot_writecombine(PAGE_KERNEL); - - return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); -} - int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) { struct scatterlist sg; @@ -174,38 +263,6 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) return size; } -static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, - bool skip_pools) -{ - struct ion_buffer *buffer; - size_t total_drained = 0; - - if (ion_heap_freelist_size(heap) == 0) - return 0; - - spin_lock(&heap->free_lock); - if (size == 0) - size = heap->free_list_size; - - while (!list_empty(&heap->free_list)) { - if (total_drained >= size) - break; - buffer = list_first_entry(&heap->free_list, struct ion_buffer, - list); - list_del(&buffer->list); - heap->free_list_size -= buffer->size; - if (skip_pools) - buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; - total_drained += buffer->size; - spin_unlock(&heap->free_lock); - ion_buffer_release(buffer); - spin_lock(&heap->free_lock); - } - spin_unlock(&heap->free_lock); - - return total_drained; -} - size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) { return _ion_heap_freelist_drain(heap, size, false); @@ -216,32 +273,6 @@ size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size) return _ion_heap_freelist_drain(heap, size, true); } -static int ion_heap_deferred_free(void *data) -{ - struct ion_heap *heap = data; - - while (true) { - struct ion_buffer *buffer; - - wait_event_freezable(heap->waitqueue, - ion_heap_freelist_size(heap) > 0); - - spin_lock(&heap->free_lock); - if (list_empty(&heap->free_list)) { - spin_unlock(&heap->free_lock); - continue; - } - buffer = list_first_entry(&heap->free_list, struct ion_buffer, - list); - list_del(&buffer->list); - heap->free_list_size -= buffer->size; - spin_unlock(&heap->free_lock); - ion_buffer_release(buffer); - } - - return 0; -} - int ion_heap_init_deferred_free(struct ion_heap *heap) { struct sched_param param = { .sched_priority = 0 }; @@ -260,50 +291,6 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) return 0; } -static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, - struct shrink_control *sc) -{ - struct ion_heap *heap = container_of(shrinker, struct ion_heap, - shrinker); - int total = 0; - - total = ion_heap_freelist_size(heap) / PAGE_SIZE; - - if (heap->ops->shrink) - total += heap->ops->shrink(heap, sc->gfp_mask, 0); - - return total; -} - -static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, - struct shrink_control *sc) -{ - struct ion_heap *heap = container_of(shrinker, struct ion_heap, - shrinker); - int freed = 0; - int to_scan = sc->nr_to_scan; - - if (to_scan == 0) - return 0; - - /* - * shrink the free list first, no point in zeroing the memory if we're - * just going to reclaim it. Also, skip any possible page pooling. - */ - if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) - freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) / - PAGE_SIZE; - - to_scan -= freed; - if (to_scan <= 0) - return freed; - - if (heap->ops->shrink) - freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan); - - return freed; -} - int ion_heap_init_shrinker(struct ion_heap *heap) { heap->shrinker.count_objects = ion_heap_shrink_count; diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h index b3c8b55788db..9c8f482cd9d2 100644 --- a/drivers/staging/android/ion/ion_private.h +++ b/drivers/staging/android/ion/ion_private.h @@ -52,5 +52,4 @@ extern struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, unsigned int flags); extern int ion_free(struct ion_buffer *buffer); - #endif /* _ION_PRIVATE_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index fbf5f39c22db..66a2b8e8b51e 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -161,7 +161,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) /* zero the buffer before goto page pool */ if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) - ion_heap_buffer_zero(buffer); + ion_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) free_buffer_page(sys_heap, buffer, sg_page(sg));