Merge tag 'for-linus-20180204' of git://git.kernel.dk/linux-block
[sfrench/cifs-2.6.git] / drivers / tee / tee_shm_pool.c
index fb4f8522a5269c59b9e0eb1cb0dc671402b3d077..e6d4b9e4a86494638eb2f85fe22078d5a4f91e53 100644 (file)
@@ -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);