162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * caam - Freescale FSL CAAM support for ahash functions of crypto API
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2011 Freescale Semiconductor, Inc.
662306a36Sopenharmony_ci * Copyright 2018-2019, 2023 NXP
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Based on caamalg.c crypto API driver.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * relationship of digest job descriptor or first job descriptor after init to
1162306a36Sopenharmony_ci * shared descriptors:
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * ---------------                     ---------------
1462306a36Sopenharmony_ci * | JobDesc #1  |-------------------->|  ShareDesc  |
1562306a36Sopenharmony_ci * | *(packet 1) |                     |  (hashKey)  |
1662306a36Sopenharmony_ci * ---------------                     | (operation) |
1762306a36Sopenharmony_ci *                                     ---------------
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * relationship of subsequent job descriptors to shared descriptors:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * ---------------                     ---------------
2262306a36Sopenharmony_ci * | JobDesc #2  |-------------------->|  ShareDesc  |
2362306a36Sopenharmony_ci * | *(packet 2) |      |------------->|  (hashKey)  |
2462306a36Sopenharmony_ci * ---------------      |    |-------->| (operation) |
2562306a36Sopenharmony_ci *       .              |    |         | (load ctx2) |
2662306a36Sopenharmony_ci *       .              |    |         ---------------
2762306a36Sopenharmony_ci * ---------------      |    |
2862306a36Sopenharmony_ci * | JobDesc #3  |------|    |
2962306a36Sopenharmony_ci * | *(packet 3) |           |
3062306a36Sopenharmony_ci * ---------------           |
3162306a36Sopenharmony_ci *       .                   |
3262306a36Sopenharmony_ci *       .                   |
3362306a36Sopenharmony_ci * ---------------           |
3462306a36Sopenharmony_ci * | JobDesc #4  |------------
3562306a36Sopenharmony_ci * | *(packet 4) |
3662306a36Sopenharmony_ci * ---------------
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * The SharedDesc never changes for a connection unless rekeyed, but
3962306a36Sopenharmony_ci * each packet will likely be in a different place. So all we need
4062306a36Sopenharmony_ci * to know to process the packet is where the input is, where the
4162306a36Sopenharmony_ci * output goes, and what context we want to process with. Context is
4262306a36Sopenharmony_ci * in the SharedDesc, packet references in the JobDesc.
4362306a36Sopenharmony_ci *
4462306a36Sopenharmony_ci * So, a job desc looks like:
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * ---------------------
4762306a36Sopenharmony_ci * | Header            |
4862306a36Sopenharmony_ci * | ShareDesc Pointer |
4962306a36Sopenharmony_ci * | SEQ_OUT_PTR       |
5062306a36Sopenharmony_ci * | (output buffer)   |
5162306a36Sopenharmony_ci * | (output length)   |
5262306a36Sopenharmony_ci * | SEQ_IN_PTR        |
5362306a36Sopenharmony_ci * | (input buffer)    |
5462306a36Sopenharmony_ci * | (input length)    |
5562306a36Sopenharmony_ci * ---------------------
5662306a36Sopenharmony_ci */
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#include "compat.h"
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#include "regs.h"
6162306a36Sopenharmony_ci#include "intern.h"
6262306a36Sopenharmony_ci#include "desc_constr.h"
6362306a36Sopenharmony_ci#include "jr.h"
6462306a36Sopenharmony_ci#include "error.h"
6562306a36Sopenharmony_ci#include "sg_sw_sec4.h"
6662306a36Sopenharmony_ci#include "key_gen.h"
6762306a36Sopenharmony_ci#include "caamhash_desc.h"
6862306a36Sopenharmony_ci#include <crypto/internal/engine.h>
6962306a36Sopenharmony_ci#include <crypto/internal/hash.h>
7062306a36Sopenharmony_ci#include <linux/dma-mapping.h>
7162306a36Sopenharmony_ci#include <linux/err.h>
7262306a36Sopenharmony_ci#include <linux/kernel.h>
7362306a36Sopenharmony_ci#include <linux/slab.h>
7462306a36Sopenharmony_ci#include <linux/string.h>
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define CAAM_CRA_PRIORITY		3000
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/* max hash key is max split key size */
7962306a36Sopenharmony_ci#define CAAM_MAX_HASH_KEY_SIZE		(SHA512_DIGEST_SIZE * 2)
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define CAAM_MAX_HASH_BLOCK_SIZE	SHA512_BLOCK_SIZE
8262306a36Sopenharmony_ci#define CAAM_MAX_HASH_DIGEST_SIZE	SHA512_DIGEST_SIZE
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define DESC_HASH_MAX_USED_BYTES	(DESC_AHASH_FINAL_LEN + \
8562306a36Sopenharmony_ci					 CAAM_MAX_HASH_KEY_SIZE)
8662306a36Sopenharmony_ci#define DESC_HASH_MAX_USED_LEN		(DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/* caam context sizes for hashes: running digest + 8 */
8962306a36Sopenharmony_ci#define HASH_MSG_LEN			8
9062306a36Sopenharmony_ci#define MAX_CTX_LEN			(HASH_MSG_LEN + SHA512_DIGEST_SIZE)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic struct list_head hash_list;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* ahash per-session context */
9562306a36Sopenharmony_cistruct caam_hash_ctx {
9662306a36Sopenharmony_ci	u32 sh_desc_update[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
9762306a36Sopenharmony_ci	u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
9862306a36Sopenharmony_ci	u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
9962306a36Sopenharmony_ci	u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
10062306a36Sopenharmony_ci	u8 key[CAAM_MAX_HASH_KEY_SIZE] ____cacheline_aligned;
10162306a36Sopenharmony_ci	dma_addr_t sh_desc_update_dma ____cacheline_aligned;
10262306a36Sopenharmony_ci	dma_addr_t sh_desc_update_first_dma;
10362306a36Sopenharmony_ci	dma_addr_t sh_desc_fin_dma;
10462306a36Sopenharmony_ci	dma_addr_t sh_desc_digest_dma;
10562306a36Sopenharmony_ci	enum dma_data_direction dir;
10662306a36Sopenharmony_ci	enum dma_data_direction key_dir;
10762306a36Sopenharmony_ci	struct device *jrdev;
10862306a36Sopenharmony_ci	int ctx_len;
10962306a36Sopenharmony_ci	struct alginfo adata;
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/* ahash state */
11362306a36Sopenharmony_cistruct caam_hash_state {
11462306a36Sopenharmony_ci	dma_addr_t buf_dma;
11562306a36Sopenharmony_ci	dma_addr_t ctx_dma;
11662306a36Sopenharmony_ci	int ctx_dma_len;
11762306a36Sopenharmony_ci	u8 buf[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
11862306a36Sopenharmony_ci	int buflen;
11962306a36Sopenharmony_ci	int next_buflen;
12062306a36Sopenharmony_ci	u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned;
12162306a36Sopenharmony_ci	int (*update)(struct ahash_request *req) ____cacheline_aligned;
12262306a36Sopenharmony_ci	int (*final)(struct ahash_request *req);
12362306a36Sopenharmony_ci	int (*finup)(struct ahash_request *req);
12462306a36Sopenharmony_ci	struct ahash_edesc *edesc;
12562306a36Sopenharmony_ci	void (*ahash_op_done)(struct device *jrdev, u32 *desc, u32 err,
12662306a36Sopenharmony_ci			      void *context);
12762306a36Sopenharmony_ci};
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistruct caam_export_state {
13062306a36Sopenharmony_ci	u8 buf[CAAM_MAX_HASH_BLOCK_SIZE];
13162306a36Sopenharmony_ci	u8 caam_ctx[MAX_CTX_LEN];
13262306a36Sopenharmony_ci	int buflen;
13362306a36Sopenharmony_ci	int (*update)(struct ahash_request *req);
13462306a36Sopenharmony_ci	int (*final)(struct ahash_request *req);
13562306a36Sopenharmony_ci	int (*finup)(struct ahash_request *req);
13662306a36Sopenharmony_ci};
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic inline bool is_cmac_aes(u32 algtype)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) ==
14162306a36Sopenharmony_ci	       (OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci/* Common job descriptor seq in/out ptr routines */
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
14662306a36Sopenharmony_cistatic inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
14762306a36Sopenharmony_ci				      struct caam_hash_state *state,
14862306a36Sopenharmony_ci				      int ctx_len)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	state->ctx_dma_len = ctx_len;
15162306a36Sopenharmony_ci	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
15262306a36Sopenharmony_ci					ctx_len, DMA_FROM_DEVICE);
15362306a36Sopenharmony_ci	if (dma_mapping_error(jrdev, state->ctx_dma)) {
15462306a36Sopenharmony_ci		dev_err(jrdev, "unable to map ctx\n");
15562306a36Sopenharmony_ci		state->ctx_dma = 0;
15662306a36Sopenharmony_ci		return -ENOMEM;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	return 0;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci/* Map current buffer in state (if length > 0) and put it in link table */
16562306a36Sopenharmony_cistatic inline int buf_map_to_sec4_sg(struct device *jrdev,
16662306a36Sopenharmony_ci				     struct sec4_sg_entry *sec4_sg,
16762306a36Sopenharmony_ci				     struct caam_hash_state *state)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	int buflen = state->buflen;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	if (!buflen)
17262306a36Sopenharmony_ci		return 0;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	state->buf_dma = dma_map_single(jrdev, state->buf, buflen,
17562306a36Sopenharmony_ci					DMA_TO_DEVICE);
17662306a36Sopenharmony_ci	if (dma_mapping_error(jrdev, state->buf_dma)) {
17762306a36Sopenharmony_ci		dev_err(jrdev, "unable to map buf\n");
17862306a36Sopenharmony_ci		state->buf_dma = 0;
17962306a36Sopenharmony_ci		return -ENOMEM;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	dma_to_sec4_sg_one(sec4_sg, state->buf_dma, buflen, 0);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	return 0;
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci/* Map state->caam_ctx, and add it to link table */
18862306a36Sopenharmony_cistatic inline int ctx_map_to_sec4_sg(struct device *jrdev,
18962306a36Sopenharmony_ci				     struct caam_hash_state *state, int ctx_len,
19062306a36Sopenharmony_ci				     struct sec4_sg_entry *sec4_sg, u32 flag)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	state->ctx_dma_len = ctx_len;
19362306a36Sopenharmony_ci	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
19462306a36Sopenharmony_ci	if (dma_mapping_error(jrdev, state->ctx_dma)) {
19562306a36Sopenharmony_ci		dev_err(jrdev, "unable to map ctx\n");
19662306a36Sopenharmony_ci		state->ctx_dma = 0;
19762306a36Sopenharmony_ci		return -ENOMEM;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	return 0;
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic int ahash_set_sh_desc(struct crypto_ahash *ahash)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
20862306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
20962306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
21062306a36Sopenharmony_ci	struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent);
21162306a36Sopenharmony_ci	u32 *desc;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	ctx->adata.key_virt = ctx->key;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	/* ahash_update shared descriptor */
21662306a36Sopenharmony_ci	desc = ctx->sh_desc_update;
21762306a36Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len,
21862306a36Sopenharmony_ci			  ctx->ctx_len, true, ctrlpriv->era);
21962306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
22062306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	print_hex_dump_debug("ahash update shdesc@"__stringify(__LINE__)": ",
22362306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
22462306a36Sopenharmony_ci			     1);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/* ahash_update_first shared descriptor */
22762306a36Sopenharmony_ci	desc = ctx->sh_desc_update_first;
22862306a36Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
22962306a36Sopenharmony_ci			  ctx->ctx_len, false, ctrlpriv->era);
23062306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
23162306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
23262306a36Sopenharmony_ci	print_hex_dump_debug("ahash update first shdesc@"__stringify(__LINE__)
23362306a36Sopenharmony_ci			     ": ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
23462306a36Sopenharmony_ci			     desc_bytes(desc), 1);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	/* ahash_final shared descriptor */
23762306a36Sopenharmony_ci	desc = ctx->sh_desc_fin;
23862306a36Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize,
23962306a36Sopenharmony_ci			  ctx->ctx_len, true, ctrlpriv->era);
24062306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
24162306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	print_hex_dump_debug("ahash final shdesc@"__stringify(__LINE__)": ",
24462306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
24562306a36Sopenharmony_ci			     desc_bytes(desc), 1);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	/* ahash_digest shared descriptor */
24862306a36Sopenharmony_ci	desc = ctx->sh_desc_digest;
24962306a36Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize,
25062306a36Sopenharmony_ci			  ctx->ctx_len, false, ctrlpriv->era);
25162306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
25262306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	print_hex_dump_debug("ahash digest shdesc@"__stringify(__LINE__)": ",
25562306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
25662306a36Sopenharmony_ci			     desc_bytes(desc), 1);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	return 0;
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic int axcbc_set_sh_desc(struct crypto_ahash *ahash)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
26462306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
26562306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
26662306a36Sopenharmony_ci	u32 *desc;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	/* shared descriptor for ahash_update */
26962306a36Sopenharmony_ci	desc = ctx->sh_desc_update;
27062306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
27162306a36Sopenharmony_ci			    ctx->ctx_len, ctx->ctx_len);
27262306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
27362306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
27462306a36Sopenharmony_ci	print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ",
27562306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
27662306a36Sopenharmony_ci			     1);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	/* shared descriptor for ahash_{final,finup} */
27962306a36Sopenharmony_ci	desc = ctx->sh_desc_fin;
28062306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
28162306a36Sopenharmony_ci			    digestsize, ctx->ctx_len);
28262306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
28362306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
28462306a36Sopenharmony_ci	print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ",
28562306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
28662306a36Sopenharmony_ci			     1);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/* key is immediate data for INIT and INITFINAL states */
28962306a36Sopenharmony_ci	ctx->adata.key_virt = ctx->key;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	/* shared descriptor for first invocation of ahash_update */
29262306a36Sopenharmony_ci	desc = ctx->sh_desc_update_first;
29362306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
29462306a36Sopenharmony_ci			    ctx->ctx_len);
29562306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
29662306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
29762306a36Sopenharmony_ci	print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__)
29862306a36Sopenharmony_ci			     " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
29962306a36Sopenharmony_ci			     desc_bytes(desc), 1);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	/* shared descriptor for ahash_digest */
30262306a36Sopenharmony_ci	desc = ctx->sh_desc_digest;
30362306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
30462306a36Sopenharmony_ci			    digestsize, ctx->ctx_len);
30562306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
30662306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
30762306a36Sopenharmony_ci	print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ",
30862306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
30962306a36Sopenharmony_ci			     1);
31062306a36Sopenharmony_ci	return 0;
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic int acmac_set_sh_desc(struct crypto_ahash *ahash)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
31662306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
31762306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
31862306a36Sopenharmony_ci	u32 *desc;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/* shared descriptor for ahash_update */
32162306a36Sopenharmony_ci	desc = ctx->sh_desc_update;
32262306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
32362306a36Sopenharmony_ci			    ctx->ctx_len, ctx->ctx_len);
32462306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
32562306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
32662306a36Sopenharmony_ci	print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ",
32762306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
32862306a36Sopenharmony_ci			     desc_bytes(desc), 1);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	/* shared descriptor for ahash_{final,finup} */
33162306a36Sopenharmony_ci	desc = ctx->sh_desc_fin;
33262306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
33362306a36Sopenharmony_ci			    digestsize, ctx->ctx_len);
33462306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
33562306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
33662306a36Sopenharmony_ci	print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ",
33762306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
33862306a36Sopenharmony_ci			     desc_bytes(desc), 1);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	/* shared descriptor for first invocation of ahash_update */
34162306a36Sopenharmony_ci	desc = ctx->sh_desc_update_first;
34262306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
34362306a36Sopenharmony_ci			    ctx->ctx_len);
34462306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
34562306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
34662306a36Sopenharmony_ci	print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__)
34762306a36Sopenharmony_ci			     " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
34862306a36Sopenharmony_ci			     desc_bytes(desc), 1);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	/* shared descriptor for ahash_digest */
35162306a36Sopenharmony_ci	desc = ctx->sh_desc_digest;
35262306a36Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
35362306a36Sopenharmony_ci			    digestsize, ctx->ctx_len);
35462306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
35562306a36Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
35662306a36Sopenharmony_ci	print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ",
35762306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
35862306a36Sopenharmony_ci			     desc_bytes(desc), 1);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return 0;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci/* Digest hash size if it is too large */
36462306a36Sopenharmony_cistatic int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key,
36562306a36Sopenharmony_ci			   u32 digestsize)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
36862306a36Sopenharmony_ci	u32 *desc;
36962306a36Sopenharmony_ci	struct split_key_result result;
37062306a36Sopenharmony_ci	dma_addr_t key_dma;
37162306a36Sopenharmony_ci	int ret;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL);
37462306a36Sopenharmony_ci	if (!desc)
37562306a36Sopenharmony_ci		return -ENOMEM;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	init_job_desc(desc, 0);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	key_dma = dma_map_single(jrdev, key, *keylen, DMA_BIDIRECTIONAL);
38062306a36Sopenharmony_ci	if (dma_mapping_error(jrdev, key_dma)) {
38162306a36Sopenharmony_ci		dev_err(jrdev, "unable to map key memory\n");
38262306a36Sopenharmony_ci		kfree(desc);
38362306a36Sopenharmony_ci		return -ENOMEM;
38462306a36Sopenharmony_ci	}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* Job descriptor to perform unkeyed hash on key_in */
38762306a36Sopenharmony_ci	append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT |
38862306a36Sopenharmony_ci			 OP_ALG_AS_INITFINAL);
38962306a36Sopenharmony_ci	append_seq_in_ptr(desc, key_dma, *keylen, 0);
39062306a36Sopenharmony_ci	append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
39162306a36Sopenharmony_ci			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
39262306a36Sopenharmony_ci	append_seq_out_ptr(desc, key_dma, digestsize, 0);
39362306a36Sopenharmony_ci	append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
39462306a36Sopenharmony_ci			 LDST_SRCDST_BYTE_CONTEXT);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	print_hex_dump_debug("key_in@"__stringify(__LINE__)": ",
39762306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
39862306a36Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
39962306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
40062306a36Sopenharmony_ci			     1);
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	result.err = 0;
40362306a36Sopenharmony_ci	init_completion(&result.completion);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
40662306a36Sopenharmony_ci	if (ret == -EINPROGRESS) {
40762306a36Sopenharmony_ci		/* in progress */
40862306a36Sopenharmony_ci		wait_for_completion(&result.completion);
40962306a36Sopenharmony_ci		ret = result.err;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci		print_hex_dump_debug("digested key@"__stringify(__LINE__)": ",
41262306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, key,
41362306a36Sopenharmony_ci				     digestsize, 1);
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci	dma_unmap_single(jrdev, key_dma, *keylen, DMA_BIDIRECTIONAL);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	*keylen = digestsize;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	kfree(desc);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	return ret;
42262306a36Sopenharmony_ci}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *ahash,
42562306a36Sopenharmony_ci			const u8 *key, unsigned int keylen)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
42862306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
42962306a36Sopenharmony_ci	int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
43062306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
43162306a36Sopenharmony_ci	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent);
43262306a36Sopenharmony_ci	int ret;
43362306a36Sopenharmony_ci	u8 *hashed_key = NULL;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	dev_dbg(jrdev, "keylen %d\n", keylen);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	if (keylen > blocksize) {
43862306a36Sopenharmony_ci		unsigned int aligned_len =
43962306a36Sopenharmony_ci			ALIGN(keylen, dma_get_cache_alignment());
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci		if (aligned_len < keylen)
44262306a36Sopenharmony_ci			return -EOVERFLOW;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci		hashed_key = kmemdup(key, keylen, GFP_KERNEL);
44562306a36Sopenharmony_ci		if (!hashed_key)
44662306a36Sopenharmony_ci			return -ENOMEM;
44762306a36Sopenharmony_ci		ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
44862306a36Sopenharmony_ci		if (ret)
44962306a36Sopenharmony_ci			goto bad_free_key;
45062306a36Sopenharmony_ci		key = hashed_key;
45162306a36Sopenharmony_ci	}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	/*
45462306a36Sopenharmony_ci	 * If DKP is supported, use it in the shared descriptor to generate
45562306a36Sopenharmony_ci	 * the split key.
45662306a36Sopenharmony_ci	 */
45762306a36Sopenharmony_ci	if (ctrlpriv->era >= 6) {
45862306a36Sopenharmony_ci		ctx->adata.key_inline = true;
45962306a36Sopenharmony_ci		ctx->adata.keylen = keylen;
46062306a36Sopenharmony_ci		ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype &
46162306a36Sopenharmony_ci						      OP_ALG_ALGSEL_MASK);
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci		if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE)
46462306a36Sopenharmony_ci			goto bad_free_key;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		memcpy(ctx->key, key, keylen);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		/*
46962306a36Sopenharmony_ci		 * In case |user key| > |derived key|, using DKP<imm,imm>
47062306a36Sopenharmony_ci		 * would result in invalid opcodes (last bytes of user key) in
47162306a36Sopenharmony_ci		 * the resulting descriptor. Use DKP<ptr,imm> instead => both
47262306a36Sopenharmony_ci		 * virtual and dma key addresses are needed.
47362306a36Sopenharmony_ci		 */
47462306a36Sopenharmony_ci		if (keylen > ctx->adata.keylen_pad)
47562306a36Sopenharmony_ci			dma_sync_single_for_device(ctx->jrdev,
47662306a36Sopenharmony_ci						   ctx->adata.key_dma,
47762306a36Sopenharmony_ci						   ctx->adata.keylen_pad,
47862306a36Sopenharmony_ci						   DMA_TO_DEVICE);
47962306a36Sopenharmony_ci	} else {
48062306a36Sopenharmony_ci		ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key,
48162306a36Sopenharmony_ci				    keylen, CAAM_MAX_HASH_KEY_SIZE);
48262306a36Sopenharmony_ci		if (ret)
48362306a36Sopenharmony_ci			goto bad_free_key;
48462306a36Sopenharmony_ci	}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	kfree(hashed_key);
48762306a36Sopenharmony_ci	return ahash_set_sh_desc(ahash);
48862306a36Sopenharmony_ci bad_free_key:
48962306a36Sopenharmony_ci	kfree(hashed_key);
49062306a36Sopenharmony_ci	return -EINVAL;
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key,
49462306a36Sopenharmony_ci			unsigned int keylen)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
49762306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (keylen != AES_KEYSIZE_128)
50062306a36Sopenharmony_ci		return -EINVAL;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
50362306a36Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->adata.key_dma, keylen,
50462306a36Sopenharmony_ci				   DMA_TO_DEVICE);
50562306a36Sopenharmony_ci	ctx->adata.keylen = keylen;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ",
50862306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	return axcbc_set_sh_desc(ahash);
51162306a36Sopenharmony_ci}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cistatic int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
51462306a36Sopenharmony_ci			unsigned int keylen)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
51762306a36Sopenharmony_ci	int err;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	err = aes_check_keylen(keylen);
52062306a36Sopenharmony_ci	if (err)
52162306a36Sopenharmony_ci		return err;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	/* key is immediate data for all cmac shared descriptors */
52462306a36Sopenharmony_ci	ctx->adata.key_virt = key;
52562306a36Sopenharmony_ci	ctx->adata.keylen = keylen;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ",
52862306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	return acmac_set_sh_desc(ahash);
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci/*
53462306a36Sopenharmony_ci * ahash_edesc - s/w-extended ahash descriptor
53562306a36Sopenharmony_ci * @sec4_sg_dma: physical mapped address of h/w link table
53662306a36Sopenharmony_ci * @src_nents: number of segments in input scatterlist
53762306a36Sopenharmony_ci * @sec4_sg_bytes: length of dma mapped sec4_sg space
53862306a36Sopenharmony_ci * @bklog: stored to determine if the request needs backlog
53962306a36Sopenharmony_ci * @hw_desc: the h/w job descriptor followed by any referenced link tables
54062306a36Sopenharmony_ci * @sec4_sg: h/w link table
54162306a36Sopenharmony_ci */
54262306a36Sopenharmony_cistruct ahash_edesc {
54362306a36Sopenharmony_ci	dma_addr_t sec4_sg_dma;
54462306a36Sopenharmony_ci	int src_nents;
54562306a36Sopenharmony_ci	int sec4_sg_bytes;
54662306a36Sopenharmony_ci	bool bklog;
54762306a36Sopenharmony_ci	u32 hw_desc[DESC_JOB_IO_LEN_MAX / sizeof(u32)] ____cacheline_aligned;
54862306a36Sopenharmony_ci	struct sec4_sg_entry sec4_sg[];
54962306a36Sopenharmony_ci};
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_cistatic inline void ahash_unmap(struct device *dev,
55262306a36Sopenharmony_ci			struct ahash_edesc *edesc,
55362306a36Sopenharmony_ci			struct ahash_request *req, int dst_len)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	if (edesc->src_nents)
55862306a36Sopenharmony_ci		dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	if (edesc->sec4_sg_bytes)
56162306a36Sopenharmony_ci		dma_unmap_single(dev, edesc->sec4_sg_dma,
56262306a36Sopenharmony_ci				 edesc->sec4_sg_bytes, DMA_TO_DEVICE);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	if (state->buf_dma) {
56562306a36Sopenharmony_ci		dma_unmap_single(dev, state->buf_dma, state->buflen,
56662306a36Sopenharmony_ci				 DMA_TO_DEVICE);
56762306a36Sopenharmony_ci		state->buf_dma = 0;
56862306a36Sopenharmony_ci	}
56962306a36Sopenharmony_ci}
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_cistatic inline void ahash_unmap_ctx(struct device *dev,
57262306a36Sopenharmony_ci			struct ahash_edesc *edesc,
57362306a36Sopenharmony_ci			struct ahash_request *req, int dst_len, u32 flag)
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	if (state->ctx_dma) {
57862306a36Sopenharmony_ci		dma_unmap_single(dev, state->ctx_dma, state->ctx_dma_len, flag);
57962306a36Sopenharmony_ci		state->ctx_dma = 0;
58062306a36Sopenharmony_ci	}
58162306a36Sopenharmony_ci	ahash_unmap(dev, edesc, req, dst_len);
58262306a36Sopenharmony_ci}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_cistatic inline void ahash_done_cpy(struct device *jrdev, u32 *desc, u32 err,
58562306a36Sopenharmony_ci				  void *context, enum dma_data_direction dir)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	struct ahash_request *req = context;
58862306a36Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
58962306a36Sopenharmony_ci	struct ahash_edesc *edesc;
59062306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
59162306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
59262306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
59362306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
59462306a36Sopenharmony_ci	int ecode = 0;
59562306a36Sopenharmony_ci	bool has_bklog;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	edesc = state->edesc;
60062306a36Sopenharmony_ci	has_bklog = edesc->bklog;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	if (err)
60362306a36Sopenharmony_ci		ecode = caam_jr_strstatus(jrdev, err);
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, digestsize, dir);
60662306a36Sopenharmony_ci	memcpy(req->result, state->caam_ctx, digestsize);
60762306a36Sopenharmony_ci	kfree(edesc);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
61062306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
61162306a36Sopenharmony_ci			     ctx->ctx_len, 1);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	/*
61462306a36Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
61562306a36Sopenharmony_ci	 * by CAAM, not crypto engine.
61662306a36Sopenharmony_ci	 */
61762306a36Sopenharmony_ci	if (!has_bklog)
61862306a36Sopenharmony_ci		ahash_request_complete(req, ecode);
61962306a36Sopenharmony_ci	else
62062306a36Sopenharmony_ci		crypto_finalize_hash_request(jrp->engine, req, ecode);
62162306a36Sopenharmony_ci}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_cistatic void ahash_done(struct device *jrdev, u32 *desc, u32 err,
62462306a36Sopenharmony_ci		       void *context)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	ahash_done_cpy(jrdev, desc, err, context, DMA_FROM_DEVICE);
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_cistatic void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
63062306a36Sopenharmony_ci			       void *context)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	ahash_done_cpy(jrdev, desc, err, context, DMA_BIDIRECTIONAL);
63362306a36Sopenharmony_ci}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_cistatic inline void ahash_done_switch(struct device *jrdev, u32 *desc, u32 err,
63662306a36Sopenharmony_ci				     void *context, enum dma_data_direction dir)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	struct ahash_request *req = context;
63962306a36Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
64062306a36Sopenharmony_ci	struct ahash_edesc *edesc;
64162306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
64262306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
64362306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
64462306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
64562306a36Sopenharmony_ci	int ecode = 0;
64662306a36Sopenharmony_ci	bool has_bklog;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	edesc = state->edesc;
65162306a36Sopenharmony_ci	has_bklog = edesc->bklog;
65262306a36Sopenharmony_ci	if (err)
65362306a36Sopenharmony_ci		ecode = caam_jr_strstatus(jrdev, err);
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, dir);
65662306a36Sopenharmony_ci	kfree(edesc);
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	scatterwalk_map_and_copy(state->buf, req->src,
65962306a36Sopenharmony_ci				 req->nbytes - state->next_buflen,
66062306a36Sopenharmony_ci				 state->next_buflen, 0);
66162306a36Sopenharmony_ci	state->buflen = state->next_buflen;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
66462306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, state->buf,
66562306a36Sopenharmony_ci			     state->buflen, 1);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
66862306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
66962306a36Sopenharmony_ci			     ctx->ctx_len, 1);
67062306a36Sopenharmony_ci	if (req->result)
67162306a36Sopenharmony_ci		print_hex_dump_debug("result@"__stringify(__LINE__)": ",
67262306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, req->result,
67362306a36Sopenharmony_ci				     digestsize, 1);
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	/*
67662306a36Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
67762306a36Sopenharmony_ci	 * by CAAM, not crypto engine.
67862306a36Sopenharmony_ci	 */
67962306a36Sopenharmony_ci	if (!has_bklog)
68062306a36Sopenharmony_ci		ahash_request_complete(req, ecode);
68162306a36Sopenharmony_ci	else
68262306a36Sopenharmony_ci		crypto_finalize_hash_request(jrp->engine, req, ecode);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_cistatic void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err,
68762306a36Sopenharmony_ci			  void *context)
68862306a36Sopenharmony_ci{
68962306a36Sopenharmony_ci	ahash_done_switch(jrdev, desc, err, context, DMA_BIDIRECTIONAL);
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
69362306a36Sopenharmony_ci			       void *context)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	ahash_done_switch(jrdev, desc, err, context, DMA_FROM_DEVICE);
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci/*
69962306a36Sopenharmony_ci * Allocate an enhanced descriptor, which contains the hardware descriptor
70062306a36Sopenharmony_ci * and space for hardware scatter table containing sg_num entries.
70162306a36Sopenharmony_ci */
70262306a36Sopenharmony_cistatic struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req,
70362306a36Sopenharmony_ci					     int sg_num, u32 *sh_desc,
70462306a36Sopenharmony_ci					     dma_addr_t sh_desc_dma)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
70762306a36Sopenharmony_ci	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
70862306a36Sopenharmony_ci		       GFP_KERNEL : GFP_ATOMIC;
70962306a36Sopenharmony_ci	struct ahash_edesc *edesc;
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	edesc = kzalloc(struct_size(edesc, sec4_sg, sg_num), flags);
71262306a36Sopenharmony_ci	if (!edesc)
71362306a36Sopenharmony_ci		return NULL;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	state->edesc = edesc;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	init_job_desc_shared(edesc->hw_desc, sh_desc_dma, desc_len(sh_desc),
71862306a36Sopenharmony_ci			     HDR_SHARE_DEFER | HDR_REVERSE);
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	return edesc;
72162306a36Sopenharmony_ci}
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_cistatic int ahash_edesc_add_src(struct caam_hash_ctx *ctx,
72462306a36Sopenharmony_ci			       struct ahash_edesc *edesc,
72562306a36Sopenharmony_ci			       struct ahash_request *req, int nents,
72662306a36Sopenharmony_ci			       unsigned int first_sg,
72762306a36Sopenharmony_ci			       unsigned int first_bytes, size_t to_hash)
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	dma_addr_t src_dma;
73062306a36Sopenharmony_ci	u32 options;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	if (nents > 1 || first_sg) {
73362306a36Sopenharmony_ci		struct sec4_sg_entry *sg = edesc->sec4_sg;
73462306a36Sopenharmony_ci		unsigned int sgsize = sizeof(*sg) *
73562306a36Sopenharmony_ci				      pad_sg_nents(first_sg + nents);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci		sg_to_sec4_sg_last(req->src, to_hash, sg + first_sg, 0);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci		src_dma = dma_map_single(ctx->jrdev, sg, sgsize, DMA_TO_DEVICE);
74062306a36Sopenharmony_ci		if (dma_mapping_error(ctx->jrdev, src_dma)) {
74162306a36Sopenharmony_ci			dev_err(ctx->jrdev, "unable to map S/G table\n");
74262306a36Sopenharmony_ci			return -ENOMEM;
74362306a36Sopenharmony_ci		}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci		edesc->sec4_sg_bytes = sgsize;
74662306a36Sopenharmony_ci		edesc->sec4_sg_dma = src_dma;
74762306a36Sopenharmony_ci		options = LDST_SGF;
74862306a36Sopenharmony_ci	} else {
74962306a36Sopenharmony_ci		src_dma = sg_dma_address(req->src);
75062306a36Sopenharmony_ci		options = 0;
75162306a36Sopenharmony_ci	}
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	append_seq_in_ptr(edesc->hw_desc, src_dma, first_bytes + to_hash,
75462306a36Sopenharmony_ci			  options);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	return 0;
75762306a36Sopenharmony_ci}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_cistatic int ahash_do_one_req(struct crypto_engine *engine, void *areq)
76062306a36Sopenharmony_ci{
76162306a36Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
76262306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(crypto_ahash_reqtfm(req));
76362306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
76462306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
76562306a36Sopenharmony_ci	u32 *desc = state->edesc->hw_desc;
76662306a36Sopenharmony_ci	int ret;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	state->edesc->bklog = true;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	ret = caam_jr_enqueue(jrdev, desc, state->ahash_op_done, req);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	if (ret == -ENOSPC && engine->retry_support)
77362306a36Sopenharmony_ci		return ret;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	if (ret != -EINPROGRESS) {
77662306a36Sopenharmony_ci		ahash_unmap(jrdev, state->edesc, req, 0);
77762306a36Sopenharmony_ci		kfree(state->edesc);
77862306a36Sopenharmony_ci	} else {
77962306a36Sopenharmony_ci		ret = 0;
78062306a36Sopenharmony_ci	}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	return ret;
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic int ahash_enqueue_req(struct device *jrdev,
78662306a36Sopenharmony_ci			     void (*cbk)(struct device *jrdev, u32 *desc,
78762306a36Sopenharmony_ci					 u32 err, void *context),
78862306a36Sopenharmony_ci			     struct ahash_request *req,
78962306a36Sopenharmony_ci			     int dst_len, enum dma_data_direction dir)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev);
79262306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
79362306a36Sopenharmony_ci	struct ahash_edesc *edesc = state->edesc;
79462306a36Sopenharmony_ci	u32 *desc = edesc->hw_desc;
79562306a36Sopenharmony_ci	int ret;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	state->ahash_op_done = cbk;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/*
80062306a36Sopenharmony_ci	 * Only the backlog request are sent to crypto-engine since the others
80162306a36Sopenharmony_ci	 * can be handled by CAAM, if free, especially since JR has up to 1024
80262306a36Sopenharmony_ci	 * entries (more than the 10 entries from crypto-engine).
80362306a36Sopenharmony_ci	 */
80462306a36Sopenharmony_ci	if (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
80562306a36Sopenharmony_ci		ret = crypto_transfer_hash_request_to_engine(jrpriv->engine,
80662306a36Sopenharmony_ci							     req);
80762306a36Sopenharmony_ci	else
80862306a36Sopenharmony_ci		ret = caam_jr_enqueue(jrdev, desc, cbk, req);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	if ((ret != -EINPROGRESS) && (ret != -EBUSY)) {
81162306a36Sopenharmony_ci		ahash_unmap_ctx(jrdev, edesc, req, dst_len, dir);
81262306a36Sopenharmony_ci		kfree(edesc);
81362306a36Sopenharmony_ci	}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	return ret;
81662306a36Sopenharmony_ci}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci/* submit update job descriptor */
81962306a36Sopenharmony_cistatic int ahash_update_ctx(struct ahash_request *req)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
82262306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
82362306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
82462306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
82562306a36Sopenharmony_ci	u8 *buf = state->buf;
82662306a36Sopenharmony_ci	int *buflen = &state->buflen;
82762306a36Sopenharmony_ci	int *next_buflen = &state->next_buflen;
82862306a36Sopenharmony_ci	int blocksize = crypto_ahash_blocksize(ahash);
82962306a36Sopenharmony_ci	int in_len = *buflen + req->nbytes, to_hash;
83062306a36Sopenharmony_ci	u32 *desc;
83162306a36Sopenharmony_ci	int src_nents, mapped_nents, sec4_sg_bytes, sec4_sg_src_index;
83262306a36Sopenharmony_ci	struct ahash_edesc *edesc;
83362306a36Sopenharmony_ci	int ret = 0;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	*next_buflen = in_len & (blocksize - 1);
83662306a36Sopenharmony_ci	to_hash = in_len - *next_buflen;
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	/*
83962306a36Sopenharmony_ci	 * For XCBC and CMAC, if to_hash is multiple of block size,
84062306a36Sopenharmony_ci	 * keep last block in internal buffer
84162306a36Sopenharmony_ci	 */
84262306a36Sopenharmony_ci	if ((is_xcbc_aes(ctx->adata.algtype) ||
84362306a36Sopenharmony_ci	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
84462306a36Sopenharmony_ci	     (*next_buflen == 0)) {
84562306a36Sopenharmony_ci		*next_buflen = blocksize;
84662306a36Sopenharmony_ci		to_hash -= blocksize;
84762306a36Sopenharmony_ci	}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	if (to_hash) {
85062306a36Sopenharmony_ci		int pad_nents;
85162306a36Sopenharmony_ci		int src_len = req->nbytes - *next_buflen;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci		src_nents = sg_nents_for_len(req->src, src_len);
85462306a36Sopenharmony_ci		if (src_nents < 0) {
85562306a36Sopenharmony_ci			dev_err(jrdev, "Invalid number of src SG.\n");
85662306a36Sopenharmony_ci			return src_nents;
85762306a36Sopenharmony_ci		}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci		if (src_nents) {
86062306a36Sopenharmony_ci			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
86162306a36Sopenharmony_ci						  DMA_TO_DEVICE);
86262306a36Sopenharmony_ci			if (!mapped_nents) {
86362306a36Sopenharmony_ci				dev_err(jrdev, "unable to DMA map source\n");
86462306a36Sopenharmony_ci				return -ENOMEM;
86562306a36Sopenharmony_ci			}
86662306a36Sopenharmony_ci		} else {
86762306a36Sopenharmony_ci			mapped_nents = 0;
86862306a36Sopenharmony_ci		}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci		sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
87162306a36Sopenharmony_ci		pad_nents = pad_sg_nents(sec4_sg_src_index + mapped_nents);
87262306a36Sopenharmony_ci		sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci		/*
87562306a36Sopenharmony_ci		 * allocate space for base edesc and hw desc commands,
87662306a36Sopenharmony_ci		 * link tables
87762306a36Sopenharmony_ci		 */
87862306a36Sopenharmony_ci		edesc = ahash_edesc_alloc(req, pad_nents, ctx->sh_desc_update,
87962306a36Sopenharmony_ci					  ctx->sh_desc_update_dma);
88062306a36Sopenharmony_ci		if (!edesc) {
88162306a36Sopenharmony_ci			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
88262306a36Sopenharmony_ci			return -ENOMEM;
88362306a36Sopenharmony_ci		}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci		edesc->src_nents = src_nents;
88662306a36Sopenharmony_ci		edesc->sec4_sg_bytes = sec4_sg_bytes;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci		ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
88962306a36Sopenharmony_ci					 edesc->sec4_sg, DMA_BIDIRECTIONAL);
89062306a36Sopenharmony_ci		if (ret)
89162306a36Sopenharmony_ci			goto unmap_ctx;
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci		ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
89462306a36Sopenharmony_ci		if (ret)
89562306a36Sopenharmony_ci			goto unmap_ctx;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci		if (mapped_nents)
89862306a36Sopenharmony_ci			sg_to_sec4_sg_last(req->src, src_len,
89962306a36Sopenharmony_ci					   edesc->sec4_sg + sec4_sg_src_index,
90062306a36Sopenharmony_ci					   0);
90162306a36Sopenharmony_ci		else
90262306a36Sopenharmony_ci			sg_to_sec4_set_last(edesc->sec4_sg + sec4_sg_src_index -
90362306a36Sopenharmony_ci					    1);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci		desc = edesc->hw_desc;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
90862306a36Sopenharmony_ci						     sec4_sg_bytes,
90962306a36Sopenharmony_ci						     DMA_TO_DEVICE);
91062306a36Sopenharmony_ci		if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
91162306a36Sopenharmony_ci			dev_err(jrdev, "unable to map S/G table\n");
91262306a36Sopenharmony_ci			ret = -ENOMEM;
91362306a36Sopenharmony_ci			goto unmap_ctx;
91462306a36Sopenharmony_ci		}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci		append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
91762306a36Sopenharmony_ci				       to_hash, LDST_SGF);
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci		append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0);
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
92262306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
92362306a36Sopenharmony_ci				     desc_bytes(desc), 1);
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci		ret = ahash_enqueue_req(jrdev, ahash_done_bi, req,
92662306a36Sopenharmony_ci					ctx->ctx_len, DMA_BIDIRECTIONAL);
92762306a36Sopenharmony_ci	} else if (*next_buflen) {
92862306a36Sopenharmony_ci		scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
92962306a36Sopenharmony_ci					 req->nbytes, 0);
93062306a36Sopenharmony_ci		*buflen = *next_buflen;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
93362306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
93462306a36Sopenharmony_ci				     *buflen, 1);
93562306a36Sopenharmony_ci	}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	return ret;
93862306a36Sopenharmony_ciunmap_ctx:
93962306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
94062306a36Sopenharmony_ci	kfree(edesc);
94162306a36Sopenharmony_ci	return ret;
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_cistatic int ahash_final_ctx(struct ahash_request *req)
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
94762306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
94862306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
94962306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
95062306a36Sopenharmony_ci	int buflen = state->buflen;
95162306a36Sopenharmony_ci	u32 *desc;
95262306a36Sopenharmony_ci	int sec4_sg_bytes;
95362306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
95462306a36Sopenharmony_ci	struct ahash_edesc *edesc;
95562306a36Sopenharmony_ci	int ret;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	sec4_sg_bytes = pad_sg_nents(1 + (buflen ? 1 : 0)) *
95862306a36Sopenharmony_ci			sizeof(struct sec4_sg_entry);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
96162306a36Sopenharmony_ci	edesc = ahash_edesc_alloc(req, 4, ctx->sh_desc_fin,
96262306a36Sopenharmony_ci				  ctx->sh_desc_fin_dma);
96362306a36Sopenharmony_ci	if (!edesc)
96462306a36Sopenharmony_ci		return -ENOMEM;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	desc = edesc->hw_desc;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	edesc->sec4_sg_bytes = sec4_sg_bytes;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
97162306a36Sopenharmony_ci				 edesc->sec4_sg, DMA_BIDIRECTIONAL);
97262306a36Sopenharmony_ci	if (ret)
97362306a36Sopenharmony_ci		goto unmap_ctx;
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
97662306a36Sopenharmony_ci	if (ret)
97762306a36Sopenharmony_ci		goto unmap_ctx;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	sg_to_sec4_set_last(edesc->sec4_sg + (buflen ? 1 : 0));
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
98262306a36Sopenharmony_ci					    sec4_sg_bytes, DMA_TO_DEVICE);
98362306a36Sopenharmony_ci	if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
98462306a36Sopenharmony_ci		dev_err(jrdev, "unable to map S/G table\n");
98562306a36Sopenharmony_ci		ret = -ENOMEM;
98662306a36Sopenharmony_ci		goto unmap_ctx;
98762306a36Sopenharmony_ci	}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
99062306a36Sopenharmony_ci			  LDST_SGF);
99162306a36Sopenharmony_ci	append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
99462306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
99562306a36Sopenharmony_ci			     1);
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req,
99862306a36Sopenharmony_ci				 digestsize, DMA_BIDIRECTIONAL);
99962306a36Sopenharmony_ci unmap_ctx:
100062306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
100162306a36Sopenharmony_ci	kfree(edesc);
100262306a36Sopenharmony_ci	return ret;
100362306a36Sopenharmony_ci}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_cistatic int ahash_finup_ctx(struct ahash_request *req)
100662306a36Sopenharmony_ci{
100762306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
100862306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
100962306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
101062306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
101162306a36Sopenharmony_ci	int buflen = state->buflen;
101262306a36Sopenharmony_ci	u32 *desc;
101362306a36Sopenharmony_ci	int sec4_sg_src_index;
101462306a36Sopenharmony_ci	int src_nents, mapped_nents;
101562306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
101662306a36Sopenharmony_ci	struct ahash_edesc *edesc;
101762306a36Sopenharmony_ci	int ret;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	src_nents = sg_nents_for_len(req->src, req->nbytes);
102062306a36Sopenharmony_ci	if (src_nents < 0) {
102162306a36Sopenharmony_ci		dev_err(jrdev, "Invalid number of src SG.\n");
102262306a36Sopenharmony_ci		return src_nents;
102362306a36Sopenharmony_ci	}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	if (src_nents) {
102662306a36Sopenharmony_ci		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
102762306a36Sopenharmony_ci					  DMA_TO_DEVICE);
102862306a36Sopenharmony_ci		if (!mapped_nents) {
102962306a36Sopenharmony_ci			dev_err(jrdev, "unable to DMA map source\n");
103062306a36Sopenharmony_ci			return -ENOMEM;
103162306a36Sopenharmony_ci		}
103262306a36Sopenharmony_ci	} else {
103362306a36Sopenharmony_ci		mapped_nents = 0;
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	sec4_sg_src_index = 1 + (buflen ? 1 : 0);
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
103962306a36Sopenharmony_ci	edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents,
104062306a36Sopenharmony_ci				  ctx->sh_desc_fin, ctx->sh_desc_fin_dma);
104162306a36Sopenharmony_ci	if (!edesc) {
104262306a36Sopenharmony_ci		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
104362306a36Sopenharmony_ci		return -ENOMEM;
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	desc = edesc->hw_desc;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	edesc->src_nents = src_nents;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
105162306a36Sopenharmony_ci				 edesc->sec4_sg, DMA_BIDIRECTIONAL);
105262306a36Sopenharmony_ci	if (ret)
105362306a36Sopenharmony_ci		goto unmap_ctx;
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
105662306a36Sopenharmony_ci	if (ret)
105762306a36Sopenharmony_ci		goto unmap_ctx;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents,
106062306a36Sopenharmony_ci				  sec4_sg_src_index, ctx->ctx_len + buflen,
106162306a36Sopenharmony_ci				  req->nbytes);
106262306a36Sopenharmony_ci	if (ret)
106362306a36Sopenharmony_ci		goto unmap_ctx;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
106862306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
106962306a36Sopenharmony_ci			     1);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req,
107262306a36Sopenharmony_ci				 digestsize, DMA_BIDIRECTIONAL);
107362306a36Sopenharmony_ci unmap_ctx:
107462306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
107562306a36Sopenharmony_ci	kfree(edesc);
107662306a36Sopenharmony_ci	return ret;
107762306a36Sopenharmony_ci}
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_cistatic int ahash_digest(struct ahash_request *req)
108062306a36Sopenharmony_ci{
108162306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
108262306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
108362306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
108462306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
108562306a36Sopenharmony_ci	u32 *desc;
108662306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
108762306a36Sopenharmony_ci	int src_nents, mapped_nents;
108862306a36Sopenharmony_ci	struct ahash_edesc *edesc;
108962306a36Sopenharmony_ci	int ret;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	state->buf_dma = 0;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	src_nents = sg_nents_for_len(req->src, req->nbytes);
109462306a36Sopenharmony_ci	if (src_nents < 0) {
109562306a36Sopenharmony_ci		dev_err(jrdev, "Invalid number of src SG.\n");
109662306a36Sopenharmony_ci		return src_nents;
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	if (src_nents) {
110062306a36Sopenharmony_ci		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
110162306a36Sopenharmony_ci					  DMA_TO_DEVICE);
110262306a36Sopenharmony_ci		if (!mapped_nents) {
110362306a36Sopenharmony_ci			dev_err(jrdev, "unable to map source for DMA\n");
110462306a36Sopenharmony_ci			return -ENOMEM;
110562306a36Sopenharmony_ci		}
110662306a36Sopenharmony_ci	} else {
110762306a36Sopenharmony_ci		mapped_nents = 0;
110862306a36Sopenharmony_ci	}
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
111162306a36Sopenharmony_ci	edesc = ahash_edesc_alloc(req, mapped_nents > 1 ? mapped_nents : 0,
111262306a36Sopenharmony_ci				  ctx->sh_desc_digest, ctx->sh_desc_digest_dma);
111362306a36Sopenharmony_ci	if (!edesc) {
111462306a36Sopenharmony_ci		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
111562306a36Sopenharmony_ci		return -ENOMEM;
111662306a36Sopenharmony_ci	}
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	edesc->src_nents = src_nents;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
112162306a36Sopenharmony_ci				  req->nbytes);
112262306a36Sopenharmony_ci	if (ret) {
112362306a36Sopenharmony_ci		ahash_unmap(jrdev, edesc, req, digestsize);
112462306a36Sopenharmony_ci		kfree(edesc);
112562306a36Sopenharmony_ci		return ret;
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	desc = edesc->hw_desc;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
113162306a36Sopenharmony_ci	if (ret) {
113262306a36Sopenharmony_ci		ahash_unmap(jrdev, edesc, req, digestsize);
113362306a36Sopenharmony_ci		kfree(edesc);
113462306a36Sopenharmony_ci		return -ENOMEM;
113562306a36Sopenharmony_ci	}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
113862306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
113962306a36Sopenharmony_ci			     1);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done, req, digestsize,
114262306a36Sopenharmony_ci				 DMA_FROM_DEVICE);
114362306a36Sopenharmony_ci}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci/* submit ahash final if it the first job descriptor */
114662306a36Sopenharmony_cistatic int ahash_final_no_ctx(struct ahash_request *req)
114762306a36Sopenharmony_ci{
114862306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
114962306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
115062306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
115162306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
115262306a36Sopenharmony_ci	u8 *buf = state->buf;
115362306a36Sopenharmony_ci	int buflen = state->buflen;
115462306a36Sopenharmony_ci	u32 *desc;
115562306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
115662306a36Sopenharmony_ci	struct ahash_edesc *edesc;
115762306a36Sopenharmony_ci	int ret;
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
116062306a36Sopenharmony_ci	edesc = ahash_edesc_alloc(req, 0, ctx->sh_desc_digest,
116162306a36Sopenharmony_ci				  ctx->sh_desc_digest_dma);
116262306a36Sopenharmony_ci	if (!edesc)
116362306a36Sopenharmony_ci		return -ENOMEM;
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	desc = edesc->hw_desc;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	if (buflen) {
116862306a36Sopenharmony_ci		state->buf_dma = dma_map_single(jrdev, buf, buflen,
116962306a36Sopenharmony_ci						DMA_TO_DEVICE);
117062306a36Sopenharmony_ci		if (dma_mapping_error(jrdev, state->buf_dma)) {
117162306a36Sopenharmony_ci			dev_err(jrdev, "unable to map src\n");
117262306a36Sopenharmony_ci			goto unmap;
117362306a36Sopenharmony_ci		}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci		append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
117662306a36Sopenharmony_ci	}
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
117962306a36Sopenharmony_ci	if (ret)
118062306a36Sopenharmony_ci		goto unmap;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
118362306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
118462306a36Sopenharmony_ci			     1);
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done, req,
118762306a36Sopenharmony_ci				 digestsize, DMA_FROM_DEVICE);
118862306a36Sopenharmony_ci unmap:
118962306a36Sopenharmony_ci	ahash_unmap(jrdev, edesc, req, digestsize);
119062306a36Sopenharmony_ci	kfree(edesc);
119162306a36Sopenharmony_ci	return -ENOMEM;
119262306a36Sopenharmony_ci}
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci/* submit ahash update if it the first job descriptor after update */
119562306a36Sopenharmony_cistatic int ahash_update_no_ctx(struct ahash_request *req)
119662306a36Sopenharmony_ci{
119762306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
119862306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
119962306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
120062306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
120162306a36Sopenharmony_ci	u8 *buf = state->buf;
120262306a36Sopenharmony_ci	int *buflen = &state->buflen;
120362306a36Sopenharmony_ci	int *next_buflen = &state->next_buflen;
120462306a36Sopenharmony_ci	int blocksize = crypto_ahash_blocksize(ahash);
120562306a36Sopenharmony_ci	int in_len = *buflen + req->nbytes, to_hash;
120662306a36Sopenharmony_ci	int sec4_sg_bytes, src_nents, mapped_nents;
120762306a36Sopenharmony_ci	struct ahash_edesc *edesc;
120862306a36Sopenharmony_ci	u32 *desc;
120962306a36Sopenharmony_ci	int ret = 0;
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	*next_buflen = in_len & (blocksize - 1);
121262306a36Sopenharmony_ci	to_hash = in_len - *next_buflen;
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	/*
121562306a36Sopenharmony_ci	 * For XCBC and CMAC, if to_hash is multiple of block size,
121662306a36Sopenharmony_ci	 * keep last block in internal buffer
121762306a36Sopenharmony_ci	 */
121862306a36Sopenharmony_ci	if ((is_xcbc_aes(ctx->adata.algtype) ||
121962306a36Sopenharmony_ci	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
122062306a36Sopenharmony_ci	     (*next_buflen == 0)) {
122162306a36Sopenharmony_ci		*next_buflen = blocksize;
122262306a36Sopenharmony_ci		to_hash -= blocksize;
122362306a36Sopenharmony_ci	}
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	if (to_hash) {
122662306a36Sopenharmony_ci		int pad_nents;
122762306a36Sopenharmony_ci		int src_len = req->nbytes - *next_buflen;
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci		src_nents = sg_nents_for_len(req->src, src_len);
123062306a36Sopenharmony_ci		if (src_nents < 0) {
123162306a36Sopenharmony_ci			dev_err(jrdev, "Invalid number of src SG.\n");
123262306a36Sopenharmony_ci			return src_nents;
123362306a36Sopenharmony_ci		}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci		if (src_nents) {
123662306a36Sopenharmony_ci			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
123762306a36Sopenharmony_ci						  DMA_TO_DEVICE);
123862306a36Sopenharmony_ci			if (!mapped_nents) {
123962306a36Sopenharmony_ci				dev_err(jrdev, "unable to DMA map source\n");
124062306a36Sopenharmony_ci				return -ENOMEM;
124162306a36Sopenharmony_ci			}
124262306a36Sopenharmony_ci		} else {
124362306a36Sopenharmony_ci			mapped_nents = 0;
124462306a36Sopenharmony_ci		}
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci		pad_nents = pad_sg_nents(1 + mapped_nents);
124762306a36Sopenharmony_ci		sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci		/*
125062306a36Sopenharmony_ci		 * allocate space for base edesc and hw desc commands,
125162306a36Sopenharmony_ci		 * link tables
125262306a36Sopenharmony_ci		 */
125362306a36Sopenharmony_ci		edesc = ahash_edesc_alloc(req, pad_nents,
125462306a36Sopenharmony_ci					  ctx->sh_desc_update_first,
125562306a36Sopenharmony_ci					  ctx->sh_desc_update_first_dma);
125662306a36Sopenharmony_ci		if (!edesc) {
125762306a36Sopenharmony_ci			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
125862306a36Sopenharmony_ci			return -ENOMEM;
125962306a36Sopenharmony_ci		}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci		edesc->src_nents = src_nents;
126262306a36Sopenharmony_ci		edesc->sec4_sg_bytes = sec4_sg_bytes;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci		ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
126562306a36Sopenharmony_ci		if (ret)
126662306a36Sopenharmony_ci			goto unmap_ctx;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci		sg_to_sec4_sg_last(req->src, src_len, edesc->sec4_sg + 1, 0);
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci		desc = edesc->hw_desc;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
127362306a36Sopenharmony_ci						    sec4_sg_bytes,
127462306a36Sopenharmony_ci						    DMA_TO_DEVICE);
127562306a36Sopenharmony_ci		if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
127662306a36Sopenharmony_ci			dev_err(jrdev, "unable to map S/G table\n");
127762306a36Sopenharmony_ci			ret = -ENOMEM;
127862306a36Sopenharmony_ci			goto unmap_ctx;
127962306a36Sopenharmony_ci		}
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci		append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
128462306a36Sopenharmony_ci		if (ret)
128562306a36Sopenharmony_ci			goto unmap_ctx;
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
128862306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
128962306a36Sopenharmony_ci				     desc_bytes(desc), 1);
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci		ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req,
129262306a36Sopenharmony_ci					ctx->ctx_len, DMA_TO_DEVICE);
129362306a36Sopenharmony_ci		if ((ret != -EINPROGRESS) && (ret != -EBUSY))
129462306a36Sopenharmony_ci			return ret;
129562306a36Sopenharmony_ci		state->update = ahash_update_ctx;
129662306a36Sopenharmony_ci		state->finup = ahash_finup_ctx;
129762306a36Sopenharmony_ci		state->final = ahash_final_ctx;
129862306a36Sopenharmony_ci	} else if (*next_buflen) {
129962306a36Sopenharmony_ci		scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
130062306a36Sopenharmony_ci					 req->nbytes, 0);
130162306a36Sopenharmony_ci		*buflen = *next_buflen;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
130462306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
130562306a36Sopenharmony_ci				     *buflen, 1);
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	return ret;
130962306a36Sopenharmony_ci unmap_ctx:
131062306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
131162306a36Sopenharmony_ci	kfree(edesc);
131262306a36Sopenharmony_ci	return ret;
131362306a36Sopenharmony_ci}
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci/* submit ahash finup if it the first job descriptor after update */
131662306a36Sopenharmony_cistatic int ahash_finup_no_ctx(struct ahash_request *req)
131762306a36Sopenharmony_ci{
131862306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
131962306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
132062306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
132162306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
132262306a36Sopenharmony_ci	int buflen = state->buflen;
132362306a36Sopenharmony_ci	u32 *desc;
132462306a36Sopenharmony_ci	int sec4_sg_bytes, sec4_sg_src_index, src_nents, mapped_nents;
132562306a36Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
132662306a36Sopenharmony_ci	struct ahash_edesc *edesc;
132762306a36Sopenharmony_ci	int ret;
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	src_nents = sg_nents_for_len(req->src, req->nbytes);
133062306a36Sopenharmony_ci	if (src_nents < 0) {
133162306a36Sopenharmony_ci		dev_err(jrdev, "Invalid number of src SG.\n");
133262306a36Sopenharmony_ci		return src_nents;
133362306a36Sopenharmony_ci	}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	if (src_nents) {
133662306a36Sopenharmony_ci		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
133762306a36Sopenharmony_ci					  DMA_TO_DEVICE);
133862306a36Sopenharmony_ci		if (!mapped_nents) {
133962306a36Sopenharmony_ci			dev_err(jrdev, "unable to DMA map source\n");
134062306a36Sopenharmony_ci			return -ENOMEM;
134162306a36Sopenharmony_ci		}
134262306a36Sopenharmony_ci	} else {
134362306a36Sopenharmony_ci		mapped_nents = 0;
134462306a36Sopenharmony_ci	}
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	sec4_sg_src_index = 2;
134762306a36Sopenharmony_ci	sec4_sg_bytes = (sec4_sg_src_index + mapped_nents) *
134862306a36Sopenharmony_ci			 sizeof(struct sec4_sg_entry);
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
135162306a36Sopenharmony_ci	edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents,
135262306a36Sopenharmony_ci				  ctx->sh_desc_digest, ctx->sh_desc_digest_dma);
135362306a36Sopenharmony_ci	if (!edesc) {
135462306a36Sopenharmony_ci		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
135562306a36Sopenharmony_ci		return -ENOMEM;
135662306a36Sopenharmony_ci	}
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	desc = edesc->hw_desc;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	edesc->src_nents = src_nents;
136162306a36Sopenharmony_ci	edesc->sec4_sg_bytes = sec4_sg_bytes;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
136462306a36Sopenharmony_ci	if (ret)
136562306a36Sopenharmony_ci		goto unmap;
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 1, buflen,
136862306a36Sopenharmony_ci				  req->nbytes);
136962306a36Sopenharmony_ci	if (ret) {
137062306a36Sopenharmony_ci		dev_err(jrdev, "unable to map S/G table\n");
137162306a36Sopenharmony_ci		goto unmap;
137262306a36Sopenharmony_ci	}
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
137562306a36Sopenharmony_ci	if (ret)
137662306a36Sopenharmony_ci		goto unmap;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
137962306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
138062306a36Sopenharmony_ci			     1);
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done, req,
138362306a36Sopenharmony_ci				 digestsize, DMA_FROM_DEVICE);
138462306a36Sopenharmony_ci unmap:
138562306a36Sopenharmony_ci	ahash_unmap(jrdev, edesc, req, digestsize);
138662306a36Sopenharmony_ci	kfree(edesc);
138762306a36Sopenharmony_ci	return -ENOMEM;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci}
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci/* submit first update job descriptor after init */
139262306a36Sopenharmony_cistatic int ahash_update_first(struct ahash_request *req)
139362306a36Sopenharmony_ci{
139462306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
139562306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
139662306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
139762306a36Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
139862306a36Sopenharmony_ci	u8 *buf = state->buf;
139962306a36Sopenharmony_ci	int *buflen = &state->buflen;
140062306a36Sopenharmony_ci	int *next_buflen = &state->next_buflen;
140162306a36Sopenharmony_ci	int to_hash;
140262306a36Sopenharmony_ci	int blocksize = crypto_ahash_blocksize(ahash);
140362306a36Sopenharmony_ci	u32 *desc;
140462306a36Sopenharmony_ci	int src_nents, mapped_nents;
140562306a36Sopenharmony_ci	struct ahash_edesc *edesc;
140662306a36Sopenharmony_ci	int ret = 0;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	*next_buflen = req->nbytes & (blocksize - 1);
140962306a36Sopenharmony_ci	to_hash = req->nbytes - *next_buflen;
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	/*
141262306a36Sopenharmony_ci	 * For XCBC and CMAC, if to_hash is multiple of block size,
141362306a36Sopenharmony_ci	 * keep last block in internal buffer
141462306a36Sopenharmony_ci	 */
141562306a36Sopenharmony_ci	if ((is_xcbc_aes(ctx->adata.algtype) ||
141662306a36Sopenharmony_ci	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
141762306a36Sopenharmony_ci	     (*next_buflen == 0)) {
141862306a36Sopenharmony_ci		*next_buflen = blocksize;
141962306a36Sopenharmony_ci		to_hash -= blocksize;
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	if (to_hash) {
142362306a36Sopenharmony_ci		src_nents = sg_nents_for_len(req->src,
142462306a36Sopenharmony_ci					     req->nbytes - *next_buflen);
142562306a36Sopenharmony_ci		if (src_nents < 0) {
142662306a36Sopenharmony_ci			dev_err(jrdev, "Invalid number of src SG.\n");
142762306a36Sopenharmony_ci			return src_nents;
142862306a36Sopenharmony_ci		}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci		if (src_nents) {
143162306a36Sopenharmony_ci			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
143262306a36Sopenharmony_ci						  DMA_TO_DEVICE);
143362306a36Sopenharmony_ci			if (!mapped_nents) {
143462306a36Sopenharmony_ci				dev_err(jrdev, "unable to map source for DMA\n");
143562306a36Sopenharmony_ci				return -ENOMEM;
143662306a36Sopenharmony_ci			}
143762306a36Sopenharmony_ci		} else {
143862306a36Sopenharmony_ci			mapped_nents = 0;
143962306a36Sopenharmony_ci		}
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci		/*
144262306a36Sopenharmony_ci		 * allocate space for base edesc and hw desc commands,
144362306a36Sopenharmony_ci		 * link tables
144462306a36Sopenharmony_ci		 */
144562306a36Sopenharmony_ci		edesc = ahash_edesc_alloc(req, mapped_nents > 1 ?
144662306a36Sopenharmony_ci					  mapped_nents : 0,
144762306a36Sopenharmony_ci					  ctx->sh_desc_update_first,
144862306a36Sopenharmony_ci					  ctx->sh_desc_update_first_dma);
144962306a36Sopenharmony_ci		if (!edesc) {
145062306a36Sopenharmony_ci			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
145162306a36Sopenharmony_ci			return -ENOMEM;
145262306a36Sopenharmony_ci		}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci		edesc->src_nents = src_nents;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci		ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
145762306a36Sopenharmony_ci					  to_hash);
145862306a36Sopenharmony_ci		if (ret)
145962306a36Sopenharmony_ci			goto unmap_ctx;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci		desc = edesc->hw_desc;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
146462306a36Sopenharmony_ci		if (ret)
146562306a36Sopenharmony_ci			goto unmap_ctx;
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
146862306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
146962306a36Sopenharmony_ci				     desc_bytes(desc), 1);
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci		ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req,
147262306a36Sopenharmony_ci					ctx->ctx_len, DMA_TO_DEVICE);
147362306a36Sopenharmony_ci		if ((ret != -EINPROGRESS) && (ret != -EBUSY))
147462306a36Sopenharmony_ci			return ret;
147562306a36Sopenharmony_ci		state->update = ahash_update_ctx;
147662306a36Sopenharmony_ci		state->finup = ahash_finup_ctx;
147762306a36Sopenharmony_ci		state->final = ahash_final_ctx;
147862306a36Sopenharmony_ci	} else if (*next_buflen) {
147962306a36Sopenharmony_ci		state->update = ahash_update_no_ctx;
148062306a36Sopenharmony_ci		state->finup = ahash_finup_no_ctx;
148162306a36Sopenharmony_ci		state->final = ahash_final_no_ctx;
148262306a36Sopenharmony_ci		scatterwalk_map_and_copy(buf, req->src, 0,
148362306a36Sopenharmony_ci					 req->nbytes, 0);
148462306a36Sopenharmony_ci		*buflen = *next_buflen;
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
148762306a36Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
148862306a36Sopenharmony_ci				     *buflen, 1);
148962306a36Sopenharmony_ci	}
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	return ret;
149262306a36Sopenharmony_ci unmap_ctx:
149362306a36Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
149462306a36Sopenharmony_ci	kfree(edesc);
149562306a36Sopenharmony_ci	return ret;
149662306a36Sopenharmony_ci}
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_cistatic int ahash_finup_first(struct ahash_request *req)
149962306a36Sopenharmony_ci{
150062306a36Sopenharmony_ci	return ahash_digest(req);
150162306a36Sopenharmony_ci}
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_cistatic int ahash_init(struct ahash_request *req)
150462306a36Sopenharmony_ci{
150562306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	state->update = ahash_update_first;
150862306a36Sopenharmony_ci	state->finup = ahash_finup_first;
150962306a36Sopenharmony_ci	state->final = ahash_final_no_ctx;
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	state->ctx_dma = 0;
151262306a36Sopenharmony_ci	state->ctx_dma_len = 0;
151362306a36Sopenharmony_ci	state->buf_dma = 0;
151462306a36Sopenharmony_ci	state->buflen = 0;
151562306a36Sopenharmony_ci	state->next_buflen = 0;
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	return 0;
151862306a36Sopenharmony_ci}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_cistatic int ahash_update(struct ahash_request *req)
152162306a36Sopenharmony_ci{
152262306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	return state->update(req);
152562306a36Sopenharmony_ci}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_cistatic int ahash_finup(struct ahash_request *req)
152862306a36Sopenharmony_ci{
152962306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	return state->finup(req);
153262306a36Sopenharmony_ci}
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_cistatic int ahash_final(struct ahash_request *req)
153562306a36Sopenharmony_ci{
153662306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	return state->final(req);
153962306a36Sopenharmony_ci}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_cistatic int ahash_export(struct ahash_request *req, void *out)
154262306a36Sopenharmony_ci{
154362306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
154462306a36Sopenharmony_ci	struct caam_export_state *export = out;
154562306a36Sopenharmony_ci	u8 *buf = state->buf;
154662306a36Sopenharmony_ci	int len = state->buflen;
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	memcpy(export->buf, buf, len);
154962306a36Sopenharmony_ci	memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx));
155062306a36Sopenharmony_ci	export->buflen = len;
155162306a36Sopenharmony_ci	export->update = state->update;
155262306a36Sopenharmony_ci	export->final = state->final;
155362306a36Sopenharmony_ci	export->finup = state->finup;
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	return 0;
155662306a36Sopenharmony_ci}
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_cistatic int ahash_import(struct ahash_request *req, const void *in)
155962306a36Sopenharmony_ci{
156062306a36Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx_dma(req);
156162306a36Sopenharmony_ci	const struct caam_export_state *export = in;
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	memset(state, 0, sizeof(*state));
156462306a36Sopenharmony_ci	memcpy(state->buf, export->buf, export->buflen);
156562306a36Sopenharmony_ci	memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx));
156662306a36Sopenharmony_ci	state->buflen = export->buflen;
156762306a36Sopenharmony_ci	state->update = export->update;
156862306a36Sopenharmony_ci	state->final = export->final;
156962306a36Sopenharmony_ci	state->finup = export->finup;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	return 0;
157262306a36Sopenharmony_ci}
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_cistruct caam_hash_template {
157562306a36Sopenharmony_ci	char name[CRYPTO_MAX_ALG_NAME];
157662306a36Sopenharmony_ci	char driver_name[CRYPTO_MAX_ALG_NAME];
157762306a36Sopenharmony_ci	char hmac_name[CRYPTO_MAX_ALG_NAME];
157862306a36Sopenharmony_ci	char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
157962306a36Sopenharmony_ci	unsigned int blocksize;
158062306a36Sopenharmony_ci	struct ahash_alg template_ahash;
158162306a36Sopenharmony_ci	u32 alg_type;
158262306a36Sopenharmony_ci};
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci/* ahash descriptors */
158562306a36Sopenharmony_cistatic struct caam_hash_template driver_hash[] = {
158662306a36Sopenharmony_ci	{
158762306a36Sopenharmony_ci		.name = "sha1",
158862306a36Sopenharmony_ci		.driver_name = "sha1-caam",
158962306a36Sopenharmony_ci		.hmac_name = "hmac(sha1)",
159062306a36Sopenharmony_ci		.hmac_driver_name = "hmac-sha1-caam",
159162306a36Sopenharmony_ci		.blocksize = SHA1_BLOCK_SIZE,
159262306a36Sopenharmony_ci		.template_ahash = {
159362306a36Sopenharmony_ci			.init = ahash_init,
159462306a36Sopenharmony_ci			.update = ahash_update,
159562306a36Sopenharmony_ci			.final = ahash_final,
159662306a36Sopenharmony_ci			.finup = ahash_finup,
159762306a36Sopenharmony_ci			.digest = ahash_digest,
159862306a36Sopenharmony_ci			.export = ahash_export,
159962306a36Sopenharmony_ci			.import = ahash_import,
160062306a36Sopenharmony_ci			.setkey = ahash_setkey,
160162306a36Sopenharmony_ci			.halg = {
160262306a36Sopenharmony_ci				.digestsize = SHA1_DIGEST_SIZE,
160362306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
160462306a36Sopenharmony_ci			},
160562306a36Sopenharmony_ci		},
160662306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA1,
160762306a36Sopenharmony_ci	}, {
160862306a36Sopenharmony_ci		.name = "sha224",
160962306a36Sopenharmony_ci		.driver_name = "sha224-caam",
161062306a36Sopenharmony_ci		.hmac_name = "hmac(sha224)",
161162306a36Sopenharmony_ci		.hmac_driver_name = "hmac-sha224-caam",
161262306a36Sopenharmony_ci		.blocksize = SHA224_BLOCK_SIZE,
161362306a36Sopenharmony_ci		.template_ahash = {
161462306a36Sopenharmony_ci			.init = ahash_init,
161562306a36Sopenharmony_ci			.update = ahash_update,
161662306a36Sopenharmony_ci			.final = ahash_final,
161762306a36Sopenharmony_ci			.finup = ahash_finup,
161862306a36Sopenharmony_ci			.digest = ahash_digest,
161962306a36Sopenharmony_ci			.export = ahash_export,
162062306a36Sopenharmony_ci			.import = ahash_import,
162162306a36Sopenharmony_ci			.setkey = ahash_setkey,
162262306a36Sopenharmony_ci			.halg = {
162362306a36Sopenharmony_ci				.digestsize = SHA224_DIGEST_SIZE,
162462306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
162562306a36Sopenharmony_ci			},
162662306a36Sopenharmony_ci		},
162762306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA224,
162862306a36Sopenharmony_ci	}, {
162962306a36Sopenharmony_ci		.name = "sha256",
163062306a36Sopenharmony_ci		.driver_name = "sha256-caam",
163162306a36Sopenharmony_ci		.hmac_name = "hmac(sha256)",
163262306a36Sopenharmony_ci		.hmac_driver_name = "hmac-sha256-caam",
163362306a36Sopenharmony_ci		.blocksize = SHA256_BLOCK_SIZE,
163462306a36Sopenharmony_ci		.template_ahash = {
163562306a36Sopenharmony_ci			.init = ahash_init,
163662306a36Sopenharmony_ci			.update = ahash_update,
163762306a36Sopenharmony_ci			.final = ahash_final,
163862306a36Sopenharmony_ci			.finup = ahash_finup,
163962306a36Sopenharmony_ci			.digest = ahash_digest,
164062306a36Sopenharmony_ci			.export = ahash_export,
164162306a36Sopenharmony_ci			.import = ahash_import,
164262306a36Sopenharmony_ci			.setkey = ahash_setkey,
164362306a36Sopenharmony_ci			.halg = {
164462306a36Sopenharmony_ci				.digestsize = SHA256_DIGEST_SIZE,
164562306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
164662306a36Sopenharmony_ci			},
164762306a36Sopenharmony_ci		},
164862306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA256,
164962306a36Sopenharmony_ci	}, {
165062306a36Sopenharmony_ci		.name = "sha384",
165162306a36Sopenharmony_ci		.driver_name = "sha384-caam",
165262306a36Sopenharmony_ci		.hmac_name = "hmac(sha384)",
165362306a36Sopenharmony_ci		.hmac_driver_name = "hmac-sha384-caam",
165462306a36Sopenharmony_ci		.blocksize = SHA384_BLOCK_SIZE,
165562306a36Sopenharmony_ci		.template_ahash = {
165662306a36Sopenharmony_ci			.init = ahash_init,
165762306a36Sopenharmony_ci			.update = ahash_update,
165862306a36Sopenharmony_ci			.final = ahash_final,
165962306a36Sopenharmony_ci			.finup = ahash_finup,
166062306a36Sopenharmony_ci			.digest = ahash_digest,
166162306a36Sopenharmony_ci			.export = ahash_export,
166262306a36Sopenharmony_ci			.import = ahash_import,
166362306a36Sopenharmony_ci			.setkey = ahash_setkey,
166462306a36Sopenharmony_ci			.halg = {
166562306a36Sopenharmony_ci				.digestsize = SHA384_DIGEST_SIZE,
166662306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
166762306a36Sopenharmony_ci			},
166862306a36Sopenharmony_ci		},
166962306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA384,
167062306a36Sopenharmony_ci	}, {
167162306a36Sopenharmony_ci		.name = "sha512",
167262306a36Sopenharmony_ci		.driver_name = "sha512-caam",
167362306a36Sopenharmony_ci		.hmac_name = "hmac(sha512)",
167462306a36Sopenharmony_ci		.hmac_driver_name = "hmac-sha512-caam",
167562306a36Sopenharmony_ci		.blocksize = SHA512_BLOCK_SIZE,
167662306a36Sopenharmony_ci		.template_ahash = {
167762306a36Sopenharmony_ci			.init = ahash_init,
167862306a36Sopenharmony_ci			.update = ahash_update,
167962306a36Sopenharmony_ci			.final = ahash_final,
168062306a36Sopenharmony_ci			.finup = ahash_finup,
168162306a36Sopenharmony_ci			.digest = ahash_digest,
168262306a36Sopenharmony_ci			.export = ahash_export,
168362306a36Sopenharmony_ci			.import = ahash_import,
168462306a36Sopenharmony_ci			.setkey = ahash_setkey,
168562306a36Sopenharmony_ci			.halg = {
168662306a36Sopenharmony_ci				.digestsize = SHA512_DIGEST_SIZE,
168762306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
168862306a36Sopenharmony_ci			},
168962306a36Sopenharmony_ci		},
169062306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA512,
169162306a36Sopenharmony_ci	}, {
169262306a36Sopenharmony_ci		.name = "md5",
169362306a36Sopenharmony_ci		.driver_name = "md5-caam",
169462306a36Sopenharmony_ci		.hmac_name = "hmac(md5)",
169562306a36Sopenharmony_ci		.hmac_driver_name = "hmac-md5-caam",
169662306a36Sopenharmony_ci		.blocksize = MD5_BLOCK_WORDS * 4,
169762306a36Sopenharmony_ci		.template_ahash = {
169862306a36Sopenharmony_ci			.init = ahash_init,
169962306a36Sopenharmony_ci			.update = ahash_update,
170062306a36Sopenharmony_ci			.final = ahash_final,
170162306a36Sopenharmony_ci			.finup = ahash_finup,
170262306a36Sopenharmony_ci			.digest = ahash_digest,
170362306a36Sopenharmony_ci			.export = ahash_export,
170462306a36Sopenharmony_ci			.import = ahash_import,
170562306a36Sopenharmony_ci			.setkey = ahash_setkey,
170662306a36Sopenharmony_ci			.halg = {
170762306a36Sopenharmony_ci				.digestsize = MD5_DIGEST_SIZE,
170862306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
170962306a36Sopenharmony_ci			},
171062306a36Sopenharmony_ci		},
171162306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_MD5,
171262306a36Sopenharmony_ci	}, {
171362306a36Sopenharmony_ci		.hmac_name = "xcbc(aes)",
171462306a36Sopenharmony_ci		.hmac_driver_name = "xcbc-aes-caam",
171562306a36Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
171662306a36Sopenharmony_ci		.template_ahash = {
171762306a36Sopenharmony_ci			.init = ahash_init,
171862306a36Sopenharmony_ci			.update = ahash_update,
171962306a36Sopenharmony_ci			.final = ahash_final,
172062306a36Sopenharmony_ci			.finup = ahash_finup,
172162306a36Sopenharmony_ci			.digest = ahash_digest,
172262306a36Sopenharmony_ci			.export = ahash_export,
172362306a36Sopenharmony_ci			.import = ahash_import,
172462306a36Sopenharmony_ci			.setkey = axcbc_setkey,
172562306a36Sopenharmony_ci			.halg = {
172662306a36Sopenharmony_ci				.digestsize = AES_BLOCK_SIZE,
172762306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
172862306a36Sopenharmony_ci			},
172962306a36Sopenharmony_ci		 },
173062306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
173162306a36Sopenharmony_ci	}, {
173262306a36Sopenharmony_ci		.hmac_name = "cmac(aes)",
173362306a36Sopenharmony_ci		.hmac_driver_name = "cmac-aes-caam",
173462306a36Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
173562306a36Sopenharmony_ci		.template_ahash = {
173662306a36Sopenharmony_ci			.init = ahash_init,
173762306a36Sopenharmony_ci			.update = ahash_update,
173862306a36Sopenharmony_ci			.final = ahash_final,
173962306a36Sopenharmony_ci			.finup = ahash_finup,
174062306a36Sopenharmony_ci			.digest = ahash_digest,
174162306a36Sopenharmony_ci			.export = ahash_export,
174262306a36Sopenharmony_ci			.import = ahash_import,
174362306a36Sopenharmony_ci			.setkey = acmac_setkey,
174462306a36Sopenharmony_ci			.halg = {
174562306a36Sopenharmony_ci				.digestsize = AES_BLOCK_SIZE,
174662306a36Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
174762306a36Sopenharmony_ci			},
174862306a36Sopenharmony_ci		 },
174962306a36Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC,
175062306a36Sopenharmony_ci	},
175162306a36Sopenharmony_ci};
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_cistruct caam_hash_alg {
175462306a36Sopenharmony_ci	struct list_head entry;
175562306a36Sopenharmony_ci	int alg_type;
175662306a36Sopenharmony_ci	struct ahash_engine_alg ahash_alg;
175762306a36Sopenharmony_ci};
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_cistatic int caam_hash_cra_init(struct crypto_tfm *tfm)
176062306a36Sopenharmony_ci{
176162306a36Sopenharmony_ci	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
176262306a36Sopenharmony_ci	struct crypto_alg *base = tfm->__crt_alg;
176362306a36Sopenharmony_ci	struct hash_alg_common *halg =
176462306a36Sopenharmony_ci		 container_of(base, struct hash_alg_common, base);
176562306a36Sopenharmony_ci	struct ahash_alg *alg =
176662306a36Sopenharmony_ci		 container_of(halg, struct ahash_alg, halg);
176762306a36Sopenharmony_ci	struct caam_hash_alg *caam_hash =
176862306a36Sopenharmony_ci		 container_of(alg, struct caam_hash_alg, ahash_alg.base);
176962306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
177062306a36Sopenharmony_ci	/* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
177162306a36Sopenharmony_ci	static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
177262306a36Sopenharmony_ci					 HASH_MSG_LEN + SHA1_DIGEST_SIZE,
177362306a36Sopenharmony_ci					 HASH_MSG_LEN + 32,
177462306a36Sopenharmony_ci					 HASH_MSG_LEN + SHA256_DIGEST_SIZE,
177562306a36Sopenharmony_ci					 HASH_MSG_LEN + 64,
177662306a36Sopenharmony_ci					 HASH_MSG_LEN + SHA512_DIGEST_SIZE };
177762306a36Sopenharmony_ci	const size_t sh_desc_update_offset = offsetof(struct caam_hash_ctx,
177862306a36Sopenharmony_ci						      sh_desc_update);
177962306a36Sopenharmony_ci	dma_addr_t dma_addr;
178062306a36Sopenharmony_ci	struct caam_drv_private *priv;
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	/*
178362306a36Sopenharmony_ci	 * Get a Job ring from Job Ring driver to ensure in-order
178462306a36Sopenharmony_ci	 * crypto request processing per tfm
178562306a36Sopenharmony_ci	 */
178662306a36Sopenharmony_ci	ctx->jrdev = caam_jr_alloc();
178762306a36Sopenharmony_ci	if (IS_ERR(ctx->jrdev)) {
178862306a36Sopenharmony_ci		pr_err("Job Ring Device allocation for transform failed\n");
178962306a36Sopenharmony_ci		return PTR_ERR(ctx->jrdev);
179062306a36Sopenharmony_ci	}
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci	priv = dev_get_drvdata(ctx->jrdev->parent);
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	if (is_xcbc_aes(caam_hash->alg_type)) {
179562306a36Sopenharmony_ci		ctx->dir = DMA_TO_DEVICE;
179662306a36Sopenharmony_ci		ctx->key_dir = DMA_BIDIRECTIONAL;
179762306a36Sopenharmony_ci		ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
179862306a36Sopenharmony_ci		ctx->ctx_len = 48;
179962306a36Sopenharmony_ci	} else if (is_cmac_aes(caam_hash->alg_type)) {
180062306a36Sopenharmony_ci		ctx->dir = DMA_TO_DEVICE;
180162306a36Sopenharmony_ci		ctx->key_dir = DMA_NONE;
180262306a36Sopenharmony_ci		ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
180362306a36Sopenharmony_ci		ctx->ctx_len = 32;
180462306a36Sopenharmony_ci	} else {
180562306a36Sopenharmony_ci		if (priv->era >= 6) {
180662306a36Sopenharmony_ci			ctx->dir = DMA_BIDIRECTIONAL;
180762306a36Sopenharmony_ci			ctx->key_dir = alg->setkey ? DMA_TO_DEVICE : DMA_NONE;
180862306a36Sopenharmony_ci		} else {
180962306a36Sopenharmony_ci			ctx->dir = DMA_TO_DEVICE;
181062306a36Sopenharmony_ci			ctx->key_dir = DMA_NONE;
181162306a36Sopenharmony_ci		}
181262306a36Sopenharmony_ci		ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
181362306a36Sopenharmony_ci		ctx->ctx_len = runninglen[(ctx->adata.algtype &
181462306a36Sopenharmony_ci					   OP_ALG_ALGSEL_SUBMASK) >>
181562306a36Sopenharmony_ci					  OP_ALG_ALGSEL_SHIFT];
181662306a36Sopenharmony_ci	}
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	if (ctx->key_dir != DMA_NONE) {
181962306a36Sopenharmony_ci		ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key,
182062306a36Sopenharmony_ci							  ARRAY_SIZE(ctx->key),
182162306a36Sopenharmony_ci							  ctx->key_dir,
182262306a36Sopenharmony_ci							  DMA_ATTR_SKIP_CPU_SYNC);
182362306a36Sopenharmony_ci		if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) {
182462306a36Sopenharmony_ci			dev_err(ctx->jrdev, "unable to map key\n");
182562306a36Sopenharmony_ci			caam_jr_free(ctx->jrdev);
182662306a36Sopenharmony_ci			return -ENOMEM;
182762306a36Sopenharmony_ci		}
182862306a36Sopenharmony_ci	}
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update,
183162306a36Sopenharmony_ci					offsetof(struct caam_hash_ctx, key) -
183262306a36Sopenharmony_ci					sh_desc_update_offset,
183362306a36Sopenharmony_ci					ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
183462306a36Sopenharmony_ci	if (dma_mapping_error(ctx->jrdev, dma_addr)) {
183562306a36Sopenharmony_ci		dev_err(ctx->jrdev, "unable to map shared descriptors\n");
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci		if (ctx->key_dir != DMA_NONE)
183862306a36Sopenharmony_ci			dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
183962306a36Sopenharmony_ci					       ARRAY_SIZE(ctx->key),
184062306a36Sopenharmony_ci					       ctx->key_dir,
184162306a36Sopenharmony_ci					       DMA_ATTR_SKIP_CPU_SYNC);
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci		caam_jr_free(ctx->jrdev);
184462306a36Sopenharmony_ci		return -ENOMEM;
184562306a36Sopenharmony_ci	}
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci	ctx->sh_desc_update_dma = dma_addr;
184862306a36Sopenharmony_ci	ctx->sh_desc_update_first_dma = dma_addr +
184962306a36Sopenharmony_ci					offsetof(struct caam_hash_ctx,
185062306a36Sopenharmony_ci						 sh_desc_update_first) -
185162306a36Sopenharmony_ci					sh_desc_update_offset;
185262306a36Sopenharmony_ci	ctx->sh_desc_fin_dma = dma_addr + offsetof(struct caam_hash_ctx,
185362306a36Sopenharmony_ci						   sh_desc_fin) -
185462306a36Sopenharmony_ci					sh_desc_update_offset;
185562306a36Sopenharmony_ci	ctx->sh_desc_digest_dma = dma_addr + offsetof(struct caam_hash_ctx,
185662306a36Sopenharmony_ci						      sh_desc_digest) -
185762306a36Sopenharmony_ci					sh_desc_update_offset;
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	crypto_ahash_set_reqsize_dma(ahash, sizeof(struct caam_hash_state));
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_ci	/*
186262306a36Sopenharmony_ci	 * For keyed hash algorithms shared descriptors
186362306a36Sopenharmony_ci	 * will be created later in setkey() callback
186462306a36Sopenharmony_ci	 */
186562306a36Sopenharmony_ci	return alg->setkey ? 0 : ahash_set_sh_desc(ahash);
186662306a36Sopenharmony_ci}
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_cistatic void caam_hash_cra_exit(struct crypto_tfm *tfm)
186962306a36Sopenharmony_ci{
187062306a36Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm);
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci	dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma,
187362306a36Sopenharmony_ci			       offsetof(struct caam_hash_ctx, key) -
187462306a36Sopenharmony_ci			       offsetof(struct caam_hash_ctx, sh_desc_update),
187562306a36Sopenharmony_ci			       ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
187662306a36Sopenharmony_ci	if (ctx->key_dir != DMA_NONE)
187762306a36Sopenharmony_ci		dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
187862306a36Sopenharmony_ci				       ARRAY_SIZE(ctx->key), ctx->key_dir,
187962306a36Sopenharmony_ci				       DMA_ATTR_SKIP_CPU_SYNC);
188062306a36Sopenharmony_ci	caam_jr_free(ctx->jrdev);
188162306a36Sopenharmony_ci}
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_civoid caam_algapi_hash_exit(void)
188462306a36Sopenharmony_ci{
188562306a36Sopenharmony_ci	struct caam_hash_alg *t_alg, *n;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	if (!hash_list.next)
188862306a36Sopenharmony_ci		return;
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
189162306a36Sopenharmony_ci		crypto_engine_unregister_ahash(&t_alg->ahash_alg);
189262306a36Sopenharmony_ci		list_del(&t_alg->entry);
189362306a36Sopenharmony_ci		kfree(t_alg);
189462306a36Sopenharmony_ci	}
189562306a36Sopenharmony_ci}
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_cistatic struct caam_hash_alg *
189862306a36Sopenharmony_cicaam_hash_alloc(struct caam_hash_template *template,
189962306a36Sopenharmony_ci		bool keyed)
190062306a36Sopenharmony_ci{
190162306a36Sopenharmony_ci	struct caam_hash_alg *t_alg;
190262306a36Sopenharmony_ci	struct ahash_alg *halg;
190362306a36Sopenharmony_ci	struct crypto_alg *alg;
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
190662306a36Sopenharmony_ci	if (!t_alg)
190762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	t_alg->ahash_alg.base = template->template_ahash;
191062306a36Sopenharmony_ci	halg = &t_alg->ahash_alg.base;
191162306a36Sopenharmony_ci	alg = &halg->halg.base;
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	if (keyed) {
191462306a36Sopenharmony_ci		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
191562306a36Sopenharmony_ci			 template->hmac_name);
191662306a36Sopenharmony_ci		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
191762306a36Sopenharmony_ci			 template->hmac_driver_name);
191862306a36Sopenharmony_ci	} else {
191962306a36Sopenharmony_ci		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
192062306a36Sopenharmony_ci			 template->name);
192162306a36Sopenharmony_ci		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
192262306a36Sopenharmony_ci			 template->driver_name);
192362306a36Sopenharmony_ci		halg->setkey = NULL;
192462306a36Sopenharmony_ci	}
192562306a36Sopenharmony_ci	alg->cra_module = THIS_MODULE;
192662306a36Sopenharmony_ci	alg->cra_init = caam_hash_cra_init;
192762306a36Sopenharmony_ci	alg->cra_exit = caam_hash_cra_exit;
192862306a36Sopenharmony_ci	alg->cra_ctxsize = sizeof(struct caam_hash_ctx) + crypto_dma_padding();
192962306a36Sopenharmony_ci	alg->cra_priority = CAAM_CRA_PRIORITY;
193062306a36Sopenharmony_ci	alg->cra_blocksize = template->blocksize;
193162306a36Sopenharmony_ci	alg->cra_alignmask = 0;
193262306a36Sopenharmony_ci	alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	t_alg->alg_type = template->alg_type;
193562306a36Sopenharmony_ci	t_alg->ahash_alg.op.do_one_request = ahash_do_one_req;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	return t_alg;
193862306a36Sopenharmony_ci}
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ciint caam_algapi_hash_init(struct device *ctrldev)
194162306a36Sopenharmony_ci{
194262306a36Sopenharmony_ci	int i = 0, err = 0;
194362306a36Sopenharmony_ci	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
194462306a36Sopenharmony_ci	unsigned int md_limit = SHA512_DIGEST_SIZE;
194562306a36Sopenharmony_ci	u32 md_inst, md_vid;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	/*
194862306a36Sopenharmony_ci	 * Register crypto algorithms the device supports.  First, identify
194962306a36Sopenharmony_ci	 * presence and attributes of MD block.
195062306a36Sopenharmony_ci	 */
195162306a36Sopenharmony_ci	if (priv->era < 10) {
195262306a36Sopenharmony_ci		struct caam_perfmon __iomem *perfmon = &priv->jr[0]->perfmon;
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci		md_vid = (rd_reg32(&perfmon->cha_id_ls) &
195562306a36Sopenharmony_ci			  CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
195662306a36Sopenharmony_ci		md_inst = (rd_reg32(&perfmon->cha_num_ls) &
195762306a36Sopenharmony_ci			   CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
195862306a36Sopenharmony_ci	} else {
195962306a36Sopenharmony_ci		u32 mdha = rd_reg32(&priv->jr[0]->vreg.mdha);
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci		md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT;
196262306a36Sopenharmony_ci		md_inst = mdha & CHA_VER_NUM_MASK;
196362306a36Sopenharmony_ci	}
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	/*
196662306a36Sopenharmony_ci	 * Skip registration of any hashing algorithms if MD block
196762306a36Sopenharmony_ci	 * is not present.
196862306a36Sopenharmony_ci	 */
196962306a36Sopenharmony_ci	if (!md_inst)
197062306a36Sopenharmony_ci		return 0;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	/* Limit digest size based on LP256 */
197362306a36Sopenharmony_ci	if (md_vid == CHA_VER_VID_MD_LP256)
197462306a36Sopenharmony_ci		md_limit = SHA256_DIGEST_SIZE;
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	INIT_LIST_HEAD(&hash_list);
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci	/* register crypto algorithms the device supports */
197962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
198062306a36Sopenharmony_ci		struct caam_hash_alg *t_alg;
198162306a36Sopenharmony_ci		struct caam_hash_template *alg = driver_hash + i;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci		/* If MD size is not supported by device, skip registration */
198462306a36Sopenharmony_ci		if (is_mdha(alg->alg_type) &&
198562306a36Sopenharmony_ci		    alg->template_ahash.halg.digestsize > md_limit)
198662306a36Sopenharmony_ci			continue;
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci		/* register hmac version */
198962306a36Sopenharmony_ci		t_alg = caam_hash_alloc(alg, true);
199062306a36Sopenharmony_ci		if (IS_ERR(t_alg)) {
199162306a36Sopenharmony_ci			err = PTR_ERR(t_alg);
199262306a36Sopenharmony_ci			pr_warn("%s alg allocation failed\n",
199362306a36Sopenharmony_ci				alg->hmac_driver_name);
199462306a36Sopenharmony_ci			continue;
199562306a36Sopenharmony_ci		}
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci		err = crypto_engine_register_ahash(&t_alg->ahash_alg);
199862306a36Sopenharmony_ci		if (err) {
199962306a36Sopenharmony_ci			pr_warn("%s alg registration failed: %d\n",
200062306a36Sopenharmony_ci				t_alg->ahash_alg.base.halg.base.cra_driver_name,
200162306a36Sopenharmony_ci				err);
200262306a36Sopenharmony_ci			kfree(t_alg);
200362306a36Sopenharmony_ci		} else
200462306a36Sopenharmony_ci			list_add_tail(&t_alg->entry, &hash_list);
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci		if ((alg->alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES)
200762306a36Sopenharmony_ci			continue;
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci		/* register unkeyed version */
201062306a36Sopenharmony_ci		t_alg = caam_hash_alloc(alg, false);
201162306a36Sopenharmony_ci		if (IS_ERR(t_alg)) {
201262306a36Sopenharmony_ci			err = PTR_ERR(t_alg);
201362306a36Sopenharmony_ci			pr_warn("%s alg allocation failed\n", alg->driver_name);
201462306a36Sopenharmony_ci			continue;
201562306a36Sopenharmony_ci		}
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci		err = crypto_engine_register_ahash(&t_alg->ahash_alg);
201862306a36Sopenharmony_ci		if (err) {
201962306a36Sopenharmony_ci			pr_warn("%s alg registration failed: %d\n",
202062306a36Sopenharmony_ci				t_alg->ahash_alg.base.halg.base.cra_driver_name,
202162306a36Sopenharmony_ci				err);
202262306a36Sopenharmony_ci			kfree(t_alg);
202362306a36Sopenharmony_ci		} else
202462306a36Sopenharmony_ci			list_add_tail(&t_alg->entry, &hash_list);
202562306a36Sopenharmony_ci	}
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	return err;
202862306a36Sopenharmony_ci}
2029