diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index 94b6ea19988b..6610cf320a92 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -96,6 +96,22 @@ static int check_scatter_align(struct scatterlist *sg_src, return (align && (sg_src->length == sg_dst->length)); } +static bool check_from_dmafd(struct crypto_async_request *async_req) +{ + struct rk_alg_ctx *alg_ctx = rk_alg_ctx_cast(async_req); + + if (alg_ctx->src_nents == 1 && + sg_virt(alg_ctx->req_src) && + sg_dma_address(alg_ctx->req_src) && + alg_ctx->dst_nents == 1 && + sg_virt(alg_ctx->req_dst) && + sg_dma_address(alg_ctx->req_dst) && + sg_dma_len(alg_ctx->req_src) == sg_dma_len(alg_ctx->req_dst)) + return true; + + return false; +} + static bool check_scatterlist_align(struct crypto_async_request *async_req, int align_mask) { @@ -133,9 +149,11 @@ static int rk_load_data(struct rk_crypto_dev *rk_dev, struct device *dev = rk_dev->dev; struct rk_alg_ctx *alg_ctx = rk_alg_ctx_cast(rk_dev->async_req); - if (alg_ctx->left_bytes == alg_ctx->total) + if (alg_ctx->left_bytes == alg_ctx->total) { + alg_ctx->is_dma = check_from_dmafd(rk_dev->async_req); alg_ctx->aligned = check_scatterlist_align(rk_dev->async_req, - alg_ctx->align_size); + alg_ctx->align_size) | alg_ctx->is_dma; + } CRYPTO_TRACE("aligned = %d, total = %u, left_bytes = %u\n", alg_ctx->aligned, alg_ctx->total, alg_ctx->left_bytes); @@ -154,7 +172,7 @@ static int rk_load_data(struct rk_crypto_dev *rk_dev, alg_ctx->addr_in = sg_dma_address(sg_src); if (sg_dst) { - if (!dma_map_sg(dev, sg_dst, 1, DMA_FROM_DEVICE)) { + if (!alg_ctx->is_dma && !dma_map_sg(dev, sg_dst, 1, DMA_FROM_DEVICE)) { dev_err(dev, "[%s:%d] dma_map_sg(dst) error\n", __func__, __LINE__); @@ -221,11 +239,13 @@ static int rk_unload_data(struct rk_crypto_dev *rk_dev) return 0; sg_in = alg_ctx->aligned ? alg_ctx->sg_src : &alg_ctx->sg_tmp; - dma_unmap_sg(rk_dev->dev, sg_in, 1, DMA_TO_DEVICE); + if (!alg_ctx->is_dma) + dma_unmap_sg(rk_dev->dev, sg_in, 1, DMA_TO_DEVICE); if (alg_ctx->sg_dst) { sg_out = alg_ctx->aligned ? alg_ctx->sg_dst : &alg_ctx->sg_tmp; - dma_unmap_sg(rk_dev->dev, sg_out, 1, DMA_FROM_DEVICE); + if (!alg_ctx->is_dma) + dma_unmap_sg(rk_dev->dev, sg_out, 1, DMA_FROM_DEVICE); } if (!alg_ctx->aligned && alg_ctx->req_dst) { diff --git a/drivers/crypto/rockchip/rk_crypto_core.h b/drivers/crypto/rockchip/rk_crypto_core.h index a22043818699..fd1ff7cf3f86 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.h +++ b/drivers/crypto/rockchip/rk_crypto_core.h @@ -114,6 +114,7 @@ struct rk_alg_ctx { dma_addr_t addr_out; bool aligned; + bool is_dma; int align_size; int chunk_size; };