0001
0002
0003
0004
0005 #include <linux/device.h>
0006 #include <linux/dma-buf.h>
0007 #include <linux/genalloc.h>
0008 #include <linux/slab.h>
0009 #include <linux/tee_drv.h>
0010 #include "tee_private.h"
0011
0012 static int pool_op_gen_alloc(struct tee_shm_pool *pool, struct tee_shm *shm,
0013 size_t size, size_t align)
0014 {
0015 unsigned long va;
0016 struct gen_pool *genpool = pool->private_data;
0017 size_t a = max_t(size_t, align, BIT(genpool->min_alloc_order));
0018 struct genpool_data_align data = { .align = a };
0019 size_t s = roundup(size, a);
0020
0021 va = gen_pool_alloc_algo(genpool, s, gen_pool_first_fit_align, &data);
0022 if (!va)
0023 return -ENOMEM;
0024
0025 memset((void *)va, 0, s);
0026 shm->kaddr = (void *)va;
0027 shm->paddr = gen_pool_virt_to_phys(genpool, va);
0028 shm->size = s;
0029
0030
0031
0032
0033 shm->flags &= ~TEE_SHM_DYNAMIC;
0034 return 0;
0035 }
0036
0037 static void pool_op_gen_free(struct tee_shm_pool *pool, struct tee_shm *shm)
0038 {
0039 gen_pool_free(pool->private_data, (unsigned long)shm->kaddr,
0040 shm->size);
0041 shm->kaddr = NULL;
0042 }
0043
0044 static void pool_op_gen_destroy_pool(struct tee_shm_pool *pool)
0045 {
0046 gen_pool_destroy(pool->private_data);
0047 kfree(pool);
0048 }
0049
0050 static const struct tee_shm_pool_ops pool_ops_generic = {
0051 .alloc = pool_op_gen_alloc,
0052 .free = pool_op_gen_free,
0053 .destroy_pool = pool_op_gen_destroy_pool,
0054 };
0055
0056 struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
0057 phys_addr_t paddr, size_t size,
0058 int min_alloc_order)
0059 {
0060 const size_t page_mask = PAGE_SIZE - 1;
0061 struct tee_shm_pool *pool;
0062 int rc;
0063
0064
0065 if (vaddr & page_mask || paddr & page_mask || size & page_mask)
0066 return ERR_PTR(-EINVAL);
0067
0068 pool = kzalloc(sizeof(*pool), GFP_KERNEL);
0069 if (!pool)
0070 return ERR_PTR(-ENOMEM);
0071
0072 pool->private_data = gen_pool_create(min_alloc_order, -1);
0073 if (!pool->private_data) {
0074 rc = -ENOMEM;
0075 goto err;
0076 }
0077
0078 rc = gen_pool_add_virt(pool->private_data, vaddr, paddr, size, -1);
0079 if (rc) {
0080 gen_pool_destroy(pool->private_data);
0081 goto err;
0082 }
0083
0084 pool->ops = &pool_ops_generic;
0085
0086 return pool;
0087 err:
0088 kfree(pool);
0089
0090 return ERR_PTR(rc);
0091 }
0092 EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);