Loading drivers/staging/android/ion/heaps/ion_system_heap.c +55 −73 Original line number Diff line number Diff line Loading @@ -51,11 +51,6 @@ static inline unsigned int order_to_size(int order) return PAGE_SIZE << order; } struct pages_mem { struct page **pages; u32 size; }; int ion_heap_is_system_heap_type(enum ion_heap_type type) { return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM); Loading @@ -71,20 +66,57 @@ static struct page *alloc_buffer_page(struct ion_system_heap *sys_heap, struct ion_page_pool *pool; int vmid = get_secure_vmid(buffer->flags); struct device *dev = sys_heap->heap.dev; int order_ind = order_to_index(order); struct task_struct *worker; if (vmid > 0) pool = sys_heap->secure_pools[vmid][order_to_index(order)]; else if (!cached) pool = sys_heap->uncached_pools[order_to_index(order)]; else pool = sys_heap->cached_pools[order_to_index(order)]; if (vmid > 0) { pool = sys_heap->secure_pools[vmid][order_ind]; /* * We should skip stealing pages if (1) we're focing our * allocations to come from buddy; or (2) pool refilling is * disabled, in which case stealing pages could deplete the * uncached pools. */ if (!(*from_pool && pool_auto_refill_en)) goto normal_alloc; page = ion_page_pool_alloc_pool_only(pool); if (!IS_ERR(page)) return page; pool = sys_heap->uncached_pools[order_ind]; page = ion_page_pool_alloc_pool_only(pool); if (IS_ERR(page)) { pool = sys_heap->secure_pools[vmid][order_ind]; goto normal_alloc; } /* * Here, setting `from_pool = false` indicates that the * page didn't come from the secure pool, and causes * the page to be hyp-assigned. */ *from_pool = false; if (pool_auto_refill_en && pool->order && pool_count_below_lowmark(pool)) { worker = sys_heap->kworker[ION_KTHREAD_UNCACHED]; wake_up_process(worker); } return page; } else if (!cached) { pool = sys_heap->uncached_pools[order_ind]; } else { pool = sys_heap->cached_pools[order_ind]; } normal_alloc: page = ion_page_pool_alloc(pool, from_pool); if (pool_auto_refill_en && pool_count_below_lowmark(pool) && vmid <= 0) { if (pool_auto_refill_en && pool->order && pool_count_below_lowmark(pool) && vmid <= 0) wake_up_process(sys_heap->kworker[cached]); } if (IS_ERR(page)) return page; Loading Loading @@ -209,13 +241,11 @@ alloc_from_pool_preferred(struct ion_system_heap *heap, return alloc_largest_available(heap, buffer, size, max_order); } static unsigned int process_info(struct page_info *info, static void process_info(struct page_info *info, struct scatterlist *sg, struct scatterlist *sg_sync, struct pages_mem *data, unsigned int i) struct scatterlist *sg_sync) { struct page *page = info->page; unsigned int j; if (sg_sync) { sg_set_page(sg_sync, page, (1 << info->order) * PAGE_SIZE, 0); Loading @@ -228,45 +258,9 @@ static unsigned int process_info(struct page_info *info, * on the currently targeted hardware. */ sg_dma_address(sg) = page_to_phys(page); if (data) { for (j = 0; j < (1 << info->order); ++j) data->pages[i++] = nth_page(page, j); } list_del(&info->list); kfree(info); return i; } static int ion_heap_alloc_pages_mem(struct pages_mem *pages_mem) { struct page **pages; unsigned int page_tbl_size; page_tbl_size = sizeof(struct page *) * (pages_mem->size >> PAGE_SHIFT); if (page_tbl_size > SZ_8K) { /* * Do fallback to ensure we have a balance between * performance and availability. */ pages = kmalloc(page_tbl_size, __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN); if (!pages) pages = vmalloc(page_tbl_size); } else { pages = kmalloc(page_tbl_size, GFP_KERNEL); } if (!pages) return -ENOMEM; pages_mem->pages = pages; return 0; } static void ion_heap_free_pages_mem(struct pages_mem *pages_mem) { kvfree(pages_mem->pages); } static int ion_system_heap_allocate(struct ion_heap *heap, Loading @@ -287,7 +281,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, unsigned int nents_sync = 0; unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; struct pages_mem data; unsigned int sz; int vmid = get_secure_vmid(buffer->flags); Loading @@ -301,7 +294,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, return -EINVAL; } data.size = 0; INIT_LIST_HEAD(&pages); INIT_LIST_HEAD(&pages_from_pool); Loading @@ -326,7 +318,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, list_add_tail(&info->list, &pages_from_pool); } else { list_add_tail(&info->list, &pages); data.size += sz; ++nents_sync; } size_remaining -= sz; Loading @@ -334,15 +325,10 @@ static int ion_system_heap_allocate(struct ion_heap *heap, i++; } ret = ion_heap_alloc_pages_mem(&data); if (ret) goto err; table = kzalloc(sizeof(*table), GFP_KERNEL); if (!table) { ret = -ENOMEM; goto err_free_data_pages; goto err; } ret = sg_alloc_table(table, i, GFP_KERNEL); Loading @@ -355,7 +341,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, goto err_free_sg; } i = 0; sg = table->sgl; sg_sync = table_sync.sgl; Loading @@ -371,16 +356,16 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct page_info, list); if (info && tmp_info) { if (info->order >= tmp_info->order) { i = process_info(info, sg, sg_sync, &data, i); process_info(info, sg, sg_sync); sg_sync = sg_next(sg_sync); } else { i = process_info(tmp_info, sg, 0, 0, i); process_info(tmp_info, sg, NULL); } } else if (info) { i = process_info(info, sg, sg_sync, &data, i); process_info(info, sg, sg_sync); sg_sync = sg_next(sg_sync); } else if (tmp_info) { i = process_info(tmp_info, sg, 0, 0, i); process_info(tmp_info, sg, NULL); } sg = sg_next(sg); Loading @@ -397,7 +382,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, buffer->sg_table = table; if (nents_sync) sg_free_table(&table_sync); ion_heap_free_pages_mem(&data); ion_prepare_sgl_for_force_dma_sync(buffer->sg_table); return 0; Loading @@ -417,8 +401,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, sg_free_table(table); err1: kfree(table); err_free_data_pages: ion_heap_free_pages_mem(&data); err: list_for_each_entry_safe(info, tmp_info, &pages, list) { free_buffer_page(sys_heap, buffer, info->page, info->order); Loading Loading
drivers/staging/android/ion/heaps/ion_system_heap.c +55 −73 Original line number Diff line number Diff line Loading @@ -51,11 +51,6 @@ static inline unsigned int order_to_size(int order) return PAGE_SIZE << order; } struct pages_mem { struct page **pages; u32 size; }; int ion_heap_is_system_heap_type(enum ion_heap_type type) { return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM); Loading @@ -71,20 +66,57 @@ static struct page *alloc_buffer_page(struct ion_system_heap *sys_heap, struct ion_page_pool *pool; int vmid = get_secure_vmid(buffer->flags); struct device *dev = sys_heap->heap.dev; int order_ind = order_to_index(order); struct task_struct *worker; if (vmid > 0) pool = sys_heap->secure_pools[vmid][order_to_index(order)]; else if (!cached) pool = sys_heap->uncached_pools[order_to_index(order)]; else pool = sys_heap->cached_pools[order_to_index(order)]; if (vmid > 0) { pool = sys_heap->secure_pools[vmid][order_ind]; /* * We should skip stealing pages if (1) we're focing our * allocations to come from buddy; or (2) pool refilling is * disabled, in which case stealing pages could deplete the * uncached pools. */ if (!(*from_pool && pool_auto_refill_en)) goto normal_alloc; page = ion_page_pool_alloc_pool_only(pool); if (!IS_ERR(page)) return page; pool = sys_heap->uncached_pools[order_ind]; page = ion_page_pool_alloc_pool_only(pool); if (IS_ERR(page)) { pool = sys_heap->secure_pools[vmid][order_ind]; goto normal_alloc; } /* * Here, setting `from_pool = false` indicates that the * page didn't come from the secure pool, and causes * the page to be hyp-assigned. */ *from_pool = false; if (pool_auto_refill_en && pool->order && pool_count_below_lowmark(pool)) { worker = sys_heap->kworker[ION_KTHREAD_UNCACHED]; wake_up_process(worker); } return page; } else if (!cached) { pool = sys_heap->uncached_pools[order_ind]; } else { pool = sys_heap->cached_pools[order_ind]; } normal_alloc: page = ion_page_pool_alloc(pool, from_pool); if (pool_auto_refill_en && pool_count_below_lowmark(pool) && vmid <= 0) { if (pool_auto_refill_en && pool->order && pool_count_below_lowmark(pool) && vmid <= 0) wake_up_process(sys_heap->kworker[cached]); } if (IS_ERR(page)) return page; Loading Loading @@ -209,13 +241,11 @@ alloc_from_pool_preferred(struct ion_system_heap *heap, return alloc_largest_available(heap, buffer, size, max_order); } static unsigned int process_info(struct page_info *info, static void process_info(struct page_info *info, struct scatterlist *sg, struct scatterlist *sg_sync, struct pages_mem *data, unsigned int i) struct scatterlist *sg_sync) { struct page *page = info->page; unsigned int j; if (sg_sync) { sg_set_page(sg_sync, page, (1 << info->order) * PAGE_SIZE, 0); Loading @@ -228,45 +258,9 @@ static unsigned int process_info(struct page_info *info, * on the currently targeted hardware. */ sg_dma_address(sg) = page_to_phys(page); if (data) { for (j = 0; j < (1 << info->order); ++j) data->pages[i++] = nth_page(page, j); } list_del(&info->list); kfree(info); return i; } static int ion_heap_alloc_pages_mem(struct pages_mem *pages_mem) { struct page **pages; unsigned int page_tbl_size; page_tbl_size = sizeof(struct page *) * (pages_mem->size >> PAGE_SHIFT); if (page_tbl_size > SZ_8K) { /* * Do fallback to ensure we have a balance between * performance and availability. */ pages = kmalloc(page_tbl_size, __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN); if (!pages) pages = vmalloc(page_tbl_size); } else { pages = kmalloc(page_tbl_size, GFP_KERNEL); } if (!pages) return -ENOMEM; pages_mem->pages = pages; return 0; } static void ion_heap_free_pages_mem(struct pages_mem *pages_mem) { kvfree(pages_mem->pages); } static int ion_system_heap_allocate(struct ion_heap *heap, Loading @@ -287,7 +281,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, unsigned int nents_sync = 0; unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; struct pages_mem data; unsigned int sz; int vmid = get_secure_vmid(buffer->flags); Loading @@ -301,7 +294,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, return -EINVAL; } data.size = 0; INIT_LIST_HEAD(&pages); INIT_LIST_HEAD(&pages_from_pool); Loading @@ -326,7 +318,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, list_add_tail(&info->list, &pages_from_pool); } else { list_add_tail(&info->list, &pages); data.size += sz; ++nents_sync; } size_remaining -= sz; Loading @@ -334,15 +325,10 @@ static int ion_system_heap_allocate(struct ion_heap *heap, i++; } ret = ion_heap_alloc_pages_mem(&data); if (ret) goto err; table = kzalloc(sizeof(*table), GFP_KERNEL); if (!table) { ret = -ENOMEM; goto err_free_data_pages; goto err; } ret = sg_alloc_table(table, i, GFP_KERNEL); Loading @@ -355,7 +341,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, goto err_free_sg; } i = 0; sg = table->sgl; sg_sync = table_sync.sgl; Loading @@ -371,16 +356,16 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct page_info, list); if (info && tmp_info) { if (info->order >= tmp_info->order) { i = process_info(info, sg, sg_sync, &data, i); process_info(info, sg, sg_sync); sg_sync = sg_next(sg_sync); } else { i = process_info(tmp_info, sg, 0, 0, i); process_info(tmp_info, sg, NULL); } } else if (info) { i = process_info(info, sg, sg_sync, &data, i); process_info(info, sg, sg_sync); sg_sync = sg_next(sg_sync); } else if (tmp_info) { i = process_info(tmp_info, sg, 0, 0, i); process_info(tmp_info, sg, NULL); } sg = sg_next(sg); Loading @@ -397,7 +382,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, buffer->sg_table = table; if (nents_sync) sg_free_table(&table_sync); ion_heap_free_pages_mem(&data); ion_prepare_sgl_for_force_dma_sync(buffer->sg_table); return 0; Loading @@ -417,8 +401,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, sg_free_table(table); err1: kfree(table); err_free_data_pages: ion_heap_free_pages_mem(&data); err: list_for_each_entry_safe(info, tmp_info, &pages, list) { free_buffer_page(sys_heap, buffer, info->page, info->order); Loading