summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2025-05-13 14:04:06 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2025-06-13 17:26:15 +0800
commit508712228696eaddc4efc706e6a8dd679654f339 (patch)
tree1f8ef00dcbea60f0e4a334a0c5c8fe5470733b7c
parent5f38ebefc3703477a87c128d1a251ab6c9f4fbf8 (diff)
crypto: aspeed/hash - Add fallback
If a hash request fails due to a DMA mapping error, or if it is too large to fit in the the driver buffer, use a fallback to do the hash rather than failing. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/aspeed/aspeed-hace-hash.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/crypto/aspeed/aspeed-hace-hash.c b/drivers/crypto/aspeed/aspeed-hace-hash.c
index d7c7f867d6e1..3bfb7db96c40 100644
--- a/drivers/crypto/aspeed/aspeed-hace-hash.c
+++ b/drivers/crypto/aspeed/aspeed-hace-hash.c
@@ -420,6 +420,32 @@ static int aspeed_hace_hash_handle_queue(struct aspeed_hace_dev *hace_dev,
hace_dev->crypt_engine_hash, req);
}
+static noinline int aspeed_ahash_fallback(struct ahash_request *req)
+{
+ struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
+ HASH_FBREQ_ON_STACK(fbreq, req);
+ u8 *state = rctx->buffer;
+ struct scatterlist sg[2];
+ struct scatterlist *ssg;
+ int ret;
+
+ ssg = scatterwalk_ffwd(sg, req->src, rctx->offset);
+ ahash_request_set_crypt(fbreq, ssg, req->result,
+ rctx->total - rctx->offset);
+
+ ret = aspeed_sham_export(req, state) ?:
+ crypto_ahash_import_core(fbreq, state);
+
+ if (rctx->flags & SHA_FLAGS_FINUP)
+ ret = ret ?: crypto_ahash_finup(fbreq);
+ else
+ ret = ret ?: crypto_ahash_update(fbreq);
+ crypto_ahash_export_core(fbreq, state) ?:
+ aspeed_sham_import(req, state);
+ HASH_REQUEST_ZERO(fbreq);
+ return ret;
+}
+
static int aspeed_ahash_do_request(struct crypto_engine *engine, void *areq)
{
struct ahash_request *req = ahash_request_cast(areq);
@@ -434,7 +460,7 @@ static int aspeed_ahash_do_request(struct crypto_engine *engine, void *areq)
ret = aspeed_ahash_req_update(hace_dev);
if (ret != -EINPROGRESS)
- return ret;
+ return aspeed_ahash_fallback(req);
return 0;
}