From 55d763a56699ce7f423a2cce456804ced08e39e3 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Tue, 8 Oct 2019 14:35:29 +0800 Subject: [PATCH] sgl:fix large memory allocation problem in sgl driver inclusion category: bugfix bugzilla: NA CVE: NA Currently sgl memory is allocated as block which size is page_size *(1 << (max_order - 1)),which will be very large when page_size and max_order are big. This patches fix this problem by allocating sgl memory as needed when needed memory is less than one block. Feature or Bugfix:Bugfix Signed-off-by: Zhou Wang Signed-off-by: shenyang39 Reviewed-by: Ling Mingqiang Reviewed-by: Yang Yingliang Signed-off-by: Yang Yingliang --- drivers/crypto/hisilicon/sgl.c | 43 +++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/hisilicon/sgl.c b/drivers/crypto/hisilicon/sgl.c index ebf36cc0ed2b..7e6f2895956d 100644 --- a/drivers/crypto/hisilicon/sgl.c +++ b/drivers/crypto/hisilicon/sgl.c @@ -58,7 +58,7 @@ struct hisi_acc_sgl_pool { struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev, u32 count, u32 sge_nr) { - u32 sgl_size, block_size, sgl_num_per_block, block_num; + u32 sgl_size, block_size, sgl_num_per_block, block_num, remain_sgl = 0; struct hisi_acc_sgl_pool *pool; struct mem_block *block; u32 i, j; @@ -70,10 +70,11 @@ struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev, sizeof(struct hisi_acc_hw_sgl); block_size = PAGE_SIZE * (1 << (MAX_ORDER - 1)); sgl_num_per_block = block_size / sgl_size; - block_num = count / sgl_num_per_block + - (count % sgl_num_per_block ? 1 : 0); + block_num = count / sgl_num_per_block; + remain_sgl = count % sgl_num_per_block; - if (block_num > HISI_ACC_MEM_BLOCK_NR) + if ((!remain_sgl && block_num > HISI_ACC_MEM_BLOCK_NR) || + (remain_sgl > 0 && block_num > HISI_ACC_MEM_BLOCK_NR - 1)) return ERR_PTR(-EINVAL); pool = kzalloc(sizeof(*pool), GFP_KERNEL); @@ -85,28 +86,38 @@ struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev, block[i].sgl = dma_alloc_coherent(dev, block_size, &block[i].sgl_dma, GFP_KERNEL); - if (!block[i].sgl) { - for (j = 0; j < i; j++) { - dma_free_coherent(dev, block_size, - block[j].sgl, - block[j].sgl_dma); - memset(block + j, 0, sizeof(*block)); - } - kfree(pool); - - return ERR_PTR(-ENOMEM); - } + if (!block[i].sgl) + goto err_free_mem; block[i].size = block_size; } + if (remain_sgl > 0) { + block[i].sgl = dma_alloc_coherent(dev, remain_sgl * sgl_size, + &block[i].sgl_dma, + GFP_KERNEL); + if (!block[i].sgl) + goto err_free_mem; + + block[i].size = remain_sgl * sgl_size; + } + pool->sgl_num_per_block = sgl_num_per_block; - pool->block_num = block_num; + pool->block_num = remain_sgl ? block_num + 1 : block_num; pool->count = count; pool->sgl_size = sgl_size; pool->sge_nr = sge_nr; return pool; + +err_free_mem: + for (j = 0; j < i; j++) { + dma_free_coherent(dev, block_size, block[j].sgl, + block[j].sgl_dma); + memset(block + j, 0, sizeof(*block)); + } + kfree(pool); + return ERR_PTR(-ENOMEM); } EXPORT_SYMBOL_GPL(hisi_acc_create_sgl_pool); -- GitLab