diff options
Diffstat (limited to 'drivers/tee/tee_shm_pool.c')
| -rw-r--r-- | drivers/tee/tee_shm_pool.c | 165 | 
1 files changed, 102 insertions, 63 deletions
| diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c index fb4f8522a526..e6d4b9e4a864 100644 --- a/drivers/tee/tee_shm_pool.c +++ b/drivers/tee/tee_shm_pool.c @@ -44,49 +44,18 @@ static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm,  	shm->kaddr = NULL;  } +static void pool_op_gen_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) +{ +	gen_pool_destroy(poolm->private_data); +	kfree(poolm); +} +  static const struct tee_shm_pool_mgr_ops pool_ops_generic = {  	.alloc = pool_op_gen_alloc,  	.free = pool_op_gen_free, +	.destroy_poolmgr = pool_op_gen_destroy_poolmgr,  }; -static void pool_res_mem_destroy(struct tee_shm_pool *pool) -{ -	gen_pool_destroy(pool->private_mgr.private_data); -	gen_pool_destroy(pool->dma_buf_mgr.private_data); -} - -static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr, -				 struct tee_shm_pool_mem_info *info, -				 int min_alloc_order) -{ -	size_t page_mask = PAGE_SIZE - 1; -	struct gen_pool *genpool = NULL; -	int rc; - -	/* -	 * Start and end must be page aligned -	 */ -	if ((info->vaddr & page_mask) || (info->paddr & page_mask) || -	    (info->size & page_mask)) -		return -EINVAL; - -	genpool = gen_pool_create(min_alloc_order, -1); -	if (!genpool) -		return -ENOMEM; - -	gen_pool_set_algo(genpool, gen_pool_best_fit, NULL); -	rc = gen_pool_add_virt(genpool, info->vaddr, info->paddr, info->size, -			       -1); -	if (rc) { -		gen_pool_destroy(genpool); -		return rc; -	} - -	mgr->private_data = genpool; -	mgr->ops = &pool_ops_generic; -	return 0; -} -  /**   * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved   * memory range @@ -104,42 +73,109 @@ struct tee_shm_pool *  tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,  			   struct tee_shm_pool_mem_info *dmabuf_info)  { -	struct tee_shm_pool *pool = NULL; -	int ret; - -	pool = kzalloc(sizeof(*pool), GFP_KERNEL); -	if (!pool) { -		ret = -ENOMEM; -		goto err; -	} +	struct tee_shm_pool_mgr *priv_mgr; +	struct tee_shm_pool_mgr *dmabuf_mgr; +	void *rc;  	/*  	 * Create the pool for driver private shared memory  	 */ -	ret = pool_res_mem_mgr_init(&pool->private_mgr, priv_info, -				    3 /* 8 byte aligned */); -	if (ret) -		goto err; +	rc = tee_shm_pool_mgr_alloc_res_mem(priv_info->vaddr, priv_info->paddr, +					    priv_info->size, +					    3 /* 8 byte aligned */); +	if (IS_ERR(rc)) +		return rc; +	priv_mgr = rc;  	/*  	 * Create the pool for dma_buf shared memory  	 */ -	ret = pool_res_mem_mgr_init(&pool->dma_buf_mgr, dmabuf_info, -				    PAGE_SHIFT); -	if (ret) +	rc = tee_shm_pool_mgr_alloc_res_mem(dmabuf_info->vaddr, +					    dmabuf_info->paddr, +					    dmabuf_info->size, PAGE_SHIFT); +	if (IS_ERR(rc)) +		goto err_free_priv_mgr; +	dmabuf_mgr = rc; + +	rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); +	if (IS_ERR(rc)) +		goto err_free_dmabuf_mgr; + +	return rc; + +err_free_dmabuf_mgr: +	tee_shm_pool_mgr_destroy(dmabuf_mgr); +err_free_priv_mgr: +	tee_shm_pool_mgr_destroy(priv_mgr); + +	return rc; +} +EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem); + +struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr, +							phys_addr_t paddr, +							size_t size, +							int min_alloc_order) +{ +	const size_t page_mask = PAGE_SIZE - 1; +	struct tee_shm_pool_mgr *mgr; +	int rc; + +	/* Start and end must be page aligned */ +	if (vaddr & page_mask || paddr & page_mask || size & page_mask) +		return ERR_PTR(-EINVAL); + +	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); +	if (!mgr) +		return ERR_PTR(-ENOMEM); + +	mgr->private_data = gen_pool_create(min_alloc_order, -1); +	if (!mgr->private_data) { +		rc = -ENOMEM;  		goto err; +	} -	pool->destroy = pool_res_mem_destroy; -	return pool; +	gen_pool_set_algo(mgr->private_data, gen_pool_best_fit, NULL); +	rc = gen_pool_add_virt(mgr->private_data, vaddr, paddr, size, -1); +	if (rc) { +		gen_pool_destroy(mgr->private_data); +		goto err; +	} + +	mgr->ops = &pool_ops_generic; + +	return mgr;  err: -	if (ret == -ENOMEM) -		pr_err("%s: can't allocate memory for res_mem shared memory pool\n", __func__); -	if (pool && pool->private_mgr.private_data) -		gen_pool_destroy(pool->private_mgr.private_data); -	kfree(pool); -	return ERR_PTR(ret); +	kfree(mgr); + +	return ERR_PTR(rc);  } -EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem); +EXPORT_SYMBOL_GPL(tee_shm_pool_mgr_alloc_res_mem); + +static bool check_mgr_ops(struct tee_shm_pool_mgr *mgr) +{ +	return mgr && mgr->ops && mgr->ops->alloc && mgr->ops->free && +		mgr->ops->destroy_poolmgr; +} + +struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr, +					struct tee_shm_pool_mgr *dmabuf_mgr) +{ +	struct tee_shm_pool *pool; + +	if (!check_mgr_ops(priv_mgr) || !check_mgr_ops(dmabuf_mgr)) +		return ERR_PTR(-EINVAL); + +	pool = kzalloc(sizeof(*pool), GFP_KERNEL); +	if (!pool) +		return ERR_PTR(-ENOMEM); + +	pool->private_mgr = priv_mgr; +	pool->dma_buf_mgr = dmabuf_mgr; + +	return pool; +} +EXPORT_SYMBOL_GPL(tee_shm_pool_alloc);  /**   * tee_shm_pool_free() - Free a shared memory pool @@ -150,7 +186,10 @@ EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);   */  void tee_shm_pool_free(struct tee_shm_pool *pool)  { -	pool->destroy(pool); +	if (pool->private_mgr) +		tee_shm_pool_mgr_destroy(pool->private_mgr); +	if (pool->dma_buf_mgr) +		tee_shm_pool_mgr_destroy(pool->dma_buf_mgr);  	kfree(pool);  }  EXPORT_SYMBOL_GPL(tee_shm_pool_free); | 
