diff options
Diffstat (limited to 'drivers/staging/android/ion/ion_system_heap.c')
-rw-r--r-- | drivers/staging/android/ion/ion_system_heap.c | 71 |
1 files changed, 24 insertions, 47 deletions
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index cb7ae08a5e24..6b77c5195b4d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -49,13 +49,7 @@ static inline unsigned int order_to_size(int order) struct ion_system_heap { struct ion_heap heap; - struct ion_page_pool **pools; -}; - -struct page_info { - struct page *page; - unsigned int order; - struct list_head list; + struct ion_page_pool *pools[0]; }; static struct page *alloc_buffer_page(struct ion_system_heap *heap, @@ -84,9 +78,9 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, } static void free_buffer_page(struct ion_system_heap *heap, - struct ion_buffer *buffer, struct page *page, - unsigned int order) + struct ion_buffer *buffer, struct page *page) { + unsigned int order = compound_order(page); bool cached = ion_buffer_cached(buffer); if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) { @@ -99,19 +93,14 @@ static void free_buffer_page(struct ion_system_heap *heap, } -static struct page_info *alloc_largest_available(struct ion_system_heap *heap, - struct ion_buffer *buffer, - unsigned long size, - unsigned int max_order) +static struct page *alloc_largest_available(struct ion_system_heap *heap, + struct ion_buffer *buffer, + unsigned long size, + unsigned int max_order) { struct page *page; - struct page_info *info; int i; - info = kmalloc(sizeof(struct page_info), GFP_KERNEL); - if (!info) - return NULL; - for (i = 0; i < num_orders; i++) { if (size < order_to_size(orders[i])) continue; @@ -122,11 +111,8 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, if (!page) continue; - info->page = page; - info->order = orders[i]; - return info; + return page; } - kfree(info); return NULL; } @@ -142,7 +128,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct sg_table *table; struct scatterlist *sg; struct list_head pages; - struct page_info *info, *tmp_info; + struct page *page, *tmp_page; int i = 0; unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; @@ -155,13 +141,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap, INIT_LIST_HEAD(&pages); while (size_remaining > 0) { - info = alloc_largest_available(sys_heap, buffer, size_remaining, + page = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); - if (!info) + if (!page) goto free_pages; - list_add_tail(&info->list, &pages); - size_remaining -= PAGE_SIZE << info->order; - max_order = info->order; + list_add_tail(&page->lru, &pages); + size_remaining -= PAGE_SIZE << compound_order(page); + max_order = compound_order(page); i++; } table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); @@ -172,12 +158,10 @@ static int ion_system_heap_allocate(struct ion_heap *heap, goto free_table; sg = table->sgl; - list_for_each_entry_safe(info, tmp_info, &pages, list) { - struct page *page = info->page; - sg_set_page(sg, page, PAGE_SIZE << info->order, 0); + list_for_each_entry_safe(page, tmp_page, &pages, lru) { + sg_set_page(sg, page, PAGE_SIZE << compound_order(page), 0); sg = sg_next(sg); - list_del(&info->list); - kfree(info); + list_del(&page->lru); } buffer->priv_virt = table; @@ -186,10 +170,8 @@ static int ion_system_heap_allocate(struct ion_heap *heap, free_table: kfree(table); free_pages: - list_for_each_entry_safe(info, tmp_info, &pages, list) { - free_buffer_page(sys_heap, buffer, info->page, info->order); - kfree(info); - } + list_for_each_entry_safe(page, tmp_page, &pages, lru) + free_buffer_page(sys_heap, buffer, page); return -ENOMEM; } @@ -209,8 +191,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) - free_buffer_page(sys_heap, buffer, sg_page(sg), - get_order(sg->length)); + free_buffer_page(sys_heap, buffer, sg_page(sg)); sg_free_table(table); kfree(table); } @@ -283,16 +264,15 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) struct ion_system_heap *heap; int i; - heap = kzalloc(sizeof(struct ion_system_heap), GFP_KERNEL); + heap = kzalloc(sizeof(struct ion_system_heap) + + sizeof(struct ion_page_pool *) * num_orders, + GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); heap->heap.ops = &system_heap_ops; heap->heap.type = ION_HEAP_TYPE_SYSTEM; heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - heap->pools = kzalloc(sizeof(struct ion_page_pool *) * num_orders, - GFP_KERNEL); - if (!heap->pools) - goto free_heap; + for (i = 0; i < num_orders; i++) { struct ion_page_pool *pool; gfp_t gfp_flags = low_order_gfp_flags; @@ -311,8 +291,6 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) destroy_pools: while (i--) ion_page_pool_destroy(heap->pools[i]); - kfree(heap->pools); -free_heap: kfree(heap); return ERR_PTR(-ENOMEM); } @@ -326,7 +304,6 @@ void ion_system_heap_destroy(struct ion_heap *heap) for (i = 0; i < num_orders; i++) ion_page_pool_destroy(sys_heap->pools[i]); - kfree(sys_heap->pools); kfree(sys_heap); } |