]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
crypto: sun8i-ce - save hash buffers and dma info to request context
authorOvidiu Panait <ovidiu.panait.oss@gmail.com>
Tue, 2 Sep 2025 13:21:33 +0000 (16:21 +0300)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sat, 13 Sep 2025 04:11:05 +0000 (12:11 +0800)
Similar to sun8i-ce skcipher code, move all request-specific data to
request context. This simplifies sun8i_ce_hash_run() and it eliminates
the remaining kmalloc() calls from the digest path.

Since the 'result' buffer in the request ctx struct is used for from-device
DMA, it needs to be properly aligned to CRYPTO_DMA_ALIGN. Therefore:
- increase reqsize by CRYPTO_DMA_PADDING
- add __aligned(CRYPTO_DMA_ALIGN) attribute for the 'result' buffer
- convert all ahash_request_ctx_dma() calls to ahash_request_ctx_dma()

Signed-off-by: Ovidiu Panait <ovidiu.panait.oss@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h

index df2acef9c6795248327c4b0f38ef85b5bfeb15a1..6573c566bd0d3451c778e2c48ad7d25fab2fb982 100644 (file)
@@ -58,7 +58,8 @@ int sun8i_ce_hash_init_tfm(struct crypto_ahash *tfm)
 
        crypto_ahash_set_reqsize(tfm,
                                 sizeof(struct sun8i_ce_hash_reqctx) +
-                                crypto_ahash_reqsize(op->fallback_tfm));
+                                crypto_ahash_reqsize(op->fallback_tfm) +
+                                CRYPTO_DMA_PADDING);
 
        if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG))
                memcpy(algt->fbname,
@@ -84,7 +85,7 @@ void sun8i_ce_hash_exit_tfm(struct crypto_ahash *tfm)
 
 int sun8i_ce_hash_init(struct ahash_request *areq)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -100,7 +101,7 @@ int sun8i_ce_hash_init(struct ahash_request *areq)
 
 int sun8i_ce_hash_export(struct ahash_request *areq, void *out)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -114,7 +115,7 @@ int sun8i_ce_hash_export(struct ahash_request *areq, void *out)
 
 int sun8i_ce_hash_import(struct ahash_request *areq, const void *in)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -128,7 +129,7 @@ int sun8i_ce_hash_import(struct ahash_request *areq, const void *in)
 
 int sun8i_ce_hash_final(struct ahash_request *areq)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -145,7 +146,7 @@ int sun8i_ce_hash_final(struct ahash_request *areq)
 
 int sun8i_ce_hash_update(struct ahash_request *areq)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -160,7 +161,7 @@ int sun8i_ce_hash_update(struct ahash_request *areq)
 
 int sun8i_ce_hash_finup(struct ahash_request *areq)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -178,7 +179,7 @@ int sun8i_ce_hash_finup(struct ahash_request *areq)
 
 static int sun8i_ce_hash_digest_fb(struct ahash_request *areq)
 {
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
 
@@ -239,7 +240,7 @@ int sun8i_ce_hash_digest(struct ahash_request *areq)
 {
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct sun8i_ce_hash_tfm_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct sun8i_ce_dev *ce = ctx->ce;
        struct crypto_engine *engine;
        int e;
@@ -317,7 +318,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
        struct ahash_request *areq = container_of(breq, struct ahash_request, base);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
        struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg);
-       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq);
+       struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx_dma(areq);
        struct sun8i_ce_alg_template *algt;
        struct sun8i_ce_dev *ce;
        struct sun8i_ce_flow *chan;
@@ -328,12 +329,9 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
        u32 common;
        u64 byte_count;
        __le32 *bf;
-       void *buf, *result;
        int j, i, todo;
        u64 bs;
        int digestsize;
-       dma_addr_t addr_res, addr_pad;
-       int ns = sg_nents_for_len(areq->src, areq->nbytes);
 
        algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash.base);
        ce = algt->ce;
@@ -345,19 +343,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
        if (digestsize == SHA384_DIGEST_SIZE)
                digestsize = SHA512_DIGEST_SIZE;
 
-       /* the padding could be up to two block. */
-       buf = kcalloc(2, bs, GFP_KERNEL | GFP_DMA);
-       if (!buf) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       bf = (__le32 *)buf;
-
-       result = kzalloc(digestsize, GFP_KERNEL | GFP_DMA);
-       if (!result) {
-               err = -ENOMEM;
-               goto err_free_buf;
-       }
+       bf = (__le32 *)rctx->pad;
 
        flow = rctx->flow;
        chan = &ce->chanlist[flow];
@@ -378,11 +364,12 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
        cet->t_sym_ctl = 0;
        cet->t_asym_ctl = 0;
 
-       nr_sgs = dma_map_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE);
+       rctx->nr_sgs = sg_nents_for_len(areq->src, areq->nbytes);
+       nr_sgs = dma_map_sg(ce->dev, areq->src, rctx->nr_sgs, DMA_TO_DEVICE);
        if (nr_sgs <= 0 || nr_sgs > MAX_SG) {
                dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs);
                err = -EINVAL;
