From d37c482e0e0f85cbd6f9e8e371caebeb674ffbeb Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 2 Mar 2021 17:35:24 +0800 Subject: [PATCH] staging: android: ion: use dma_sync_sg_for_device to do flush Fake platform devices for ion page pools, which are required by dma api. Change-Id: Id4b5844f20f993ea1b93704286610555386aeda8 Signed-off-by: Jianqun Xu --- drivers/staging/android/ion/ion.c | 19 ++++++++++++++++ drivers/staging/android/ion/ion.h | 5 +++++ drivers/staging/android/ion/ion_page_pool.c | 24 +++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 0a2d943e6564..5db9b0202d03 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -481,6 +481,25 @@ static const struct dma_buf_ops dma_buf_ops = { .vunmap = ion_dma_buf_vunmap, }; +void ion_page_sync_for_device(struct device *dev, struct page *page, + size_t size, enum dma_data_direction dir) +{ + struct scatterlist sg; + + if (!dev || !page) + return; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + /* + * This is not correct - sg_dma_address needs a dma_addr_t that is valid + * for the targeted device, but this works on the currently targeted + * hardware. + */ + sg_dma_address(&sg) = page_to_phys(page); + dma_sync_sg_for_device(dev, &sg, 1, dir); +} + int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) { struct ion_device *dev = internal_dev; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 55c62c2755c8..3ee98132ac6c 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -294,6 +294,7 @@ size_t ion_heap_freelist_size(struct ion_heap *heap); * @gfp_mask: gfp_mask to use from alloc * @order: order of pages in the pool * @list: plist node for list of pools + * @dev: device for the pool * * 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 @@ -309,6 +310,7 @@ struct ion_page_pool { gfp_t gfp_mask; unsigned int order; struct plist_node list; + struct device *dev; }; struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); @@ -322,6 +324,9 @@ long ion_page_pool_nr_pages(void); static inline long ion_page_pool_nr_pages(void) { return 0; } #endif +void ion_page_sync_for_device(struct device *dev, struct page *page, + size_t size, enum dma_data_direction dir); + /** ion_page_pool_shrink - shrinks the size of the memory cached in the pool * @pool: the pool * @gfp_mask: the memory type to reclaim diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 0ad1fb37408c..04e639141a85 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -5,6 +5,7 @@ * Copyright (C) 2011 Google, Inc. */ +#include #include #include #include @@ -83,8 +84,12 @@ struct page *ion_page_pool_alloc(struct ion_page_pool *pool) page = ion_page_pool_remove(pool, false); mutex_unlock(&pool->mutex); - if (!page) + if (!page) { page = ion_page_pool_alloc_pages(pool); + ion_page_sync_for_device(pool->dev, page, + PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); + } return page; } @@ -150,7 +155,8 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) { - struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL); + struct platform_device *pdev; + struct ion_page_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); if (!pool) return NULL; @@ -163,10 +169,24 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) mutex_init(&pool->mutex); plist_node_init(&pool->list, order); + pdev = platform_device_alloc("ion_pool", PLATFORM_DEVID_AUTO); + if (pdev) { + if (!platform_device_add(pdev)) { + pool->dev = &pdev->dev; + goto exit; + } + platform_device_put(pdev); + } + +exit: return pool; } void ion_page_pool_destroy(struct ion_page_pool *pool) { + struct platform_device *pdev; + + pdev = pool->dev ? to_platform_device(pool->dev) : NULL; + platform_device_put(pdev); kfree(pool); }