diff --git a/drivers/crypto/hisilicon/sgl.c b/drivers/crypto/hisilicon/sgl.c index ebf36cc0ed2b6ea48fcc88d464c93cd3097a6cd7..7e6f2895956dda637e63ae6f1e03a2807b68f41f 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);