-               goto err_free_result;
+               goto err_out;
        }
 
        len = areq->nbytes;
@@ -397,10 +384,13 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
                err = -EINVAL;
                goto err_unmap_src;
        }
-       addr_res = dma_map_single(ce->dev, result, digestsize, DMA_FROM_DEVICE);
-       cet->t_dst[0].addr = desc_addr_val_le32(ce, addr_res);
-       cet->t_dst[0].len = cpu_to_le32(digestsize / 4);
-       if (dma_mapping_error(ce->dev, addr_res)) {
+
+       rctx->result_len = digestsize;
+       rctx->addr_res = dma_map_single(ce->dev, rctx->result, rctx->result_len,
+                                       DMA_FROM_DEVICE);
+       cet->t_dst[0].addr = desc_addr_val_le32(ce, rctx->addr_res);
+       cet->t_dst[0].len = cpu_to_le32(rctx->result_len / 4);
+       if (dma_mapping_error(ce->dev, rctx->addr_res)) {
                dev_err(ce->dev, "DMA map dest\n");
                err = -EINVAL;
                goto err_unmap_src;
@@ -428,10 +418,12 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
                goto err_unmap_result;
        }
 
-       addr_pad = dma_map_single(ce->dev, buf, j * 4, DMA_TO_DEVICE);
-       cet->t_src[i].addr = desc_addr_val_le32(ce, addr_pad);
+       rctx->pad_len = j * 4;
+       rctx->addr_pad = dma_map_single(ce->dev, rctx->pad, rctx->pad_len,
+                                       DMA_TO_DEVICE);
+       cet->t_src[i].addr = desc_addr_val_le32(ce, rctx->addr_pad);
        cet->t_src[i].len = cpu_to_le32(j);
-       if (dma_mapping_error(ce->dev, addr_pad)) {
+       if (dma_mapping_error(ce->dev, rctx->addr_pad)) {
                dev_err(ce->dev, "DMA error on padding SG\n");
                err = -EINVAL;
                goto err_unmap_result;
@@ -444,21 +436,16 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
 
        err = sun8i_ce_run_task(ce, flow, crypto_ahash_alg_name(tfm));
 
-       dma_unmap_single(ce->dev, addr_pad, j * 4, DMA_TO_DEVICE);
+       dma_unmap_single(ce->dev, rctx->addr_pad, rctx->pad_len, DMA_TO_DEVICE);
 
 err_unmap_result:
-       dma_unmap_single(ce->dev, addr_res, digestsize, DMA_FROM_DEVICE);
+       dma_unmap_single(ce->dev, rctx->addr_res, rctx->result_len,
+                        DMA_FROM_DEVICE);
        if (!err)
-               memcpy(areq->result, result, crypto_ahash_digestsize(tfm));
+               memcpy(areq->result, rctx->result, crypto_ahash_digestsize(tfm));
 
 err_unmap_src:
-       dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE);
-
-err_free_result:
-       kfree(result);
-
-err_free_buf:
-       kfree(buf);
+       dma_unmap_sg(ce->dev, areq->src, rctx->nr_sgs, DMA_TO_DEVICE);
 
 err_out:
        local_bh_disable();
index de3a096c476c23dfc988b3f7634250f395693c5d..71f5a0cd3d45825494472caa0cc100be1ec18ee8 100644 (file)
 
 #define MAXFLOW 4
 
+#define CE_MAX_HASH_DIGEST_SIZE                SHA512_DIGEST_SIZE
+#define CE_MAX_HASH_BLOCK_SIZE         SHA512_BLOCK_SIZE
+
 /*
  * struct ce_clock - Describe clocks used by sun8i-ce
  * @name:      Name of clock needed by this variant
@@ -304,9 +307,23 @@ struct sun8i_ce_hash_tfm_ctx {
  * struct sun8i_ce_hash_reqctx - context for an ahash request
  * @fallback_req:      pre-allocated fallback request
  * @flow:      the flow to use for this request
+ * @nr_sgs: number of entries in the source scatterlist
+ * @result_len: result length in bytes
+ * @pad_len: padding length in bytes
+ * @addr_res: DMA address of the result buffer, returned by dma_map_single()
+ * @addr_pad: DMA address of the padding buffer, returned by dma_map_single()
+ * @result: per-request result buffer
+ * @pad: per-request padding buffer (up to 2 blocks)
  */
 struct sun8i_ce_hash_reqctx {
        int flow;
+       int nr_sgs;
+       size_t result_len;
+       size_t pad_len;
+       dma_addr_t addr_res;
+       dma_addr_t addr_pad;
+       u8 result[CE_MAX_HASH_DIGEST_SIZE] __aligned(CRYPTO_DMA_ALIGN);
+       u8 pad[2 * CE_MAX_HASH_BLOCK_SIZE];
        struct ahash_request fallback_req; // keep at the end
 };