18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * caam - Freescale FSL CAAM support for ahash functions of crypto API
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2011 Freescale Semiconductor, Inc.
68c2ecf20Sopenharmony_ci * Copyright 2018-2019 NXP
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Based on caamalg.c crypto API driver.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * relationship of digest job descriptor or first job descriptor after init to
118c2ecf20Sopenharmony_ci * shared descriptors:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * ---------------                     ---------------
148c2ecf20Sopenharmony_ci * | JobDesc #1  |-------------------->|  ShareDesc  |
158c2ecf20Sopenharmony_ci * | *(packet 1) |                     |  (hashKey)  |
168c2ecf20Sopenharmony_ci * ---------------                     | (operation) |
178c2ecf20Sopenharmony_ci *                                     ---------------
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * relationship of subsequent job descriptors to shared descriptors:
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * ---------------                     ---------------
228c2ecf20Sopenharmony_ci * | JobDesc #2  |-------------------->|  ShareDesc  |
238c2ecf20Sopenharmony_ci * | *(packet 2) |      |------------->|  (hashKey)  |
248c2ecf20Sopenharmony_ci * ---------------      |    |-------->| (operation) |
258c2ecf20Sopenharmony_ci *       .              |    |         | (load ctx2) |
268c2ecf20Sopenharmony_ci *       .              |    |         ---------------
278c2ecf20Sopenharmony_ci * ---------------      |    |
288c2ecf20Sopenharmony_ci * | JobDesc #3  |------|    |
298c2ecf20Sopenharmony_ci * | *(packet 3) |           |
308c2ecf20Sopenharmony_ci * ---------------           |
318c2ecf20Sopenharmony_ci *       .                   |
328c2ecf20Sopenharmony_ci *       .                   |
338c2ecf20Sopenharmony_ci * ---------------           |
348c2ecf20Sopenharmony_ci * | JobDesc #4  |------------
358c2ecf20Sopenharmony_ci * | *(packet 4) |
368c2ecf20Sopenharmony_ci * ---------------
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * The SharedDesc never changes for a connection unless rekeyed, but
398c2ecf20Sopenharmony_ci * each packet will likely be in a different place. So all we need
408c2ecf20Sopenharmony_ci * to know to process the packet is where the input is, where the
418c2ecf20Sopenharmony_ci * output goes, and what context we want to process with. Context is
428c2ecf20Sopenharmony_ci * in the SharedDesc, packet references in the JobDesc.
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci * So, a job desc looks like:
458c2ecf20Sopenharmony_ci *
468c2ecf20Sopenharmony_ci * ---------------------
478c2ecf20Sopenharmony_ci * | Header            |
488c2ecf20Sopenharmony_ci * | ShareDesc Pointer |
498c2ecf20Sopenharmony_ci * | SEQ_OUT_PTR       |
508c2ecf20Sopenharmony_ci * | (output buffer)   |
518c2ecf20Sopenharmony_ci * | (output length)   |
528c2ecf20Sopenharmony_ci * | SEQ_IN_PTR        |
538c2ecf20Sopenharmony_ci * | (input buffer)    |
548c2ecf20Sopenharmony_ci * | (input length)    |
558c2ecf20Sopenharmony_ci * ---------------------
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#include "compat.h"
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#include "regs.h"
618c2ecf20Sopenharmony_ci#include "intern.h"
628c2ecf20Sopenharmony_ci#include "desc_constr.h"
638c2ecf20Sopenharmony_ci#include "jr.h"
648c2ecf20Sopenharmony_ci#include "error.h"
658c2ecf20Sopenharmony_ci#include "sg_sw_sec4.h"
668c2ecf20Sopenharmony_ci#include "key_gen.h"
678c2ecf20Sopenharmony_ci#include "caamhash_desc.h"
688c2ecf20Sopenharmony_ci#include <crypto/engine.h>
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define CAAM_CRA_PRIORITY		3000
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/* max hash key is max split key size */
738c2ecf20Sopenharmony_ci#define CAAM_MAX_HASH_KEY_SIZE		(SHA512_DIGEST_SIZE * 2)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define CAAM_MAX_HASH_BLOCK_SIZE	SHA512_BLOCK_SIZE
768c2ecf20Sopenharmony_ci#define CAAM_MAX_HASH_DIGEST_SIZE	SHA512_DIGEST_SIZE
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#define DESC_HASH_MAX_USED_BYTES	(DESC_AHASH_FINAL_LEN + \
798c2ecf20Sopenharmony_ci					 CAAM_MAX_HASH_KEY_SIZE)
808c2ecf20Sopenharmony_ci#define DESC_HASH_MAX_USED_LEN		(DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ)
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/* caam context sizes for hashes: running digest + 8 */
838c2ecf20Sopenharmony_ci#define HASH_MSG_LEN			8
848c2ecf20Sopenharmony_ci#define MAX_CTX_LEN			(HASH_MSG_LEN + SHA512_DIGEST_SIZE)
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic struct list_head hash_list;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* ahash per-session context */
898c2ecf20Sopenharmony_cistruct caam_hash_ctx {
908c2ecf20Sopenharmony_ci	struct crypto_engine_ctx enginectx;
918c2ecf20Sopenharmony_ci	u32 sh_desc_update[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
928c2ecf20Sopenharmony_ci	u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
938c2ecf20Sopenharmony_ci	u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
948c2ecf20Sopenharmony_ci	u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
958c2ecf20Sopenharmony_ci	u8 key[CAAM_MAX_HASH_KEY_SIZE] ____cacheline_aligned;
968c2ecf20Sopenharmony_ci	dma_addr_t sh_desc_update_dma ____cacheline_aligned;
978c2ecf20Sopenharmony_ci	dma_addr_t sh_desc_update_first_dma;
988c2ecf20Sopenharmony_ci	dma_addr_t sh_desc_fin_dma;
998c2ecf20Sopenharmony_ci	dma_addr_t sh_desc_digest_dma;
1008c2ecf20Sopenharmony_ci	enum dma_data_direction dir;
1018c2ecf20Sopenharmony_ci	enum dma_data_direction key_dir;
1028c2ecf20Sopenharmony_ci	struct device *jrdev;
1038c2ecf20Sopenharmony_ci	int ctx_len;
1048c2ecf20Sopenharmony_ci	struct alginfo adata;
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/* ahash state */
1088c2ecf20Sopenharmony_cistruct caam_hash_state {
1098c2ecf20Sopenharmony_ci	dma_addr_t buf_dma;
1108c2ecf20Sopenharmony_ci	dma_addr_t ctx_dma;
1118c2ecf20Sopenharmony_ci	int ctx_dma_len;
1128c2ecf20Sopenharmony_ci	u8 buf[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
1138c2ecf20Sopenharmony_ci	int buflen;
1148c2ecf20Sopenharmony_ci	int next_buflen;
1158c2ecf20Sopenharmony_ci	u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned;
1168c2ecf20Sopenharmony_ci	int (*update)(struct ahash_request *req) ____cacheline_aligned;
1178c2ecf20Sopenharmony_ci	int (*final)(struct ahash_request *req);
1188c2ecf20Sopenharmony_ci	int (*finup)(struct ahash_request *req);
1198c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
1208c2ecf20Sopenharmony_ci	void (*ahash_op_done)(struct device *jrdev, u32 *desc, u32 err,
1218c2ecf20Sopenharmony_ci			      void *context);
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistruct caam_export_state {
1258c2ecf20Sopenharmony_ci	u8 buf[CAAM_MAX_HASH_BLOCK_SIZE];
1268c2ecf20Sopenharmony_ci	u8 caam_ctx[MAX_CTX_LEN];
1278c2ecf20Sopenharmony_ci	int buflen;
1288c2ecf20Sopenharmony_ci	int (*update)(struct ahash_request *req);
1298c2ecf20Sopenharmony_ci	int (*final)(struct ahash_request *req);
1308c2ecf20Sopenharmony_ci	int (*finup)(struct ahash_request *req);
1318c2ecf20Sopenharmony_ci};
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic inline bool is_cmac_aes(u32 algtype)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) ==
1368c2ecf20Sopenharmony_ci	       (OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci/* Common job descriptor seq in/out ptr routines */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
1418c2ecf20Sopenharmony_cistatic inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
1428c2ecf20Sopenharmony_ci				      struct caam_hash_state *state,
1438c2ecf20Sopenharmony_ci				      int ctx_len)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	state->ctx_dma_len = ctx_len;
1468c2ecf20Sopenharmony_ci	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
1478c2ecf20Sopenharmony_ci					ctx_len, DMA_FROM_DEVICE);
1488c2ecf20Sopenharmony_ci	if (dma_mapping_error(jrdev, state->ctx_dma)) {
1498c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to map ctx\n");
1508c2ecf20Sopenharmony_ci		state->ctx_dma = 0;
1518c2ecf20Sopenharmony_ci		return -ENOMEM;
1528c2ecf20Sopenharmony_ci	}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	return 0;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/* Map current buffer in state (if length > 0) and put it in link table */
1608c2ecf20Sopenharmony_cistatic inline int buf_map_to_sec4_sg(struct device *jrdev,
1618c2ecf20Sopenharmony_ci				     struct sec4_sg_entry *sec4_sg,
1628c2ecf20Sopenharmony_ci				     struct caam_hash_state *state)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	int buflen = state->buflen;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	if (!buflen)
1678c2ecf20Sopenharmony_ci		return 0;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	state->buf_dma = dma_map_single(jrdev, state->buf, buflen,
1708c2ecf20Sopenharmony_ci					DMA_TO_DEVICE);
1718c2ecf20Sopenharmony_ci	if (dma_mapping_error(jrdev, state->buf_dma)) {
1728c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to map buf\n");
1738c2ecf20Sopenharmony_ci		state->buf_dma = 0;
1748c2ecf20Sopenharmony_ci		return -ENOMEM;
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	dma_to_sec4_sg_one(sec4_sg, state->buf_dma, buflen, 0);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	return 0;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/* Map state->caam_ctx, and add it to link table */
1838c2ecf20Sopenharmony_cistatic inline int ctx_map_to_sec4_sg(struct device *jrdev,
1848c2ecf20Sopenharmony_ci				     struct caam_hash_state *state, int ctx_len,
1858c2ecf20Sopenharmony_ci				     struct sec4_sg_entry *sec4_sg, u32 flag)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	state->ctx_dma_len = ctx_len;
1888c2ecf20Sopenharmony_ci	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
1898c2ecf20Sopenharmony_ci	if (dma_mapping_error(jrdev, state->ctx_dma)) {
1908c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to map ctx\n");
1918c2ecf20Sopenharmony_ci		state->ctx_dma = 0;
1928c2ecf20Sopenharmony_ci		return -ENOMEM;
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	return 0;
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic int ahash_set_sh_desc(struct crypto_ahash *ahash)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
2038c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
2048c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
2058c2ecf20Sopenharmony_ci	struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent);
2068c2ecf20Sopenharmony_ci	u32 *desc;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	ctx->adata.key_virt = ctx->key;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/* ahash_update shared descriptor */
2118c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_update;
2128c2ecf20Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len,
2138c2ecf20Sopenharmony_ci			  ctx->ctx_len, true, ctrlpriv->era);
2148c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
2158c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	print_hex_dump_debug("ahash update shdesc@"__stringify(__LINE__)": ",
2188c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
2198c2ecf20Sopenharmony_ci			     1);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	/* ahash_update_first shared descriptor */
2228c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_update_first;
2238c2ecf20Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
2248c2ecf20Sopenharmony_ci			  ctx->ctx_len, false, ctrlpriv->era);
2258c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
2268c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2278c2ecf20Sopenharmony_ci	print_hex_dump_debug("ahash update first shdesc@"__stringify(__LINE__)
2288c2ecf20Sopenharmony_ci			     ": ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
2298c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* ahash_final shared descriptor */
2328c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_fin;
2338c2ecf20Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize,
2348c2ecf20Sopenharmony_ci			  ctx->ctx_len, true, ctrlpriv->era);
2358c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
2368c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	print_hex_dump_debug("ahash final shdesc@"__stringify(__LINE__)": ",
2398c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
2408c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* ahash_digest shared descriptor */
2438c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_digest;
2448c2ecf20Sopenharmony_ci	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize,
2458c2ecf20Sopenharmony_ci			  ctx->ctx_len, false, ctrlpriv->era);
2468c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
2478c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	print_hex_dump_debug("ahash digest shdesc@"__stringify(__LINE__)": ",
2508c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
2518c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	return 0;
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic int axcbc_set_sh_desc(struct crypto_ahash *ahash)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
2598c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
2608c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
2618c2ecf20Sopenharmony_ci	u32 *desc;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	/* shared descriptor for ahash_update */
2648c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_update;
2658c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
2668c2ecf20Sopenharmony_ci			    ctx->ctx_len, ctx->ctx_len);
2678c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
2688c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2698c2ecf20Sopenharmony_ci	print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ",
2708c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
2718c2ecf20Sopenharmony_ci			     1);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	/* shared descriptor for ahash_{final,finup} */
2748c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_fin;
2758c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
2768c2ecf20Sopenharmony_ci			    digestsize, ctx->ctx_len);
2778c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
2788c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2798c2ecf20Sopenharmony_ci	print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ",
2808c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
2818c2ecf20Sopenharmony_ci			     1);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	/* key is immediate data for INIT and INITFINAL states */
2848c2ecf20Sopenharmony_ci	ctx->adata.key_virt = ctx->key;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	/* shared descriptor for first invocation of ahash_update */
2878c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_update_first;
2888c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
2898c2ecf20Sopenharmony_ci			    ctx->ctx_len);
2908c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
2918c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
2928c2ecf20Sopenharmony_ci	print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__)
2938c2ecf20Sopenharmony_ci			     " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
2948c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/* shared descriptor for ahash_digest */
2978c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_digest;
2988c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
2998c2ecf20Sopenharmony_ci			    digestsize, ctx->ctx_len);
3008c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
3018c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
3028c2ecf20Sopenharmony_ci	print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ",
3038c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
3048c2ecf20Sopenharmony_ci			     1);
3058c2ecf20Sopenharmony_ci	return 0;
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic int acmac_set_sh_desc(struct crypto_ahash *ahash)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
3118c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
3128c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
3138c2ecf20Sopenharmony_ci	u32 *desc;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	/* shared descriptor for ahash_update */
3168c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_update;
3178c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
3188c2ecf20Sopenharmony_ci			    ctx->ctx_len, ctx->ctx_len);
3198c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
3208c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
3218c2ecf20Sopenharmony_ci	print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ",
3228c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
3238c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/* shared descriptor for ahash_{final,finup} */
3268c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_fin;
3278c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
3288c2ecf20Sopenharmony_ci			    digestsize, ctx->ctx_len);
3298c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
3308c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
3318c2ecf20Sopenharmony_ci	print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ",
3328c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
3338c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	/* shared descriptor for first invocation of ahash_update */
3368c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_update_first;
3378c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
3388c2ecf20Sopenharmony_ci			    ctx->ctx_len);
3398c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
3408c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
3418c2ecf20Sopenharmony_ci	print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__)
3428c2ecf20Sopenharmony_ci			     " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
3438c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	/* shared descriptor for ahash_digest */
3468c2ecf20Sopenharmony_ci	desc = ctx->sh_desc_digest;
3478c2ecf20Sopenharmony_ci	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
3488c2ecf20Sopenharmony_ci			    digestsize, ctx->ctx_len);
3498c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
3508c2ecf20Sopenharmony_ci				   desc_bytes(desc), ctx->dir);
3518c2ecf20Sopenharmony_ci	print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ",
3528c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
3538c2ecf20Sopenharmony_ci			     desc_bytes(desc), 1);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	return 0;
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci/* Digest hash size if it is too large */
3598c2ecf20Sopenharmony_cistatic int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key,
3608c2ecf20Sopenharmony_ci			   u32 digestsize)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
3638c2ecf20Sopenharmony_ci	u32 *desc;
3648c2ecf20Sopenharmony_ci	struct split_key_result result;
3658c2ecf20Sopenharmony_ci	dma_addr_t key_dma;
3668c2ecf20Sopenharmony_ci	int ret;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
3698c2ecf20Sopenharmony_ci	if (!desc) {
3708c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to allocate key input memory\n");
3718c2ecf20Sopenharmony_ci		return -ENOMEM;
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	init_job_desc(desc, 0);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	key_dma = dma_map_single(jrdev, key, *keylen, DMA_BIDIRECTIONAL);
3778c2ecf20Sopenharmony_ci	if (dma_mapping_error(jrdev, key_dma)) {
3788c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to map key memory\n");
3798c2ecf20Sopenharmony_ci		kfree(desc);
3808c2ecf20Sopenharmony_ci		return -ENOMEM;
3818c2ecf20Sopenharmony_ci	}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	/* Job descriptor to perform unkeyed hash on key_in */
3848c2ecf20Sopenharmony_ci	append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT |
3858c2ecf20Sopenharmony_ci			 OP_ALG_AS_INITFINAL);
3868c2ecf20Sopenharmony_ci	append_seq_in_ptr(desc, key_dma, *keylen, 0);
3878c2ecf20Sopenharmony_ci	append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
3888c2ecf20Sopenharmony_ci			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
3898c2ecf20Sopenharmony_ci	append_seq_out_ptr(desc, key_dma, digestsize, 0);
3908c2ecf20Sopenharmony_ci	append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
3918c2ecf20Sopenharmony_ci			 LDST_SRCDST_BYTE_CONTEXT);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	print_hex_dump_debug("key_in@"__stringify(__LINE__)": ",
3948c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
3958c2ecf20Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
3968c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
3978c2ecf20Sopenharmony_ci			     1);
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	result.err = 0;
4008c2ecf20Sopenharmony_ci	init_completion(&result.completion);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
4038c2ecf20Sopenharmony_ci	if (ret == -EINPROGRESS) {
4048c2ecf20Sopenharmony_ci		/* in progress */
4058c2ecf20Sopenharmony_ci		wait_for_completion(&result.completion);
4068c2ecf20Sopenharmony_ci		ret = result.err;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci		print_hex_dump_debug("digested key@"__stringify(__LINE__)": ",
4098c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, key,
4108c2ecf20Sopenharmony_ci				     digestsize, 1);
4118c2ecf20Sopenharmony_ci	}
4128c2ecf20Sopenharmony_ci	dma_unmap_single(jrdev, key_dma, *keylen, DMA_BIDIRECTIONAL);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	*keylen = digestsize;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	kfree(desc);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	return ret;
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *ahash,
4228c2ecf20Sopenharmony_ci			const u8 *key, unsigned int keylen)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
4258c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
4268c2ecf20Sopenharmony_ci	int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
4278c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
4288c2ecf20Sopenharmony_ci	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent);
4298c2ecf20Sopenharmony_ci	int ret;
4308c2ecf20Sopenharmony_ci	u8 *hashed_key = NULL;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	dev_dbg(jrdev, "keylen %d\n", keylen);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	if (keylen > blocksize) {
4358c2ecf20Sopenharmony_ci		hashed_key = kmemdup(key, keylen, GFP_KERNEL | GFP_DMA);
4368c2ecf20Sopenharmony_ci		if (!hashed_key)
4378c2ecf20Sopenharmony_ci			return -ENOMEM;
4388c2ecf20Sopenharmony_ci		ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
4398c2ecf20Sopenharmony_ci		if (ret)
4408c2ecf20Sopenharmony_ci			goto bad_free_key;
4418c2ecf20Sopenharmony_ci		key = hashed_key;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/*
4458c2ecf20Sopenharmony_ci	 * If DKP is supported, use it in the shared descriptor to generate
4468c2ecf20Sopenharmony_ci	 * the split key.
4478c2ecf20Sopenharmony_ci	 */
4488c2ecf20Sopenharmony_ci	if (ctrlpriv->era >= 6) {
4498c2ecf20Sopenharmony_ci		ctx->adata.key_inline = true;
4508c2ecf20Sopenharmony_ci		ctx->adata.keylen = keylen;
4518c2ecf20Sopenharmony_ci		ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype &
4528c2ecf20Sopenharmony_ci						      OP_ALG_ALGSEL_MASK);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci		if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE)
4558c2ecf20Sopenharmony_ci			goto bad_free_key;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		memcpy(ctx->key, key, keylen);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		/*
4608c2ecf20Sopenharmony_ci		 * In case |user key| > |derived key|, using DKP<imm,imm>
4618c2ecf20Sopenharmony_ci		 * would result in invalid opcodes (last bytes of user key) in
4628c2ecf20Sopenharmony_ci		 * the resulting descriptor. Use DKP<ptr,imm> instead => both
4638c2ecf20Sopenharmony_ci		 * virtual and dma key addresses are needed.
4648c2ecf20Sopenharmony_ci		 */
4658c2ecf20Sopenharmony_ci		if (keylen > ctx->adata.keylen_pad)
4668c2ecf20Sopenharmony_ci			dma_sync_single_for_device(ctx->jrdev,
4678c2ecf20Sopenharmony_ci						   ctx->adata.key_dma,
4688c2ecf20Sopenharmony_ci						   ctx->adata.keylen_pad,
4698c2ecf20Sopenharmony_ci						   DMA_TO_DEVICE);
4708c2ecf20Sopenharmony_ci	} else {
4718c2ecf20Sopenharmony_ci		ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key,
4728c2ecf20Sopenharmony_ci				    keylen, CAAM_MAX_HASH_KEY_SIZE);
4738c2ecf20Sopenharmony_ci		if (ret)
4748c2ecf20Sopenharmony_ci			goto bad_free_key;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	kfree(hashed_key);
4788c2ecf20Sopenharmony_ci	return ahash_set_sh_desc(ahash);
4798c2ecf20Sopenharmony_ci bad_free_key:
4808c2ecf20Sopenharmony_ci	kfree(hashed_key);
4818c2ecf20Sopenharmony_ci	return -EINVAL;
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key,
4858c2ecf20Sopenharmony_ci			unsigned int keylen)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
4888c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	if (keylen != AES_KEYSIZE_128)
4918c2ecf20Sopenharmony_ci		return -EINVAL;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	memcpy(ctx->key, key, keylen);
4948c2ecf20Sopenharmony_ci	dma_sync_single_for_device(jrdev, ctx->adata.key_dma, keylen,
4958c2ecf20Sopenharmony_ci				   DMA_TO_DEVICE);
4968c2ecf20Sopenharmony_ci	ctx->adata.keylen = keylen;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ",
4998c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1);
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	return axcbc_set_sh_desc(ahash);
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_cistatic int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
5058c2ecf20Sopenharmony_ci			unsigned int keylen)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
5088c2ecf20Sopenharmony_ci	int err;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	err = aes_check_keylen(keylen);
5118c2ecf20Sopenharmony_ci	if (err)
5128c2ecf20Sopenharmony_ci		return err;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	/* key is immediate data for all cmac shared descriptors */
5158c2ecf20Sopenharmony_ci	ctx->adata.key_virt = key;
5168c2ecf20Sopenharmony_ci	ctx->adata.keylen = keylen;
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ",
5198c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	return acmac_set_sh_desc(ahash);
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci/*
5258c2ecf20Sopenharmony_ci * ahash_edesc - s/w-extended ahash descriptor
5268c2ecf20Sopenharmony_ci * @sec4_sg_dma: physical mapped address of h/w link table
5278c2ecf20Sopenharmony_ci * @src_nents: number of segments in input scatterlist
5288c2ecf20Sopenharmony_ci * @sec4_sg_bytes: length of dma mapped sec4_sg space
5298c2ecf20Sopenharmony_ci * @bklog: stored to determine if the request needs backlog
5308c2ecf20Sopenharmony_ci * @hw_desc: the h/w job descriptor followed by any referenced link tables
5318c2ecf20Sopenharmony_ci * @sec4_sg: h/w link table
5328c2ecf20Sopenharmony_ci */
5338c2ecf20Sopenharmony_cistruct ahash_edesc {
5348c2ecf20Sopenharmony_ci	dma_addr_t sec4_sg_dma;
5358c2ecf20Sopenharmony_ci	int src_nents;
5368c2ecf20Sopenharmony_ci	int sec4_sg_bytes;
5378c2ecf20Sopenharmony_ci	bool bklog;
5388c2ecf20Sopenharmony_ci	u32 hw_desc[DESC_JOB_IO_LEN_MAX / sizeof(u32)] ____cacheline_aligned;
5398c2ecf20Sopenharmony_ci	struct sec4_sg_entry sec4_sg[];
5408c2ecf20Sopenharmony_ci};
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic inline void ahash_unmap(struct device *dev,
5438c2ecf20Sopenharmony_ci			struct ahash_edesc *edesc,
5448c2ecf20Sopenharmony_ci			struct ahash_request *req, int dst_len)
5458c2ecf20Sopenharmony_ci{
5468c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (edesc->src_nents)
5498c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	if (edesc->sec4_sg_bytes)
5528c2ecf20Sopenharmony_ci		dma_unmap_single(dev, edesc->sec4_sg_dma,
5538c2ecf20Sopenharmony_ci				 edesc->sec4_sg_bytes, DMA_TO_DEVICE);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	if (state->buf_dma) {
5568c2ecf20Sopenharmony_ci		dma_unmap_single(dev, state->buf_dma, state->buflen,
5578c2ecf20Sopenharmony_ci				 DMA_TO_DEVICE);
5588c2ecf20Sopenharmony_ci		state->buf_dma = 0;
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_cistatic inline void ahash_unmap_ctx(struct device *dev,
5638c2ecf20Sopenharmony_ci			struct ahash_edesc *edesc,
5648c2ecf20Sopenharmony_ci			struct ahash_request *req, int dst_len, u32 flag)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	if (state->ctx_dma) {
5698c2ecf20Sopenharmony_ci		dma_unmap_single(dev, state->ctx_dma, state->ctx_dma_len, flag);
5708c2ecf20Sopenharmony_ci		state->ctx_dma = 0;
5718c2ecf20Sopenharmony_ci	}
5728c2ecf20Sopenharmony_ci	ahash_unmap(dev, edesc, req, dst_len);
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_cistatic inline void ahash_done_cpy(struct device *jrdev, u32 *desc, u32 err,
5768c2ecf20Sopenharmony_ci				  void *context, enum dma_data_direction dir)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	struct ahash_request *req = context;
5798c2ecf20Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
5808c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
5818c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
5828c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
5838c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
5848c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
5858c2ecf20Sopenharmony_ci	int ecode = 0;
5868c2ecf20Sopenharmony_ci	bool has_bklog;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	edesc = state->edesc;
5918c2ecf20Sopenharmony_ci	has_bklog = edesc->bklog;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	if (err)
5948c2ecf20Sopenharmony_ci		ecode = caam_jr_strstatus(jrdev, err);
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, digestsize, dir);
5978c2ecf20Sopenharmony_ci	memcpy(req->result, state->caam_ctx, digestsize);
5988c2ecf20Sopenharmony_ci	kfree(edesc);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
6018c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
6028c2ecf20Sopenharmony_ci			     ctx->ctx_len, 1);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	/*
6058c2ecf20Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
6068c2ecf20Sopenharmony_ci	 * by CAAM, not crypto engine.
6078c2ecf20Sopenharmony_ci	 */
6088c2ecf20Sopenharmony_ci	if (!has_bklog)
6098c2ecf20Sopenharmony_ci		req->base.complete(&req->base, ecode);
6108c2ecf20Sopenharmony_ci	else
6118c2ecf20Sopenharmony_ci		crypto_finalize_hash_request(jrp->engine, req, ecode);
6128c2ecf20Sopenharmony_ci}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic void ahash_done(struct device *jrdev, u32 *desc, u32 err,
6158c2ecf20Sopenharmony_ci		       void *context)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	ahash_done_cpy(jrdev, desc, err, context, DMA_FROM_DEVICE);
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_cistatic void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
6218c2ecf20Sopenharmony_ci			       void *context)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	ahash_done_cpy(jrdev, desc, err, context, DMA_BIDIRECTIONAL);
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic inline void ahash_done_switch(struct device *jrdev, u32 *desc, u32 err,
6278c2ecf20Sopenharmony_ci				     void *context, enum dma_data_direction dir)
6288c2ecf20Sopenharmony_ci{
6298c2ecf20Sopenharmony_ci	struct ahash_request *req = context;
6308c2ecf20Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
6318c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
6328c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
6338c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
6348c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
6358c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
6368c2ecf20Sopenharmony_ci	int ecode = 0;
6378c2ecf20Sopenharmony_ci	bool has_bklog;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	edesc = state->edesc;
6428c2ecf20Sopenharmony_ci	has_bklog = edesc->bklog;
6438c2ecf20Sopenharmony_ci	if (err)
6448c2ecf20Sopenharmony_ci		ecode = caam_jr_strstatus(jrdev, err);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, dir);
6478c2ecf20Sopenharmony_ci	kfree(edesc);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	scatterwalk_map_and_copy(state->buf, req->src,
6508c2ecf20Sopenharmony_ci				 req->nbytes - state->next_buflen,
6518c2ecf20Sopenharmony_ci				 state->next_buflen, 0);
6528c2ecf20Sopenharmony_ci	state->buflen = state->next_buflen;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
6558c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, state->buf,
6568c2ecf20Sopenharmony_ci			     state->buflen, 1);
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
6598c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
6608c2ecf20Sopenharmony_ci			     ctx->ctx_len, 1);
6618c2ecf20Sopenharmony_ci	if (req->result)
6628c2ecf20Sopenharmony_ci		print_hex_dump_debug("result@"__stringify(__LINE__)": ",
6638c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, req->result,
6648c2ecf20Sopenharmony_ci				     digestsize, 1);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	/*
6678c2ecf20Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
6688c2ecf20Sopenharmony_ci	 * by CAAM, not crypto engine.
6698c2ecf20Sopenharmony_ci	 */
6708c2ecf20Sopenharmony_ci	if (!has_bklog)
6718c2ecf20Sopenharmony_ci		req->base.complete(&req->base, ecode);
6728c2ecf20Sopenharmony_ci	else
6738c2ecf20Sopenharmony_ci		crypto_finalize_hash_request(jrp->engine, req, ecode);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_cistatic void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err,
6788c2ecf20Sopenharmony_ci			  void *context)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	ahash_done_switch(jrdev, desc, err, context, DMA_BIDIRECTIONAL);
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_cistatic void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
6848c2ecf20Sopenharmony_ci			       void *context)
6858c2ecf20Sopenharmony_ci{
6868c2ecf20Sopenharmony_ci	ahash_done_switch(jrdev, desc, err, context, DMA_FROM_DEVICE);
6878c2ecf20Sopenharmony_ci}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci/*
6908c2ecf20Sopenharmony_ci * Allocate an enhanced descriptor, which contains the hardware descriptor
6918c2ecf20Sopenharmony_ci * and space for hardware scatter table containing sg_num entries.
6928c2ecf20Sopenharmony_ci */
6938c2ecf20Sopenharmony_cistatic struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req,
6948c2ecf20Sopenharmony_ci					     int sg_num, u32 *sh_desc,
6958c2ecf20Sopenharmony_ci					     dma_addr_t sh_desc_dma)
6968c2ecf20Sopenharmony_ci{
6978c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
6988c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
6998c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
7008c2ecf20Sopenharmony_ci	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
7018c2ecf20Sopenharmony_ci		       GFP_KERNEL : GFP_ATOMIC;
7028c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
7038c2ecf20Sopenharmony_ci	unsigned int sg_size = sg_num * sizeof(struct sec4_sg_entry);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	edesc = kzalloc(sizeof(*edesc) + sg_size, GFP_DMA | flags);
7068c2ecf20Sopenharmony_ci	if (!edesc) {
7078c2ecf20Sopenharmony_ci		dev_err(ctx->jrdev, "could not allocate extended descriptor\n");
7088c2ecf20Sopenharmony_ci		return NULL;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	state->edesc = edesc;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	init_job_desc_shared(edesc->hw_desc, sh_desc_dma, desc_len(sh_desc),
7148c2ecf20Sopenharmony_ci			     HDR_SHARE_DEFER | HDR_REVERSE);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	return edesc;
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_cistatic int ahash_edesc_add_src(struct caam_hash_ctx *ctx,
7208c2ecf20Sopenharmony_ci			       struct ahash_edesc *edesc,
7218c2ecf20Sopenharmony_ci			       struct ahash_request *req, int nents,
7228c2ecf20Sopenharmony_ci			       unsigned int first_sg,
7238c2ecf20Sopenharmony_ci			       unsigned int first_bytes, size_t to_hash)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	dma_addr_t src_dma;
7268c2ecf20Sopenharmony_ci	u32 options;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	if (nents > 1 || first_sg) {
7298c2ecf20Sopenharmony_ci		struct sec4_sg_entry *sg = edesc->sec4_sg;
7308c2ecf20Sopenharmony_ci		unsigned int sgsize = sizeof(*sg) *
7318c2ecf20Sopenharmony_ci				      pad_sg_nents(first_sg + nents);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci		sg_to_sec4_sg_last(req->src, to_hash, sg + first_sg, 0);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci		src_dma = dma_map_single(ctx->jrdev, sg, sgsize, DMA_TO_DEVICE);
7368c2ecf20Sopenharmony_ci		if (dma_mapping_error(ctx->jrdev, src_dma)) {
7378c2ecf20Sopenharmony_ci			dev_err(ctx->jrdev, "unable to map S/G table\n");
7388c2ecf20Sopenharmony_ci			return -ENOMEM;
7398c2ecf20Sopenharmony_ci		}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci		edesc->sec4_sg_bytes = sgsize;
7428c2ecf20Sopenharmony_ci		edesc->sec4_sg_dma = src_dma;
7438c2ecf20Sopenharmony_ci		options = LDST_SGF;
7448c2ecf20Sopenharmony_ci	} else {
7458c2ecf20Sopenharmony_ci		src_dma = sg_dma_address(req->src);
7468c2ecf20Sopenharmony_ci		options = 0;
7478c2ecf20Sopenharmony_ci	}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	append_seq_in_ptr(edesc->hw_desc, src_dma, first_bytes + to_hash,
7508c2ecf20Sopenharmony_ci			  options);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	return 0;
7538c2ecf20Sopenharmony_ci}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_cistatic int ahash_do_one_req(struct crypto_engine *engine, void *areq)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
7588c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
7598c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
7608c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
7618c2ecf20Sopenharmony_ci	u32 *desc = state->edesc->hw_desc;
7628c2ecf20Sopenharmony_ci	int ret;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	state->edesc->bklog = true;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	ret = caam_jr_enqueue(jrdev, desc, state->ahash_op_done, req);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
7698c2ecf20Sopenharmony_ci		ahash_unmap(jrdev, state->edesc, req, 0);
7708c2ecf20Sopenharmony_ci		kfree(state->edesc);
7718c2ecf20Sopenharmony_ci	} else {
7728c2ecf20Sopenharmony_ci		ret = 0;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	return ret;
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_cistatic int ahash_enqueue_req(struct device *jrdev,
7798c2ecf20Sopenharmony_ci			     void (*cbk)(struct device *jrdev, u32 *desc,
7808c2ecf20Sopenharmony_ci					 u32 err, void *context),
7818c2ecf20Sopenharmony_ci			     struct ahash_request *req,
7828c2ecf20Sopenharmony_ci			     int dst_len, enum dma_data_direction dir)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev);
7858c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
7868c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc = state->edesc;
7878c2ecf20Sopenharmony_ci	u32 *desc = edesc->hw_desc;
7888c2ecf20Sopenharmony_ci	int ret;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	state->ahash_op_done = cbk;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	/*
7938c2ecf20Sopenharmony_ci	 * Only the backlog request are sent to crypto-engine since the others
7948c2ecf20Sopenharmony_ci	 * can be handled by CAAM, if free, especially since JR has up to 1024
7958c2ecf20Sopenharmony_ci	 * entries (more than the 10 entries from crypto-engine).
7968c2ecf20Sopenharmony_ci	 */
7978c2ecf20Sopenharmony_ci	if (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
7988c2ecf20Sopenharmony_ci		ret = crypto_transfer_hash_request_to_engine(jrpriv->engine,
7998c2ecf20Sopenharmony_ci							     req);
8008c2ecf20Sopenharmony_ci	else
8018c2ecf20Sopenharmony_ci		ret = caam_jr_enqueue(jrdev, desc, cbk, req);
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	if ((ret != -EINPROGRESS) && (ret != -EBUSY)) {
8048c2ecf20Sopenharmony_ci		ahash_unmap_ctx(jrdev, edesc, req, dst_len, dir);
8058c2ecf20Sopenharmony_ci		kfree(edesc);
8068c2ecf20Sopenharmony_ci	}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	return ret;
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci/* submit update job descriptor */
8128c2ecf20Sopenharmony_cistatic int ahash_update_ctx(struct ahash_request *req)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
8158c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
8168c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
8178c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
8188c2ecf20Sopenharmony_ci	u8 *buf = state->buf;
8198c2ecf20Sopenharmony_ci	int *buflen = &state->buflen;
8208c2ecf20Sopenharmony_ci	int *next_buflen = &state->next_buflen;
8218c2ecf20Sopenharmony_ci	int blocksize = crypto_ahash_blocksize(ahash);
8228c2ecf20Sopenharmony_ci	int in_len = *buflen + req->nbytes, to_hash;
8238c2ecf20Sopenharmony_ci	u32 *desc;
8248c2ecf20Sopenharmony_ci	int src_nents, mapped_nents, sec4_sg_bytes, sec4_sg_src_index;
8258c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
8268c2ecf20Sopenharmony_ci	int ret = 0;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	*next_buflen = in_len & (blocksize - 1);
8298c2ecf20Sopenharmony_ci	to_hash = in_len - *next_buflen;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/*
8328c2ecf20Sopenharmony_ci	 * For XCBC and CMAC, if to_hash is multiple of block size,
8338c2ecf20Sopenharmony_ci	 * keep last block in internal buffer
8348c2ecf20Sopenharmony_ci	 */
8358c2ecf20Sopenharmony_ci	if ((is_xcbc_aes(ctx->adata.algtype) ||
8368c2ecf20Sopenharmony_ci	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
8378c2ecf20Sopenharmony_ci	     (*next_buflen == 0)) {
8388c2ecf20Sopenharmony_ci		*next_buflen = blocksize;
8398c2ecf20Sopenharmony_ci		to_hash -= blocksize;
8408c2ecf20Sopenharmony_ci	}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	if (to_hash) {
8438c2ecf20Sopenharmony_ci		int pad_nents;
8448c2ecf20Sopenharmony_ci		int src_len = req->nbytes - *next_buflen;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci		src_nents = sg_nents_for_len(req->src, src_len);
8478c2ecf20Sopenharmony_ci		if (src_nents < 0) {
8488c2ecf20Sopenharmony_ci			dev_err(jrdev, "Invalid number of src SG.\n");
8498c2ecf20Sopenharmony_ci			return src_nents;
8508c2ecf20Sopenharmony_ci		}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci		if (src_nents) {
8538c2ecf20Sopenharmony_ci			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
8548c2ecf20Sopenharmony_ci						  DMA_TO_DEVICE);
8558c2ecf20Sopenharmony_ci			if (!mapped_nents) {
8568c2ecf20Sopenharmony_ci				dev_err(jrdev, "unable to DMA map source\n");
8578c2ecf20Sopenharmony_ci				return -ENOMEM;
8588c2ecf20Sopenharmony_ci			}
8598c2ecf20Sopenharmony_ci		} else {
8608c2ecf20Sopenharmony_ci			mapped_nents = 0;
8618c2ecf20Sopenharmony_ci		}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci		sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
8648c2ecf20Sopenharmony_ci		pad_nents = pad_sg_nents(sec4_sg_src_index + mapped_nents);
8658c2ecf20Sopenharmony_ci		sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci		/*
8688c2ecf20Sopenharmony_ci		 * allocate space for base edesc and hw desc commands,
8698c2ecf20Sopenharmony_ci		 * link tables
8708c2ecf20Sopenharmony_ci		 */
8718c2ecf20Sopenharmony_ci		edesc = ahash_edesc_alloc(req, pad_nents, ctx->sh_desc_update,
8728c2ecf20Sopenharmony_ci					  ctx->sh_desc_update_dma);
8738c2ecf20Sopenharmony_ci		if (!edesc) {
8748c2ecf20Sopenharmony_ci			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
8758c2ecf20Sopenharmony_ci			return -ENOMEM;
8768c2ecf20Sopenharmony_ci		}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci		edesc->src_nents = src_nents;
8798c2ecf20Sopenharmony_ci		edesc->sec4_sg_bytes = sec4_sg_bytes;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci		ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
8828c2ecf20Sopenharmony_ci					 edesc->sec4_sg, DMA_BIDIRECTIONAL);
8838c2ecf20Sopenharmony_ci		if (ret)
8848c2ecf20Sopenharmony_ci			goto unmap_ctx;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci		ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
8878c2ecf20Sopenharmony_ci		if (ret)
8888c2ecf20Sopenharmony_ci			goto unmap_ctx;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci		if (mapped_nents)
8918c2ecf20Sopenharmony_ci			sg_to_sec4_sg_last(req->src, src_len,
8928c2ecf20Sopenharmony_ci					   edesc->sec4_sg + sec4_sg_src_index,
8938c2ecf20Sopenharmony_ci					   0);
8948c2ecf20Sopenharmony_ci		else
8958c2ecf20Sopenharmony_ci			sg_to_sec4_set_last(edesc->sec4_sg + sec4_sg_src_index -
8968c2ecf20Sopenharmony_ci					    1);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci		desc = edesc->hw_desc;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
9018c2ecf20Sopenharmony_ci						     sec4_sg_bytes,
9028c2ecf20Sopenharmony_ci						     DMA_TO_DEVICE);
9038c2ecf20Sopenharmony_ci		if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
9048c2ecf20Sopenharmony_ci			dev_err(jrdev, "unable to map S/G table\n");
9058c2ecf20Sopenharmony_ci			ret = -ENOMEM;
9068c2ecf20Sopenharmony_ci			goto unmap_ctx;
9078c2ecf20Sopenharmony_ci		}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci		append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
9108c2ecf20Sopenharmony_ci				       to_hash, LDST_SGF);
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci		append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0);
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
9158c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
9168c2ecf20Sopenharmony_ci				     desc_bytes(desc), 1);
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci		ret = ahash_enqueue_req(jrdev, ahash_done_bi, req,
9198c2ecf20Sopenharmony_ci					ctx->ctx_len, DMA_BIDIRECTIONAL);
9208c2ecf20Sopenharmony_ci	} else if (*next_buflen) {
9218c2ecf20Sopenharmony_ci		scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
9228c2ecf20Sopenharmony_ci					 req->nbytes, 0);
9238c2ecf20Sopenharmony_ci		*buflen = *next_buflen;
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
9268c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
9278c2ecf20Sopenharmony_ci				     *buflen, 1);
9288c2ecf20Sopenharmony_ci	}
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	return ret;
9318c2ecf20Sopenharmony_ciunmap_ctx:
9328c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
9338c2ecf20Sopenharmony_ci	kfree(edesc);
9348c2ecf20Sopenharmony_ci	return ret;
9358c2ecf20Sopenharmony_ci}
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_cistatic int ahash_final_ctx(struct ahash_request *req)
9388c2ecf20Sopenharmony_ci{
9398c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
9408c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
9418c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
9428c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
9438c2ecf20Sopenharmony_ci	int buflen = state->buflen;
9448c2ecf20Sopenharmony_ci	u32 *desc;
9458c2ecf20Sopenharmony_ci	int sec4_sg_bytes;
9468c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
9478c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
9488c2ecf20Sopenharmony_ci	int ret;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	sec4_sg_bytes = pad_sg_nents(1 + (buflen ? 1 : 0)) *
9518c2ecf20Sopenharmony_ci			sizeof(struct sec4_sg_entry);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
9548c2ecf20Sopenharmony_ci	edesc = ahash_edesc_alloc(req, 4, ctx->sh_desc_fin,
9558c2ecf20Sopenharmony_ci				  ctx->sh_desc_fin_dma);
9568c2ecf20Sopenharmony_ci	if (!edesc)
9578c2ecf20Sopenharmony_ci		return -ENOMEM;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	desc = edesc->hw_desc;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	edesc->sec4_sg_bytes = sec4_sg_bytes;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
9648c2ecf20Sopenharmony_ci				 edesc->sec4_sg, DMA_BIDIRECTIONAL);
9658c2ecf20Sopenharmony_ci	if (ret)
9668c2ecf20Sopenharmony_ci		goto unmap_ctx;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
9698c2ecf20Sopenharmony_ci	if (ret)
9708c2ecf20Sopenharmony_ci		goto unmap_ctx;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	sg_to_sec4_set_last(edesc->sec4_sg + (buflen ? 1 : 0));
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
9758c2ecf20Sopenharmony_ci					    sec4_sg_bytes, DMA_TO_DEVICE);
9768c2ecf20Sopenharmony_ci	if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
9778c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to map S/G table\n");
9788c2ecf20Sopenharmony_ci		ret = -ENOMEM;
9798c2ecf20Sopenharmony_ci		goto unmap_ctx;
9808c2ecf20Sopenharmony_ci	}
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
9838c2ecf20Sopenharmony_ci			  LDST_SGF);
9848c2ecf20Sopenharmony_ci	append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
9878c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
9888c2ecf20Sopenharmony_ci			     1);
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req,
9918c2ecf20Sopenharmony_ci				 digestsize, DMA_BIDIRECTIONAL);
9928c2ecf20Sopenharmony_ci unmap_ctx:
9938c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
9948c2ecf20Sopenharmony_ci	kfree(edesc);
9958c2ecf20Sopenharmony_ci	return ret;
9968c2ecf20Sopenharmony_ci}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_cistatic int ahash_finup_ctx(struct ahash_request *req)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
10018c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
10028c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
10038c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
10048c2ecf20Sopenharmony_ci	int buflen = state->buflen;
10058c2ecf20Sopenharmony_ci	u32 *desc;
10068c2ecf20Sopenharmony_ci	int sec4_sg_src_index;
10078c2ecf20Sopenharmony_ci	int src_nents, mapped_nents;
10088c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
10098c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
10108c2ecf20Sopenharmony_ci	int ret;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	src_nents = sg_nents_for_len(req->src, req->nbytes);
10138c2ecf20Sopenharmony_ci	if (src_nents < 0) {
10148c2ecf20Sopenharmony_ci		dev_err(jrdev, "Invalid number of src SG.\n");
10158c2ecf20Sopenharmony_ci		return src_nents;
10168c2ecf20Sopenharmony_ci	}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	if (src_nents) {
10198c2ecf20Sopenharmony_ci		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
10208c2ecf20Sopenharmony_ci					  DMA_TO_DEVICE);
10218c2ecf20Sopenharmony_ci		if (!mapped_nents) {
10228c2ecf20Sopenharmony_ci			dev_err(jrdev, "unable to DMA map source\n");
10238c2ecf20Sopenharmony_ci			return -ENOMEM;
10248c2ecf20Sopenharmony_ci		}
10258c2ecf20Sopenharmony_ci	} else {
10268c2ecf20Sopenharmony_ci		mapped_nents = 0;
10278c2ecf20Sopenharmony_ci	}
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	sec4_sg_src_index = 1 + (buflen ? 1 : 0);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
10328c2ecf20Sopenharmony_ci	edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents,
10338c2ecf20Sopenharmony_ci				  ctx->sh_desc_fin, ctx->sh_desc_fin_dma);
10348c2ecf20Sopenharmony_ci	if (!edesc) {
10358c2ecf20Sopenharmony_ci		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
10368c2ecf20Sopenharmony_ci		return -ENOMEM;
10378c2ecf20Sopenharmony_ci	}
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	desc = edesc->hw_desc;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	edesc->src_nents = src_nents;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
10448c2ecf20Sopenharmony_ci				 edesc->sec4_sg, DMA_BIDIRECTIONAL);
10458c2ecf20Sopenharmony_ci	if (ret)
10468c2ecf20Sopenharmony_ci		goto unmap_ctx;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
10498c2ecf20Sopenharmony_ci	if (ret)
10508c2ecf20Sopenharmony_ci		goto unmap_ctx;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents,
10538c2ecf20Sopenharmony_ci				  sec4_sg_src_index, ctx->ctx_len + buflen,
10548c2ecf20Sopenharmony_ci				  req->nbytes);
10558c2ecf20Sopenharmony_ci	if (ret)
10568c2ecf20Sopenharmony_ci		goto unmap_ctx;
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
10618c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
10628c2ecf20Sopenharmony_ci			     1);
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req,
10658c2ecf20Sopenharmony_ci				 digestsize, DMA_BIDIRECTIONAL);
10668c2ecf20Sopenharmony_ci unmap_ctx:
10678c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
10688c2ecf20Sopenharmony_ci	kfree(edesc);
10698c2ecf20Sopenharmony_ci	return ret;
10708c2ecf20Sopenharmony_ci}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_cistatic int ahash_digest(struct ahash_request *req)
10738c2ecf20Sopenharmony_ci{
10748c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
10758c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
10768c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
10778c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
10788c2ecf20Sopenharmony_ci	u32 *desc;
10798c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
10808c2ecf20Sopenharmony_ci	int src_nents, mapped_nents;
10818c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
10828c2ecf20Sopenharmony_ci	int ret;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	state->buf_dma = 0;
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	src_nents = sg_nents_for_len(req->src, req->nbytes);
10878c2ecf20Sopenharmony_ci	if (src_nents < 0) {
10888c2ecf20Sopenharmony_ci		dev_err(jrdev, "Invalid number of src SG.\n");
10898c2ecf20Sopenharmony_ci		return src_nents;
10908c2ecf20Sopenharmony_ci	}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	if (src_nents) {
10938c2ecf20Sopenharmony_ci		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
10948c2ecf20Sopenharmony_ci					  DMA_TO_DEVICE);
10958c2ecf20Sopenharmony_ci		if (!mapped_nents) {
10968c2ecf20Sopenharmony_ci			dev_err(jrdev, "unable to map source for DMA\n");
10978c2ecf20Sopenharmony_ci			return -ENOMEM;
10988c2ecf20Sopenharmony_ci		}
10998c2ecf20Sopenharmony_ci	} else {
11008c2ecf20Sopenharmony_ci		mapped_nents = 0;
11018c2ecf20Sopenharmony_ci	}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
11048c2ecf20Sopenharmony_ci	edesc = ahash_edesc_alloc(req, mapped_nents > 1 ? mapped_nents : 0,
11058c2ecf20Sopenharmony_ci				  ctx->sh_desc_digest, ctx->sh_desc_digest_dma);
11068c2ecf20Sopenharmony_ci	if (!edesc) {
11078c2ecf20Sopenharmony_ci		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
11088c2ecf20Sopenharmony_ci		return -ENOMEM;
11098c2ecf20Sopenharmony_ci	}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	edesc->src_nents = src_nents;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
11148c2ecf20Sopenharmony_ci				  req->nbytes);
11158c2ecf20Sopenharmony_ci	if (ret) {
11168c2ecf20Sopenharmony_ci		ahash_unmap(jrdev, edesc, req, digestsize);
11178c2ecf20Sopenharmony_ci		kfree(edesc);
11188c2ecf20Sopenharmony_ci		return ret;
11198c2ecf20Sopenharmony_ci	}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	desc = edesc->hw_desc;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
11248c2ecf20Sopenharmony_ci	if (ret) {
11258c2ecf20Sopenharmony_ci		ahash_unmap(jrdev, edesc, req, digestsize);
11268c2ecf20Sopenharmony_ci		kfree(edesc);
11278c2ecf20Sopenharmony_ci		return -ENOMEM;
11288c2ecf20Sopenharmony_ci	}
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
11318c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
11328c2ecf20Sopenharmony_ci			     1);
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done, req, digestsize,
11358c2ecf20Sopenharmony_ci				 DMA_FROM_DEVICE);
11368c2ecf20Sopenharmony_ci}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci/* submit ahash final if it the first job descriptor */
11398c2ecf20Sopenharmony_cistatic int ahash_final_no_ctx(struct ahash_request *req)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
11428c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
11438c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
11448c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
11458c2ecf20Sopenharmony_ci	u8 *buf = state->buf;
11468c2ecf20Sopenharmony_ci	int buflen = state->buflen;
11478c2ecf20Sopenharmony_ci	u32 *desc;
11488c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
11498c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
11508c2ecf20Sopenharmony_ci	int ret;
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
11538c2ecf20Sopenharmony_ci	edesc = ahash_edesc_alloc(req, 0, ctx->sh_desc_digest,
11548c2ecf20Sopenharmony_ci				  ctx->sh_desc_digest_dma);
11558c2ecf20Sopenharmony_ci	if (!edesc)
11568c2ecf20Sopenharmony_ci		return -ENOMEM;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	desc = edesc->hw_desc;
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	if (buflen) {
11618c2ecf20Sopenharmony_ci		state->buf_dma = dma_map_single(jrdev, buf, buflen,
11628c2ecf20Sopenharmony_ci						DMA_TO_DEVICE);
11638c2ecf20Sopenharmony_ci		if (dma_mapping_error(jrdev, state->buf_dma)) {
11648c2ecf20Sopenharmony_ci			dev_err(jrdev, "unable to map src\n");
11658c2ecf20Sopenharmony_ci			goto unmap;
11668c2ecf20Sopenharmony_ci		}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci		append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
11698c2ecf20Sopenharmony_ci	}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
11728c2ecf20Sopenharmony_ci	if (ret)
11738c2ecf20Sopenharmony_ci		goto unmap;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
11768c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
11778c2ecf20Sopenharmony_ci			     1);
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done, req,
11808c2ecf20Sopenharmony_ci				 digestsize, DMA_FROM_DEVICE);
11818c2ecf20Sopenharmony_ci unmap:
11828c2ecf20Sopenharmony_ci	ahash_unmap(jrdev, edesc, req, digestsize);
11838c2ecf20Sopenharmony_ci	kfree(edesc);
11848c2ecf20Sopenharmony_ci	return -ENOMEM;
11858c2ecf20Sopenharmony_ci}
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci/* submit ahash update if it the first job descriptor after update */
11888c2ecf20Sopenharmony_cistatic int ahash_update_no_ctx(struct ahash_request *req)
11898c2ecf20Sopenharmony_ci{
11908c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
11918c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
11928c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
11938c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
11948c2ecf20Sopenharmony_ci	u8 *buf = state->buf;
11958c2ecf20Sopenharmony_ci	int *buflen = &state->buflen;
11968c2ecf20Sopenharmony_ci	int *next_buflen = &state->next_buflen;
11978c2ecf20Sopenharmony_ci	int blocksize = crypto_ahash_blocksize(ahash);
11988c2ecf20Sopenharmony_ci	int in_len = *buflen + req->nbytes, to_hash;
11998c2ecf20Sopenharmony_ci	int sec4_sg_bytes, src_nents, mapped_nents;
12008c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
12018c2ecf20Sopenharmony_ci	u32 *desc;
12028c2ecf20Sopenharmony_ci	int ret = 0;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	*next_buflen = in_len & (blocksize - 1);
12058c2ecf20Sopenharmony_ci	to_hash = in_len - *next_buflen;
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	/*
12088c2ecf20Sopenharmony_ci	 * For XCBC and CMAC, if to_hash is multiple of block size,
12098c2ecf20Sopenharmony_ci	 * keep last block in internal buffer
12108c2ecf20Sopenharmony_ci	 */
12118c2ecf20Sopenharmony_ci	if ((is_xcbc_aes(ctx->adata.algtype) ||
12128c2ecf20Sopenharmony_ci	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
12138c2ecf20Sopenharmony_ci	     (*next_buflen == 0)) {
12148c2ecf20Sopenharmony_ci		*next_buflen = blocksize;
12158c2ecf20Sopenharmony_ci		to_hash -= blocksize;
12168c2ecf20Sopenharmony_ci	}
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	if (to_hash) {
12198c2ecf20Sopenharmony_ci		int pad_nents;
12208c2ecf20Sopenharmony_ci		int src_len = req->nbytes - *next_buflen;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci		src_nents = sg_nents_for_len(req->src, src_len);
12238c2ecf20Sopenharmony_ci		if (src_nents < 0) {
12248c2ecf20Sopenharmony_ci			dev_err(jrdev, "Invalid number of src SG.\n");
12258c2ecf20Sopenharmony_ci			return src_nents;
12268c2ecf20Sopenharmony_ci		}
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci		if (src_nents) {
12298c2ecf20Sopenharmony_ci			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
12308c2ecf20Sopenharmony_ci						  DMA_TO_DEVICE);
12318c2ecf20Sopenharmony_ci			if (!mapped_nents) {
12328c2ecf20Sopenharmony_ci				dev_err(jrdev, "unable to DMA map source\n");
12338c2ecf20Sopenharmony_ci				return -ENOMEM;
12348c2ecf20Sopenharmony_ci			}
12358c2ecf20Sopenharmony_ci		} else {
12368c2ecf20Sopenharmony_ci			mapped_nents = 0;
12378c2ecf20Sopenharmony_ci		}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci		pad_nents = pad_sg_nents(1 + mapped_nents);
12408c2ecf20Sopenharmony_ci		sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci		/*
12438c2ecf20Sopenharmony_ci		 * allocate space for base edesc and hw desc commands,
12448c2ecf20Sopenharmony_ci		 * link tables
12458c2ecf20Sopenharmony_ci		 */
12468c2ecf20Sopenharmony_ci		edesc = ahash_edesc_alloc(req, pad_nents,
12478c2ecf20Sopenharmony_ci					  ctx->sh_desc_update_first,
12488c2ecf20Sopenharmony_ci					  ctx->sh_desc_update_first_dma);
12498c2ecf20Sopenharmony_ci		if (!edesc) {
12508c2ecf20Sopenharmony_ci			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
12518c2ecf20Sopenharmony_ci			return -ENOMEM;
12528c2ecf20Sopenharmony_ci		}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci		edesc->src_nents = src_nents;
12558c2ecf20Sopenharmony_ci		edesc->sec4_sg_bytes = sec4_sg_bytes;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci		ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
12588c2ecf20Sopenharmony_ci		if (ret)
12598c2ecf20Sopenharmony_ci			goto unmap_ctx;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci		sg_to_sec4_sg_last(req->src, src_len, edesc->sec4_sg + 1, 0);
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci		desc = edesc->hw_desc;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
12668c2ecf20Sopenharmony_ci						    sec4_sg_bytes,
12678c2ecf20Sopenharmony_ci						    DMA_TO_DEVICE);
12688c2ecf20Sopenharmony_ci		if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
12698c2ecf20Sopenharmony_ci			dev_err(jrdev, "unable to map S/G table\n");
12708c2ecf20Sopenharmony_ci			ret = -ENOMEM;
12718c2ecf20Sopenharmony_ci			goto unmap_ctx;
12728c2ecf20Sopenharmony_ci		}
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci		append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
12778c2ecf20Sopenharmony_ci		if (ret)
12788c2ecf20Sopenharmony_ci			goto unmap_ctx;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
12818c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
12828c2ecf20Sopenharmony_ci				     desc_bytes(desc), 1);
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci		ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req,
12858c2ecf20Sopenharmony_ci					ctx->ctx_len, DMA_TO_DEVICE);
12868c2ecf20Sopenharmony_ci		if ((ret != -EINPROGRESS) && (ret != -EBUSY))
12878c2ecf20Sopenharmony_ci			return ret;
12888c2ecf20Sopenharmony_ci		state->update = ahash_update_ctx;
12898c2ecf20Sopenharmony_ci		state->finup = ahash_finup_ctx;
12908c2ecf20Sopenharmony_ci		state->final = ahash_final_ctx;
12918c2ecf20Sopenharmony_ci	} else if (*next_buflen) {
12928c2ecf20Sopenharmony_ci		scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
12938c2ecf20Sopenharmony_ci					 req->nbytes, 0);
12948c2ecf20Sopenharmony_ci		*buflen = *next_buflen;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
12978c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
12988c2ecf20Sopenharmony_ci				     *buflen, 1);
12998c2ecf20Sopenharmony_ci	}
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	return ret;
13028c2ecf20Sopenharmony_ci unmap_ctx:
13038c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
13048c2ecf20Sopenharmony_ci	kfree(edesc);
13058c2ecf20Sopenharmony_ci	return ret;
13068c2ecf20Sopenharmony_ci}
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci/* submit ahash finup if it the first job descriptor after update */
13098c2ecf20Sopenharmony_cistatic int ahash_finup_no_ctx(struct ahash_request *req)
13108c2ecf20Sopenharmony_ci{
13118c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
13128c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
13138c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
13148c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
13158c2ecf20Sopenharmony_ci	int buflen = state->buflen;
13168c2ecf20Sopenharmony_ci	u32 *desc;
13178c2ecf20Sopenharmony_ci	int sec4_sg_bytes, sec4_sg_src_index, src_nents, mapped_nents;
13188c2ecf20Sopenharmony_ci	int digestsize = crypto_ahash_digestsize(ahash);
13198c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
13208c2ecf20Sopenharmony_ci	int ret;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	src_nents = sg_nents_for_len(req->src, req->nbytes);
13238c2ecf20Sopenharmony_ci	if (src_nents < 0) {
13248c2ecf20Sopenharmony_ci		dev_err(jrdev, "Invalid number of src SG.\n");
13258c2ecf20Sopenharmony_ci		return src_nents;
13268c2ecf20Sopenharmony_ci	}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	if (src_nents) {
13298c2ecf20Sopenharmony_ci		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
13308c2ecf20Sopenharmony_ci					  DMA_TO_DEVICE);
13318c2ecf20Sopenharmony_ci		if (!mapped_nents) {
13328c2ecf20Sopenharmony_ci			dev_err(jrdev, "unable to DMA map source\n");
13338c2ecf20Sopenharmony_ci			return -ENOMEM;
13348c2ecf20Sopenharmony_ci		}
13358c2ecf20Sopenharmony_ci	} else {
13368c2ecf20Sopenharmony_ci		mapped_nents = 0;
13378c2ecf20Sopenharmony_ci	}
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	sec4_sg_src_index = 2;
13408c2ecf20Sopenharmony_ci	sec4_sg_bytes = (sec4_sg_src_index + mapped_nents) *
13418c2ecf20Sopenharmony_ci			 sizeof(struct sec4_sg_entry);
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	/* allocate space for base edesc and hw desc commands, link tables */
13448c2ecf20Sopenharmony_ci	edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents,
13458c2ecf20Sopenharmony_ci				  ctx->sh_desc_digest, ctx->sh_desc_digest_dma);
13468c2ecf20Sopenharmony_ci	if (!edesc) {
13478c2ecf20Sopenharmony_ci		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
13488c2ecf20Sopenharmony_ci		return -ENOMEM;
13498c2ecf20Sopenharmony_ci	}
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	desc = edesc->hw_desc;
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	edesc->src_nents = src_nents;
13548c2ecf20Sopenharmony_ci	edesc->sec4_sg_bytes = sec4_sg_bytes;
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
13578c2ecf20Sopenharmony_ci	if (ret)
13588c2ecf20Sopenharmony_ci		goto unmap;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 1, buflen,
13618c2ecf20Sopenharmony_ci				  req->nbytes);
13628c2ecf20Sopenharmony_ci	if (ret) {
13638c2ecf20Sopenharmony_ci		dev_err(jrdev, "unable to map S/G table\n");
13648c2ecf20Sopenharmony_ci		goto unmap;
13658c2ecf20Sopenharmony_ci	}
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
13688c2ecf20Sopenharmony_ci	if (ret)
13698c2ecf20Sopenharmony_ci		goto unmap;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
13728c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
13738c2ecf20Sopenharmony_ci			     1);
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	return ahash_enqueue_req(jrdev, ahash_done, req,
13768c2ecf20Sopenharmony_ci				 digestsize, DMA_FROM_DEVICE);
13778c2ecf20Sopenharmony_ci unmap:
13788c2ecf20Sopenharmony_ci	ahash_unmap(jrdev, edesc, req, digestsize);
13798c2ecf20Sopenharmony_ci	kfree(edesc);
13808c2ecf20Sopenharmony_ci	return -ENOMEM;
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci/* submit first update job descriptor after init */
13858c2ecf20Sopenharmony_cistatic int ahash_update_first(struct ahash_request *req)
13868c2ecf20Sopenharmony_ci{
13878c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
13888c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
13898c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
13908c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->jrdev;
13918c2ecf20Sopenharmony_ci	u8 *buf = state->buf;
13928c2ecf20Sopenharmony_ci	int *buflen = &state->buflen;
13938c2ecf20Sopenharmony_ci	int *next_buflen = &state->next_buflen;
13948c2ecf20Sopenharmony_ci	int to_hash;
13958c2ecf20Sopenharmony_ci	int blocksize = crypto_ahash_blocksize(ahash);
13968c2ecf20Sopenharmony_ci	u32 *desc;
13978c2ecf20Sopenharmony_ci	int src_nents, mapped_nents;
13988c2ecf20Sopenharmony_ci	struct ahash_edesc *edesc;
13998c2ecf20Sopenharmony_ci	int ret = 0;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	*next_buflen = req->nbytes & (blocksize - 1);
14028c2ecf20Sopenharmony_ci	to_hash = req->nbytes - *next_buflen;
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	/*
14058c2ecf20Sopenharmony_ci	 * For XCBC and CMAC, if to_hash is multiple of block size,
14068c2ecf20Sopenharmony_ci	 * keep last block in internal buffer
14078c2ecf20Sopenharmony_ci	 */
14088c2ecf20Sopenharmony_ci	if ((is_xcbc_aes(ctx->adata.algtype) ||
14098c2ecf20Sopenharmony_ci	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
14108c2ecf20Sopenharmony_ci	     (*next_buflen == 0)) {
14118c2ecf20Sopenharmony_ci		*next_buflen = blocksize;
14128c2ecf20Sopenharmony_ci		to_hash -= blocksize;
14138c2ecf20Sopenharmony_ci	}
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci	if (to_hash) {
14168c2ecf20Sopenharmony_ci		src_nents = sg_nents_for_len(req->src,
14178c2ecf20Sopenharmony_ci					     req->nbytes - *next_buflen);
14188c2ecf20Sopenharmony_ci		if (src_nents < 0) {
14198c2ecf20Sopenharmony_ci			dev_err(jrdev, "Invalid number of src SG.\n");
14208c2ecf20Sopenharmony_ci			return src_nents;
14218c2ecf20Sopenharmony_ci		}
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci		if (src_nents) {
14248c2ecf20Sopenharmony_ci			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
14258c2ecf20Sopenharmony_ci						  DMA_TO_DEVICE);
14268c2ecf20Sopenharmony_ci			if (!mapped_nents) {
14278c2ecf20Sopenharmony_ci				dev_err(jrdev, "unable to map source for DMA\n");
14288c2ecf20Sopenharmony_ci				return -ENOMEM;
14298c2ecf20Sopenharmony_ci			}
14308c2ecf20Sopenharmony_ci		} else {
14318c2ecf20Sopenharmony_ci			mapped_nents = 0;
14328c2ecf20Sopenharmony_ci		}
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci		/*
14358c2ecf20Sopenharmony_ci		 * allocate space for base edesc and hw desc commands,
14368c2ecf20Sopenharmony_ci		 * link tables
14378c2ecf20Sopenharmony_ci		 */
14388c2ecf20Sopenharmony_ci		edesc = ahash_edesc_alloc(req, mapped_nents > 1 ?
14398c2ecf20Sopenharmony_ci					  mapped_nents : 0,
14408c2ecf20Sopenharmony_ci					  ctx->sh_desc_update_first,
14418c2ecf20Sopenharmony_ci					  ctx->sh_desc_update_first_dma);
14428c2ecf20Sopenharmony_ci		if (!edesc) {
14438c2ecf20Sopenharmony_ci			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
14448c2ecf20Sopenharmony_ci			return -ENOMEM;
14458c2ecf20Sopenharmony_ci		}
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_ci		edesc->src_nents = src_nents;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci		ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
14508c2ecf20Sopenharmony_ci					  to_hash);
14518c2ecf20Sopenharmony_ci		if (ret)
14528c2ecf20Sopenharmony_ci			goto unmap_ctx;
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci		desc = edesc->hw_desc;
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
14578c2ecf20Sopenharmony_ci		if (ret)
14588c2ecf20Sopenharmony_ci			goto unmap_ctx;
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_ci		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
14618c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
14628c2ecf20Sopenharmony_ci				     desc_bytes(desc), 1);
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci		ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req,
14658c2ecf20Sopenharmony_ci					ctx->ctx_len, DMA_TO_DEVICE);
14668c2ecf20Sopenharmony_ci		if ((ret != -EINPROGRESS) && (ret != -EBUSY))
14678c2ecf20Sopenharmony_ci			return ret;
14688c2ecf20Sopenharmony_ci		state->update = ahash_update_ctx;
14698c2ecf20Sopenharmony_ci		state->finup = ahash_finup_ctx;
14708c2ecf20Sopenharmony_ci		state->final = ahash_final_ctx;
14718c2ecf20Sopenharmony_ci	} else if (*next_buflen) {
14728c2ecf20Sopenharmony_ci		state->update = ahash_update_no_ctx;
14738c2ecf20Sopenharmony_ci		state->finup = ahash_finup_no_ctx;
14748c2ecf20Sopenharmony_ci		state->final = ahash_final_no_ctx;
14758c2ecf20Sopenharmony_ci		scatterwalk_map_and_copy(buf, req->src, 0,
14768c2ecf20Sopenharmony_ci					 req->nbytes, 0);
14778c2ecf20Sopenharmony_ci		*buflen = *next_buflen;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
14808c2ecf20Sopenharmony_ci				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
14818c2ecf20Sopenharmony_ci				     *buflen, 1);
14828c2ecf20Sopenharmony_ci	}
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	return ret;
14858c2ecf20Sopenharmony_ci unmap_ctx:
14868c2ecf20Sopenharmony_ci	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
14878c2ecf20Sopenharmony_ci	kfree(edesc);
14888c2ecf20Sopenharmony_ci	return ret;
14898c2ecf20Sopenharmony_ci}
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_cistatic int ahash_finup_first(struct ahash_request *req)
14928c2ecf20Sopenharmony_ci{
14938c2ecf20Sopenharmony_ci	return ahash_digest(req);
14948c2ecf20Sopenharmony_ci}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_cistatic int ahash_init(struct ahash_request *req)
14978c2ecf20Sopenharmony_ci{
14988c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	state->update = ahash_update_first;
15018c2ecf20Sopenharmony_ci	state->finup = ahash_finup_first;
15028c2ecf20Sopenharmony_ci	state->final = ahash_final_no_ctx;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	state->ctx_dma = 0;
15058c2ecf20Sopenharmony_ci	state->ctx_dma_len = 0;
15068c2ecf20Sopenharmony_ci	state->buf_dma = 0;
15078c2ecf20Sopenharmony_ci	state->buflen = 0;
15088c2ecf20Sopenharmony_ci	state->next_buflen = 0;
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci	return 0;
15118c2ecf20Sopenharmony_ci}
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_cistatic int ahash_update(struct ahash_request *req)
15148c2ecf20Sopenharmony_ci{
15158c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	return state->update(req);
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic int ahash_finup(struct ahash_request *req)
15218c2ecf20Sopenharmony_ci{
15228c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	return state->finup(req);
15258c2ecf20Sopenharmony_ci}
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_cistatic int ahash_final(struct ahash_request *req)
15288c2ecf20Sopenharmony_ci{
15298c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	return state->final(req);
15328c2ecf20Sopenharmony_ci}
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_cistatic int ahash_export(struct ahash_request *req, void *out)
15358c2ecf20Sopenharmony_ci{
15368c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
15378c2ecf20Sopenharmony_ci	struct caam_export_state *export = out;
15388c2ecf20Sopenharmony_ci	u8 *buf = state->buf;
15398c2ecf20Sopenharmony_ci	int len = state->buflen;
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_ci	memcpy(export->buf, buf, len);
15428c2ecf20Sopenharmony_ci	memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx));
15438c2ecf20Sopenharmony_ci	export->buflen = len;
15448c2ecf20Sopenharmony_ci	export->update = state->update;
15458c2ecf20Sopenharmony_ci	export->final = state->final;
15468c2ecf20Sopenharmony_ci	export->finup = state->finup;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	return 0;
15498c2ecf20Sopenharmony_ci}
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_cistatic int ahash_import(struct ahash_request *req, const void *in)
15528c2ecf20Sopenharmony_ci{
15538c2ecf20Sopenharmony_ci	struct caam_hash_state *state = ahash_request_ctx(req);
15548c2ecf20Sopenharmony_ci	const struct caam_export_state *export = in;
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	memset(state, 0, sizeof(*state));
15578c2ecf20Sopenharmony_ci	memcpy(state->buf, export->buf, export->buflen);
15588c2ecf20Sopenharmony_ci	memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx));
15598c2ecf20Sopenharmony_ci	state->buflen = export->buflen;
15608c2ecf20Sopenharmony_ci	state->update = export->update;
15618c2ecf20Sopenharmony_ci	state->final = export->final;
15628c2ecf20Sopenharmony_ci	state->finup = export->finup;
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	return 0;
15658c2ecf20Sopenharmony_ci}
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_cistruct caam_hash_template {
15688c2ecf20Sopenharmony_ci	char name[CRYPTO_MAX_ALG_NAME];
15698c2ecf20Sopenharmony_ci	char driver_name[CRYPTO_MAX_ALG_NAME];
15708c2ecf20Sopenharmony_ci	char hmac_name[CRYPTO_MAX_ALG_NAME];
15718c2ecf20Sopenharmony_ci	char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
15728c2ecf20Sopenharmony_ci	unsigned int blocksize;
15738c2ecf20Sopenharmony_ci	struct ahash_alg template_ahash;
15748c2ecf20Sopenharmony_ci	u32 alg_type;
15758c2ecf20Sopenharmony_ci};
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci/* ahash descriptors */
15788c2ecf20Sopenharmony_cistatic struct caam_hash_template driver_hash[] = {
15798c2ecf20Sopenharmony_ci	{
15808c2ecf20Sopenharmony_ci		.name = "sha1",
15818c2ecf20Sopenharmony_ci		.driver_name = "sha1-caam",
15828c2ecf20Sopenharmony_ci		.hmac_name = "hmac(sha1)",
15838c2ecf20Sopenharmony_ci		.hmac_driver_name = "hmac-sha1-caam",
15848c2ecf20Sopenharmony_ci		.blocksize = SHA1_BLOCK_SIZE,
15858c2ecf20Sopenharmony_ci		.template_ahash = {
15868c2ecf20Sopenharmony_ci			.init = ahash_init,
15878c2ecf20Sopenharmony_ci			.update = ahash_update,
15888c2ecf20Sopenharmony_ci			.final = ahash_final,
15898c2ecf20Sopenharmony_ci			.finup = ahash_finup,
15908c2ecf20Sopenharmony_ci			.digest = ahash_digest,
15918c2ecf20Sopenharmony_ci			.export = ahash_export,
15928c2ecf20Sopenharmony_ci			.import = ahash_import,
15938c2ecf20Sopenharmony_ci			.setkey = ahash_setkey,
15948c2ecf20Sopenharmony_ci			.halg = {
15958c2ecf20Sopenharmony_ci				.digestsize = SHA1_DIGEST_SIZE,
15968c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
15978c2ecf20Sopenharmony_ci			},
15988c2ecf20Sopenharmony_ci		},
15998c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA1,
16008c2ecf20Sopenharmony_ci	}, {
16018c2ecf20Sopenharmony_ci		.name = "sha224",
16028c2ecf20Sopenharmony_ci		.driver_name = "sha224-caam",
16038c2ecf20Sopenharmony_ci		.hmac_name = "hmac(sha224)",
16048c2ecf20Sopenharmony_ci		.hmac_driver_name = "hmac-sha224-caam",
16058c2ecf20Sopenharmony_ci		.blocksize = SHA224_BLOCK_SIZE,
16068c2ecf20Sopenharmony_ci		.template_ahash = {
16078c2ecf20Sopenharmony_ci			.init = ahash_init,
16088c2ecf20Sopenharmony_ci			.update = ahash_update,
16098c2ecf20Sopenharmony_ci			.final = ahash_final,
16108c2ecf20Sopenharmony_ci			.finup = ahash_finup,
16118c2ecf20Sopenharmony_ci			.digest = ahash_digest,
16128c2ecf20Sopenharmony_ci			.export = ahash_export,
16138c2ecf20Sopenharmony_ci			.import = ahash_import,
16148c2ecf20Sopenharmony_ci			.setkey = ahash_setkey,
16158c2ecf20Sopenharmony_ci			.halg = {
16168c2ecf20Sopenharmony_ci				.digestsize = SHA224_DIGEST_SIZE,
16178c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
16188c2ecf20Sopenharmony_ci			},
16198c2ecf20Sopenharmony_ci		},
16208c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA224,
16218c2ecf20Sopenharmony_ci	}, {
16228c2ecf20Sopenharmony_ci		.name = "sha256",
16238c2ecf20Sopenharmony_ci		.driver_name = "sha256-caam",
16248c2ecf20Sopenharmony_ci		.hmac_name = "hmac(sha256)",
16258c2ecf20Sopenharmony_ci		.hmac_driver_name = "hmac-sha256-caam",
16268c2ecf20Sopenharmony_ci		.blocksize = SHA256_BLOCK_SIZE,
16278c2ecf20Sopenharmony_ci		.template_ahash = {
16288c2ecf20Sopenharmony_ci			.init = ahash_init,
16298c2ecf20Sopenharmony_ci			.update = ahash_update,
16308c2ecf20Sopenharmony_ci			.final = ahash_final,
16318c2ecf20Sopenharmony_ci			.finup = ahash_finup,
16328c2ecf20Sopenharmony_ci			.digest = ahash_digest,
16338c2ecf20Sopenharmony_ci			.export = ahash_export,
16348c2ecf20Sopenharmony_ci			.import = ahash_import,
16358c2ecf20Sopenharmony_ci			.setkey = ahash_setkey,
16368c2ecf20Sopenharmony_ci			.halg = {
16378c2ecf20Sopenharmony_ci				.digestsize = SHA256_DIGEST_SIZE,
16388c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
16398c2ecf20Sopenharmony_ci			},
16408c2ecf20Sopenharmony_ci		},
16418c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA256,
16428c2ecf20Sopenharmony_ci	}, {
16438c2ecf20Sopenharmony_ci		.name = "sha384",
16448c2ecf20Sopenharmony_ci		.driver_name = "sha384-caam",
16458c2ecf20Sopenharmony_ci		.hmac_name = "hmac(sha384)",
16468c2ecf20Sopenharmony_ci		.hmac_driver_name = "hmac-sha384-caam",
16478c2ecf20Sopenharmony_ci		.blocksize = SHA384_BLOCK_SIZE,
16488c2ecf20Sopenharmony_ci		.template_ahash = {
16498c2ecf20Sopenharmony_ci			.init = ahash_init,
16508c2ecf20Sopenharmony_ci			.update = ahash_update,
16518c2ecf20Sopenharmony_ci			.final = ahash_final,
16528c2ecf20Sopenharmony_ci			.finup = ahash_finup,
16538c2ecf20Sopenharmony_ci			.digest = ahash_digest,
16548c2ecf20Sopenharmony_ci			.export = ahash_export,
16558c2ecf20Sopenharmony_ci			.import = ahash_import,
16568c2ecf20Sopenharmony_ci			.setkey = ahash_setkey,
16578c2ecf20Sopenharmony_ci			.halg = {
16588c2ecf20Sopenharmony_ci				.digestsize = SHA384_DIGEST_SIZE,
16598c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
16608c2ecf20Sopenharmony_ci			},
16618c2ecf20Sopenharmony_ci		},
16628c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA384,
16638c2ecf20Sopenharmony_ci	}, {
16648c2ecf20Sopenharmony_ci		.name = "sha512",
16658c2ecf20Sopenharmony_ci		.driver_name = "sha512-caam",
16668c2ecf20Sopenharmony_ci		.hmac_name = "hmac(sha512)",
16678c2ecf20Sopenharmony_ci		.hmac_driver_name = "hmac-sha512-caam",
16688c2ecf20Sopenharmony_ci		.blocksize = SHA512_BLOCK_SIZE,
16698c2ecf20Sopenharmony_ci		.template_ahash = {
16708c2ecf20Sopenharmony_ci			.init = ahash_init,
16718c2ecf20Sopenharmony_ci			.update = ahash_update,
16728c2ecf20Sopenharmony_ci			.final = ahash_final,
16738c2ecf20Sopenharmony_ci			.finup = ahash_finup,
16748c2ecf20Sopenharmony_ci			.digest = ahash_digest,
16758c2ecf20Sopenharmony_ci			.export = ahash_export,
16768c2ecf20Sopenharmony_ci			.import = ahash_import,
16778c2ecf20Sopenharmony_ci			.setkey = ahash_setkey,
16788c2ecf20Sopenharmony_ci			.halg = {
16798c2ecf20Sopenharmony_ci				.digestsize = SHA512_DIGEST_SIZE,
16808c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
16818c2ecf20Sopenharmony_ci			},
16828c2ecf20Sopenharmony_ci		},
16838c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_SHA512,
16848c2ecf20Sopenharmony_ci	}, {
16858c2ecf20Sopenharmony_ci		.name = "md5",
16868c2ecf20Sopenharmony_ci		.driver_name = "md5-caam",
16878c2ecf20Sopenharmony_ci		.hmac_name = "hmac(md5)",
16888c2ecf20Sopenharmony_ci		.hmac_driver_name = "hmac-md5-caam",
16898c2ecf20Sopenharmony_ci		.blocksize = MD5_BLOCK_WORDS * 4,
16908c2ecf20Sopenharmony_ci		.template_ahash = {
16918c2ecf20Sopenharmony_ci			.init = ahash_init,
16928c2ecf20Sopenharmony_ci			.update = ahash_update,
16938c2ecf20Sopenharmony_ci			.final = ahash_final,
16948c2ecf20Sopenharmony_ci			.finup = ahash_finup,
16958c2ecf20Sopenharmony_ci			.digest = ahash_digest,
16968c2ecf20Sopenharmony_ci			.export = ahash_export,
16978c2ecf20Sopenharmony_ci			.import = ahash_import,
16988c2ecf20Sopenharmony_ci			.setkey = ahash_setkey,
16998c2ecf20Sopenharmony_ci			.halg = {
17008c2ecf20Sopenharmony_ci				.digestsize = MD5_DIGEST_SIZE,
17018c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
17028c2ecf20Sopenharmony_ci			},
17038c2ecf20Sopenharmony_ci		},
17048c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_MD5,
17058c2ecf20Sopenharmony_ci	}, {
17068c2ecf20Sopenharmony_ci		.hmac_name = "xcbc(aes)",
17078c2ecf20Sopenharmony_ci		.hmac_driver_name = "xcbc-aes-caam",
17088c2ecf20Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
17098c2ecf20Sopenharmony_ci		.template_ahash = {
17108c2ecf20Sopenharmony_ci			.init = ahash_init,
17118c2ecf20Sopenharmony_ci			.update = ahash_update,
17128c2ecf20Sopenharmony_ci			.final = ahash_final,
17138c2ecf20Sopenharmony_ci			.finup = ahash_finup,
17148c2ecf20Sopenharmony_ci			.digest = ahash_digest,
17158c2ecf20Sopenharmony_ci			.export = ahash_export,
17168c2ecf20Sopenharmony_ci			.import = ahash_import,
17178c2ecf20Sopenharmony_ci			.setkey = axcbc_setkey,
17188c2ecf20Sopenharmony_ci			.halg = {
17198c2ecf20Sopenharmony_ci				.digestsize = AES_BLOCK_SIZE,
17208c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
17218c2ecf20Sopenharmony_ci			},
17228c2ecf20Sopenharmony_ci		 },
17238c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
17248c2ecf20Sopenharmony_ci	}, {
17258c2ecf20Sopenharmony_ci		.hmac_name = "cmac(aes)",
17268c2ecf20Sopenharmony_ci		.hmac_driver_name = "cmac-aes-caam",
17278c2ecf20Sopenharmony_ci		.blocksize = AES_BLOCK_SIZE,
17288c2ecf20Sopenharmony_ci		.template_ahash = {
17298c2ecf20Sopenharmony_ci			.init = ahash_init,
17308c2ecf20Sopenharmony_ci			.update = ahash_update,
17318c2ecf20Sopenharmony_ci			.final = ahash_final,
17328c2ecf20Sopenharmony_ci			.finup = ahash_finup,
17338c2ecf20Sopenharmony_ci			.digest = ahash_digest,
17348c2ecf20Sopenharmony_ci			.export = ahash_export,
17358c2ecf20Sopenharmony_ci			.import = ahash_import,
17368c2ecf20Sopenharmony_ci			.setkey = acmac_setkey,
17378c2ecf20Sopenharmony_ci			.halg = {
17388c2ecf20Sopenharmony_ci				.digestsize = AES_BLOCK_SIZE,
17398c2ecf20Sopenharmony_ci				.statesize = sizeof(struct caam_export_state),
17408c2ecf20Sopenharmony_ci			},
17418c2ecf20Sopenharmony_ci		 },
17428c2ecf20Sopenharmony_ci		.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC,
17438c2ecf20Sopenharmony_ci	},
17448c2ecf20Sopenharmony_ci};
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_cistruct caam_hash_alg {
17478c2ecf20Sopenharmony_ci	struct list_head entry;
17488c2ecf20Sopenharmony_ci	int alg_type;
17498c2ecf20Sopenharmony_ci	struct ahash_alg ahash_alg;
17508c2ecf20Sopenharmony_ci};
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_cistatic int caam_hash_cra_init(struct crypto_tfm *tfm)
17538c2ecf20Sopenharmony_ci{
17548c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
17558c2ecf20Sopenharmony_ci	struct crypto_alg *base = tfm->__crt_alg;
17568c2ecf20Sopenharmony_ci	struct hash_alg_common *halg =
17578c2ecf20Sopenharmony_ci		 container_of(base, struct hash_alg_common, base);
17588c2ecf20Sopenharmony_ci	struct ahash_alg *alg =
17598c2ecf20Sopenharmony_ci		 container_of(halg, struct ahash_alg, halg);
17608c2ecf20Sopenharmony_ci	struct caam_hash_alg *caam_hash =
17618c2ecf20Sopenharmony_ci		 container_of(alg, struct caam_hash_alg, ahash_alg);
17628c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
17638c2ecf20Sopenharmony_ci	/* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
17648c2ecf20Sopenharmony_ci	static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
17658c2ecf20Sopenharmony_ci					 HASH_MSG_LEN + SHA1_DIGEST_SIZE,
17668c2ecf20Sopenharmony_ci					 HASH_MSG_LEN + 32,
17678c2ecf20Sopenharmony_ci					 HASH_MSG_LEN + SHA256_DIGEST_SIZE,
17688c2ecf20Sopenharmony_ci					 HASH_MSG_LEN + 64,
17698c2ecf20Sopenharmony_ci					 HASH_MSG_LEN + SHA512_DIGEST_SIZE };
17708c2ecf20Sopenharmony_ci	const size_t sh_desc_update_offset = offsetof(struct caam_hash_ctx,
17718c2ecf20Sopenharmony_ci						      sh_desc_update);
17728c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
17738c2ecf20Sopenharmony_ci	struct caam_drv_private *priv;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	/*
17768c2ecf20Sopenharmony_ci	 * Get a Job ring from Job Ring driver to ensure in-order
17778c2ecf20Sopenharmony_ci	 * crypto request processing per tfm
17788c2ecf20Sopenharmony_ci	 */
17798c2ecf20Sopenharmony_ci	ctx->jrdev = caam_jr_alloc();
17808c2ecf20Sopenharmony_ci	if (IS_ERR(ctx->jrdev)) {
17818c2ecf20Sopenharmony_ci		pr_err("Job Ring Device allocation for transform failed\n");
17828c2ecf20Sopenharmony_ci		return PTR_ERR(ctx->jrdev);
17838c2ecf20Sopenharmony_ci	}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	priv = dev_get_drvdata(ctx->jrdev->parent);
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci	if (is_xcbc_aes(caam_hash->alg_type)) {
17888c2ecf20Sopenharmony_ci		ctx->dir = DMA_TO_DEVICE;
17898c2ecf20Sopenharmony_ci		ctx->key_dir = DMA_BIDIRECTIONAL;
17908c2ecf20Sopenharmony_ci		ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
17918c2ecf20Sopenharmony_ci		ctx->ctx_len = 48;
17928c2ecf20Sopenharmony_ci	} else if (is_cmac_aes(caam_hash->alg_type)) {
17938c2ecf20Sopenharmony_ci		ctx->dir = DMA_TO_DEVICE;
17948c2ecf20Sopenharmony_ci		ctx->key_dir = DMA_NONE;
17958c2ecf20Sopenharmony_ci		ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
17968c2ecf20Sopenharmony_ci		ctx->ctx_len = 32;
17978c2ecf20Sopenharmony_ci	} else {
17988c2ecf20Sopenharmony_ci		if (priv->era >= 6) {
17998c2ecf20Sopenharmony_ci			ctx->dir = DMA_BIDIRECTIONAL;
18008c2ecf20Sopenharmony_ci			ctx->key_dir = alg->setkey ? DMA_TO_DEVICE : DMA_NONE;
18018c2ecf20Sopenharmony_ci		} else {
18028c2ecf20Sopenharmony_ci			ctx->dir = DMA_TO_DEVICE;
18038c2ecf20Sopenharmony_ci			ctx->key_dir = DMA_NONE;
18048c2ecf20Sopenharmony_ci		}
18058c2ecf20Sopenharmony_ci		ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
18068c2ecf20Sopenharmony_ci		ctx->ctx_len = runninglen[(ctx->adata.algtype &
18078c2ecf20Sopenharmony_ci					   OP_ALG_ALGSEL_SUBMASK) >>
18088c2ecf20Sopenharmony_ci					  OP_ALG_ALGSEL_SHIFT];
18098c2ecf20Sopenharmony_ci	}
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci	if (ctx->key_dir != DMA_NONE) {
18128c2ecf20Sopenharmony_ci		ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key,
18138c2ecf20Sopenharmony_ci							  ARRAY_SIZE(ctx->key),
18148c2ecf20Sopenharmony_ci							  ctx->key_dir,
18158c2ecf20Sopenharmony_ci							  DMA_ATTR_SKIP_CPU_SYNC);
18168c2ecf20Sopenharmony_ci		if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) {
18178c2ecf20Sopenharmony_ci			dev_err(ctx->jrdev, "unable to map key\n");
18188c2ecf20Sopenharmony_ci			caam_jr_free(ctx->jrdev);
18198c2ecf20Sopenharmony_ci			return -ENOMEM;
18208c2ecf20Sopenharmony_ci		}
18218c2ecf20Sopenharmony_ci	}
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update,
18248c2ecf20Sopenharmony_ci					offsetof(struct caam_hash_ctx, key) -
18258c2ecf20Sopenharmony_ci					sh_desc_update_offset,
18268c2ecf20Sopenharmony_ci					ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
18278c2ecf20Sopenharmony_ci	if (dma_mapping_error(ctx->jrdev, dma_addr)) {
18288c2ecf20Sopenharmony_ci		dev_err(ctx->jrdev, "unable to map shared descriptors\n");
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci		if (ctx->key_dir != DMA_NONE)
18318c2ecf20Sopenharmony_ci			dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
18328c2ecf20Sopenharmony_ci					       ARRAY_SIZE(ctx->key),
18338c2ecf20Sopenharmony_ci					       ctx->key_dir,
18348c2ecf20Sopenharmony_ci					       DMA_ATTR_SKIP_CPU_SYNC);
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci		caam_jr_free(ctx->jrdev);
18378c2ecf20Sopenharmony_ci		return -ENOMEM;
18388c2ecf20Sopenharmony_ci	}
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	ctx->sh_desc_update_dma = dma_addr;
18418c2ecf20Sopenharmony_ci	ctx->sh_desc_update_first_dma = dma_addr +
18428c2ecf20Sopenharmony_ci					offsetof(struct caam_hash_ctx,
18438c2ecf20Sopenharmony_ci						 sh_desc_update_first) -
18448c2ecf20Sopenharmony_ci					sh_desc_update_offset;
18458c2ecf20Sopenharmony_ci	ctx->sh_desc_fin_dma = dma_addr + offsetof(struct caam_hash_ctx,
18468c2ecf20Sopenharmony_ci						   sh_desc_fin) -
18478c2ecf20Sopenharmony_ci					sh_desc_update_offset;
18488c2ecf20Sopenharmony_ci	ctx->sh_desc_digest_dma = dma_addr + offsetof(struct caam_hash_ctx,
18498c2ecf20Sopenharmony_ci						      sh_desc_digest) -
18508c2ecf20Sopenharmony_ci					sh_desc_update_offset;
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci	ctx->enginectx.op.do_one_request = ahash_do_one_req;
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
18558c2ecf20Sopenharmony_ci				 sizeof(struct caam_hash_state));
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	/*
18588c2ecf20Sopenharmony_ci	 * For keyed hash algorithms shared descriptors
18598c2ecf20Sopenharmony_ci	 * will be created later in setkey() callback
18608c2ecf20Sopenharmony_ci	 */
18618c2ecf20Sopenharmony_ci	return alg->setkey ? 0 : ahash_set_sh_desc(ahash);
18628c2ecf20Sopenharmony_ci}
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_cistatic void caam_hash_cra_exit(struct crypto_tfm *tfm)
18658c2ecf20Sopenharmony_ci{
18668c2ecf20Sopenharmony_ci	struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma,
18698c2ecf20Sopenharmony_ci			       offsetof(struct caam_hash_ctx, key) -
18708c2ecf20Sopenharmony_ci			       offsetof(struct caam_hash_ctx, sh_desc_update),
18718c2ecf20Sopenharmony_ci			       ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
18728c2ecf20Sopenharmony_ci	if (ctx->key_dir != DMA_NONE)
18738c2ecf20Sopenharmony_ci		dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
18748c2ecf20Sopenharmony_ci				       ARRAY_SIZE(ctx->key), ctx->key_dir,
18758c2ecf20Sopenharmony_ci				       DMA_ATTR_SKIP_CPU_SYNC);
18768c2ecf20Sopenharmony_ci	caam_jr_free(ctx->jrdev);
18778c2ecf20Sopenharmony_ci}
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_civoid caam_algapi_hash_exit(void)
18808c2ecf20Sopenharmony_ci{
18818c2ecf20Sopenharmony_ci	struct caam_hash_alg *t_alg, *n;
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	if (!hash_list.next)
18848c2ecf20Sopenharmony_ci		return;
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
18878c2ecf20Sopenharmony_ci		crypto_unregister_ahash(&t_alg->ahash_alg);
18888c2ecf20Sopenharmony_ci		list_del(&t_alg->entry);
18898c2ecf20Sopenharmony_ci		kfree(t_alg);
18908c2ecf20Sopenharmony_ci	}
18918c2ecf20Sopenharmony_ci}
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_cistatic struct caam_hash_alg *
18948c2ecf20Sopenharmony_cicaam_hash_alloc(struct caam_hash_template *template,
18958c2ecf20Sopenharmony_ci		bool keyed)
18968c2ecf20Sopenharmony_ci{
18978c2ecf20Sopenharmony_ci	struct caam_hash_alg *t_alg;
18988c2ecf20Sopenharmony_ci	struct ahash_alg *halg;
18998c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
19028c2ecf20Sopenharmony_ci	if (!t_alg) {
19038c2ecf20Sopenharmony_ci		pr_err("failed to allocate t_alg\n");
19048c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
19058c2ecf20Sopenharmony_ci	}
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	t_alg->ahash_alg = template->template_ahash;
19088c2ecf20Sopenharmony_ci	halg = &t_alg->ahash_alg;
19098c2ecf20Sopenharmony_ci	alg = &halg->halg.base;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	if (keyed) {
19128c2ecf20Sopenharmony_ci		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
19138c2ecf20Sopenharmony_ci			 template->hmac_name);
19148c2ecf20Sopenharmony_ci		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
19158c2ecf20Sopenharmony_ci			 template->hmac_driver_name);
19168c2ecf20Sopenharmony_ci	} else {
19178c2ecf20Sopenharmony_ci		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
19188c2ecf20Sopenharmony_ci			 template->name);
19198c2ecf20Sopenharmony_ci		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
19208c2ecf20Sopenharmony_ci			 template->driver_name);
19218c2ecf20Sopenharmony_ci		t_alg->ahash_alg.setkey = NULL;
19228c2ecf20Sopenharmony_ci	}
19238c2ecf20Sopenharmony_ci	alg->cra_module = THIS_MODULE;
19248c2ecf20Sopenharmony_ci	alg->cra_init = caam_hash_cra_init;
19258c2ecf20Sopenharmony_ci	alg->cra_exit = caam_hash_cra_exit;
19268c2ecf20Sopenharmony_ci	alg->cra_ctxsize = sizeof(struct caam_hash_ctx);
19278c2ecf20Sopenharmony_ci	alg->cra_priority = CAAM_CRA_PRIORITY;
19288c2ecf20Sopenharmony_ci	alg->cra_blocksize = template->blocksize;
19298c2ecf20Sopenharmony_ci	alg->cra_alignmask = 0;
19308c2ecf20Sopenharmony_ci	alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_ci	t_alg->alg_type = template->alg_type;
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci	return t_alg;
19358c2ecf20Sopenharmony_ci}
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ciint caam_algapi_hash_init(struct device *ctrldev)
19388c2ecf20Sopenharmony_ci{
19398c2ecf20Sopenharmony_ci	int i = 0, err = 0;
19408c2ecf20Sopenharmony_ci	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
19418c2ecf20Sopenharmony_ci	unsigned int md_limit = SHA512_DIGEST_SIZE;
19428c2ecf20Sopenharmony_ci	u32 md_inst, md_vid;
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	/*
19458c2ecf20Sopenharmony_ci	 * Register crypto algorithms the device supports.  First, identify
19468c2ecf20Sopenharmony_ci	 * presence and attributes of MD block.
19478c2ecf20Sopenharmony_ci	 */
19488c2ecf20Sopenharmony_ci	if (priv->era < 10) {
19498c2ecf20Sopenharmony_ci		md_vid = (rd_reg32(&priv->ctrl->perfmon.cha_id_ls) &
19508c2ecf20Sopenharmony_ci			  CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
19518c2ecf20Sopenharmony_ci		md_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) &
19528c2ecf20Sopenharmony_ci			   CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
19538c2ecf20Sopenharmony_ci	} else {
19548c2ecf20Sopenharmony_ci		u32 mdha = rd_reg32(&priv->ctrl->vreg.mdha);
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci		md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT;
19578c2ecf20Sopenharmony_ci		md_inst = mdha & CHA_VER_NUM_MASK;
19588c2ecf20Sopenharmony_ci	}
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci	/*
19618c2ecf20Sopenharmony_ci	 * Skip registration of any hashing algorithms if MD block
19628c2ecf20Sopenharmony_ci	 * is not present.
19638c2ecf20Sopenharmony_ci	 */
19648c2ecf20Sopenharmony_ci	if (!md_inst)
19658c2ecf20Sopenharmony_ci		return 0;
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	/* Limit digest size based on LP256 */
19688c2ecf20Sopenharmony_ci	if (md_vid == CHA_VER_VID_MD_LP256)
19698c2ecf20Sopenharmony_ci		md_limit = SHA256_DIGEST_SIZE;
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hash_list);
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci	/* register crypto algorithms the device supports */
19748c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
19758c2ecf20Sopenharmony_ci		struct caam_hash_alg *t_alg;
19768c2ecf20Sopenharmony_ci		struct caam_hash_template *alg = driver_hash + i;
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci		/* If MD size is not supported by device, skip registration */
19798c2ecf20Sopenharmony_ci		if (is_mdha(alg->alg_type) &&
19808c2ecf20Sopenharmony_ci		    alg->template_ahash.halg.digestsize > md_limit)
19818c2ecf20Sopenharmony_ci			continue;
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci		/* register hmac version */
19848c2ecf20Sopenharmony_ci		t_alg = caam_hash_alloc(alg, true);
19858c2ecf20Sopenharmony_ci		if (IS_ERR(t_alg)) {
19868c2ecf20Sopenharmony_ci			err = PTR_ERR(t_alg);
19878c2ecf20Sopenharmony_ci			pr_warn("%s alg allocation failed\n",
19888c2ecf20Sopenharmony_ci				alg->hmac_driver_name);
19898c2ecf20Sopenharmony_ci			continue;
19908c2ecf20Sopenharmony_ci		}
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci		err = crypto_register_ahash(&t_alg->ahash_alg);
19938c2ecf20Sopenharmony_ci		if (err) {
19948c2ecf20Sopenharmony_ci			pr_warn("%s alg registration failed: %d\n",
19958c2ecf20Sopenharmony_ci				t_alg->ahash_alg.halg.base.cra_driver_name,
19968c2ecf20Sopenharmony_ci				err);
19978c2ecf20Sopenharmony_ci			kfree(t_alg);
19988c2ecf20Sopenharmony_ci		} else
19998c2ecf20Sopenharmony_ci			list_add_tail(&t_alg->entry, &hash_list);
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci		if ((alg->alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES)
20028c2ecf20Sopenharmony_ci			continue;
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci		/* register unkeyed version */
20058c2ecf20Sopenharmony_ci		t_alg = caam_hash_alloc(alg, false);
20068c2ecf20Sopenharmony_ci		if (IS_ERR(t_alg)) {
20078c2ecf20Sopenharmony_ci			err = PTR_ERR(t_alg);
20088c2ecf20Sopenharmony_ci			pr_warn("%s alg allocation failed\n", alg->driver_name);
20098c2ecf20Sopenharmony_ci			continue;
20108c2ecf20Sopenharmony_ci		}
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci		err = crypto_register_ahash(&t_alg->ahash_alg);
20138c2ecf20Sopenharmony_ci		if (err) {
20148c2ecf20Sopenharmony_ci			pr_warn("%s alg registration failed: %d\n",
20158c2ecf20Sopenharmony_ci				t_alg->ahash_alg.halg.base.cra_driver_name,
20168c2ecf20Sopenharmony_ci				err);
20178c2ecf20Sopenharmony_ci			kfree(t_alg);
20188c2ecf20Sopenharmony_ci		} else
20198c2ecf20Sopenharmony_ci			list_add_tail(&t_alg->entry, &hash_list);
20208c2ecf20Sopenharmony_ci	}
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	return err;
20238c2ecf20Sopenharmony_ci}
2024