1 /* 2 * Copyright (c) 2015, Linaro Limited 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 #include <linux/device.h> 15 #include <linux/dma-buf.h> 16 #include <linux/genalloc.h> 17 #include <linux/slab.h> 18 #include <linux/tee_drv.h> 19 #include "tee_private.h" 20 21 static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm, 22 struct tee_shm *shm, size_t size) 23 { 24 unsigned long va; 25 struct gen_pool *genpool = poolm->private_data; 26 size_t s = roundup(size, 1 << genpool->min_alloc_order); 27 28 va = gen_pool_alloc(genpool, s); 29 if (!va) 30 return -ENOMEM; 31 32 memset((void *)va, 0, s); 33 shm->kaddr = (void *)va; 34 shm->paddr = gen_pool_virt_to_phys(genpool, va); 35 shm->size = s; 36 return 0; 37 } 38 39 static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm, 40 struct tee_shm *shm) 41 { 42 gen_pool_free(poolm->private_data, (unsigned long)shm->kaddr, 43 shm->size); 44 shm->kaddr = NULL; 45 } 46 47 static const struct tee_shm_pool_mgr_ops pool_ops_generic = { 48 .alloc = pool_op_gen_alloc, 49 .free = pool_op_gen_free, 50 }; 51 52 static void pool_res_mem_destroy(struct tee_shm_pool *pool) 53 { 54 gen_pool_destroy(pool->private_mgr.private_data); 55 gen_pool_destroy(pool->dma_buf_mgr.private_data); 56 } 57 58 static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr, 59 struct tee_shm_pool_mem_info *info, 60 int min_alloc_order) 61 { 62 size_t page_mask = PAGE_SIZE - 1; 63 struct gen_pool *genpool = NULL; 64 int rc; 65 66 /* 67 * Start and end must be page aligned 68 */ 69 if ((info->vaddr & page_mask) || (info->paddr & page_mask) || 70 (info->size & page_mask)) 71 return -EINVAL; 72 73 genpool = gen_pool_create(min_alloc_order, -1); 74 if (!genpool) 75 return -ENOMEM; 76 77 gen_pool_set_algo(genpool, gen_pool_best_fit, NULL); 78 rc = gen_pool_add_virt(genpool, info->vaddr, info->paddr, info->size, 79 -1); 80 if (rc) { 81 gen_pool_destroy(genpool); 82 return rc; 83 } 84 85 mgr->private_data = genpool; 86 mgr->ops = &pool_ops_generic; 87 return 0; 88 } 89 90 /** 91 * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved 92 * memory range 93 * @priv_info: Information for driver private shared memory pool 94 * @dmabuf_info: Information for dma-buf shared memory pool 95 * 96 * Start and end of pools will must be page aligned. 97 * 98 * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied 99 * in @dmabuf, others will use the range provided by @priv. 100 * 101 * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. 102 */ 103 struct tee_shm_pool * 104 tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, 105 struct tee_shm_pool_mem_info *dmabuf_info) 106 { 107 struct tee_shm_pool *pool = NULL; 108 int ret; 109 110 pool = kzalloc(sizeof(*pool), GFP_KERNEL); 111 if (!pool) { 112 ret = -ENOMEM; 113 goto err; 114 } 115 116 /* 117 * Create the pool for driver private shared memory 118 */ 119 ret = pool_res_mem_mgr_init(&pool->private_mgr, priv_info, 120 3 /* 8 byte aligned */); 121 if (ret) 122 goto err; 123 124 /* 125 * Create the pool for dma_buf shared memory 126 */ 127 ret = pool_res_mem_mgr_init(&pool->dma_buf_mgr, dmabuf_info, 128 PAGE_SHIFT); 129 if (ret) 130 goto err; 131 132 pool->destroy = pool_res_mem_destroy; 133 return pool; 134 err: 135 if (ret == -ENOMEM) 136 pr_err("%s: can't allocate memory for res_mem shared memory pool\n", __func__); 137 if (pool && pool->private_mgr.private_data) 138 gen_pool_destroy(pool->private_mgr.private_data); 139 kfree(pool); 140 return ERR_PTR(ret); 141 } 142 EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem); 143 144 /** 145 * tee_shm_pool_free() - Free a shared memory pool 146 * @pool: The shared memory pool to free 147 * 148 * There must be no remaining shared memory allocated from this pool when 149 * this function is called. 150 */ 151 void tee_shm_pool_free(struct tee_shm_pool *pool) 152 { 153 pool->destroy(pool); 154 kfree(pool); 155 } 156 EXPORT_SYMBOL_GPL(tee_shm_pool_free); 157