xref: /linux/drivers/crypto/caam/caamhash.c (revision 674f368a952c48ede71784935a799a5205b92b6c)
1618b5dc4SHoria Geantă // SPDX-License-Identifier: GPL-2.0+
2045e3678SYuan Kang /*
3045e3678SYuan Kang  * caam - Freescale FSL CAAM support for ahash functions of crypto API
4045e3678SYuan Kang  *
5045e3678SYuan Kang  * Copyright 2011 Freescale Semiconductor, Inc.
687870cfbSIuliana Prodan  * Copyright 2018-2019 NXP
7045e3678SYuan Kang  *
8045e3678SYuan Kang  * Based on caamalg.c crypto API driver.
9045e3678SYuan Kang  *
10045e3678SYuan Kang  * relationship of digest job descriptor or first job descriptor after init to
11045e3678SYuan Kang  * shared descriptors:
12045e3678SYuan Kang  *
13045e3678SYuan Kang  * ---------------                     ---------------
14045e3678SYuan Kang  * | JobDesc #1  |-------------------->|  ShareDesc  |
15045e3678SYuan Kang  * | *(packet 1) |                     |  (hashKey)  |
16045e3678SYuan Kang  * ---------------                     | (operation) |
17045e3678SYuan Kang  *                                     ---------------
18045e3678SYuan Kang  *
19045e3678SYuan Kang  * relationship of subsequent job descriptors to shared descriptors:
20045e3678SYuan Kang  *
21045e3678SYuan Kang  * ---------------                     ---------------
22045e3678SYuan Kang  * | JobDesc #2  |-------------------->|  ShareDesc  |
23045e3678SYuan Kang  * | *(packet 2) |      |------------->|  (hashKey)  |
24045e3678SYuan Kang  * ---------------      |    |-------->| (operation) |
25045e3678SYuan Kang  *       .              |    |         | (load ctx2) |
26045e3678SYuan Kang  *       .              |    |         ---------------
27045e3678SYuan Kang  * ---------------      |    |
28045e3678SYuan Kang  * | JobDesc #3  |------|    |
29045e3678SYuan Kang  * | *(packet 3) |           |
30045e3678SYuan Kang  * ---------------           |
31045e3678SYuan Kang  *       .                   |
32045e3678SYuan Kang  *       .                   |
33045e3678SYuan Kang  * ---------------           |
34045e3678SYuan Kang  * | JobDesc #4  |------------
35045e3678SYuan Kang  * | *(packet 4) |
36045e3678SYuan Kang  * ---------------
37045e3678SYuan Kang  *
38045e3678SYuan Kang  * The SharedDesc never changes for a connection unless rekeyed, but
39045e3678SYuan Kang  * each packet will likely be in a different place. So all we need
40045e3678SYuan Kang  * to know to process the packet is where the input is, where the
41045e3678SYuan Kang  * output goes, and what context we want to process with. Context is
42045e3678SYuan Kang  * in the SharedDesc, packet references in the JobDesc.
43045e3678SYuan Kang  *
44045e3678SYuan Kang  * So, a job desc looks like:
45045e3678SYuan Kang  *
46045e3678SYuan Kang  * ---------------------
47045e3678SYuan Kang  * | Header            |
48045e3678SYuan Kang  * | ShareDesc Pointer |
49045e3678SYuan Kang  * | SEQ_OUT_PTR       |
50045e3678SYuan Kang  * | (output buffer)   |
51045e3678SYuan Kang  * | (output length)   |
52045e3678SYuan Kang  * | SEQ_IN_PTR        |
53045e3678SYuan Kang  * | (input buffer)    |
54045e3678SYuan Kang  * | (input length)    |
55045e3678SYuan Kang  * ---------------------
56045e3678SYuan Kang  */
57045e3678SYuan Kang 
58045e3678SYuan Kang #include "compat.h"
59045e3678SYuan Kang 
60045e3678SYuan Kang #include "regs.h"
61045e3678SYuan Kang #include "intern.h"
62045e3678SYuan Kang #include "desc_constr.h"
63045e3678SYuan Kang #include "jr.h"
64045e3678SYuan Kang #include "error.h"
65045e3678SYuan Kang #include "sg_sw_sec4.h"
66045e3678SYuan Kang #include "key_gen.h"
670efa7579SHoria Geantă #include "caamhash_desc.h"
68045e3678SYuan Kang 
69045e3678SYuan Kang #define CAAM_CRA_PRIORITY		3000
70045e3678SYuan Kang 
71045e3678SYuan Kang /* max hash key is max split key size */
72045e3678SYuan Kang #define CAAM_MAX_HASH_KEY_SIZE		(SHA512_DIGEST_SIZE * 2)
73045e3678SYuan Kang 
74045e3678SYuan Kang #define CAAM_MAX_HASH_BLOCK_SIZE	SHA512_BLOCK_SIZE
75045e3678SYuan Kang #define CAAM_MAX_HASH_DIGEST_SIZE	SHA512_DIGEST_SIZE
76045e3678SYuan Kang 
77045e3678SYuan Kang #define DESC_HASH_MAX_USED_BYTES	(DESC_AHASH_FINAL_LEN + \
78045e3678SYuan Kang 					 CAAM_MAX_HASH_KEY_SIZE)
79045e3678SYuan Kang #define DESC_HASH_MAX_USED_LEN		(DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ)
80045e3678SYuan Kang 
81045e3678SYuan Kang /* caam context sizes for hashes: running digest + 8 */
82045e3678SYuan Kang #define HASH_MSG_LEN			8
83045e3678SYuan Kang #define MAX_CTX_LEN			(HASH_MSG_LEN + SHA512_DIGEST_SIZE)
84045e3678SYuan Kang 
85cfc6f11bSRuchika Gupta static struct list_head hash_list;
86cfc6f11bSRuchika Gupta 
87045e3678SYuan Kang /* ahash per-session context */
88045e3678SYuan Kang struct caam_hash_ctx {
89e11793f5SRussell King 	u32 sh_desc_update[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
90e11793f5SRussell King 	u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
91e11793f5SRussell King 	u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
92e11793f5SRussell King 	u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
9312b8567fSIuliana Prodan 	u8 key[CAAM_MAX_HASH_KEY_SIZE] ____cacheline_aligned;
94e11793f5SRussell King 	dma_addr_t sh_desc_update_dma ____cacheline_aligned;
95045e3678SYuan Kang 	dma_addr_t sh_desc_update_first_dma;
96045e3678SYuan Kang 	dma_addr_t sh_desc_fin_dma;
97045e3678SYuan Kang 	dma_addr_t sh_desc_digest_dma;
987e0880b9SHoria Geantă 	enum dma_data_direction dir;
99e9b4913aSHoria Geantă 	enum dma_data_direction key_dir;
100e11793f5SRussell King 	struct device *jrdev;
101045e3678SYuan Kang 	int ctx_len;
102db57656bSHoria Geantă 	struct alginfo adata;
103045e3678SYuan Kang };
104045e3678SYuan Kang 
105045e3678SYuan Kang /* ahash state */
106045e3678SYuan Kang struct caam_hash_state {
107045e3678SYuan Kang 	dma_addr_t buf_dma;
108045e3678SYuan Kang 	dma_addr_t ctx_dma;
10965055e21SFranck LENORMAND 	int ctx_dma_len;
11046b49abcSAndrei Botila 	u8 buf[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
11146b49abcSAndrei Botila 	int buflen;
11246b49abcSAndrei Botila 	int next_buflen;
113e7472422SVictoria Milhoan 	u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned;
114045e3678SYuan Kang 	int (*update)(struct ahash_request *req);
115045e3678SYuan Kang 	int (*final)(struct ahash_request *req);
116045e3678SYuan Kang 	int (*finup)(struct ahash_request *req);
117045e3678SYuan Kang };
118045e3678SYuan Kang 
1195ec90831SRussell King struct caam_export_state {
1205ec90831SRussell King 	u8 buf[CAAM_MAX_HASH_BLOCK_SIZE];
1215ec90831SRussell King 	u8 caam_ctx[MAX_CTX_LEN];
1225ec90831SRussell King 	int buflen;
1235ec90831SRussell King 	int (*update)(struct ahash_request *req);
1245ec90831SRussell King 	int (*final)(struct ahash_request *req);
1255ec90831SRussell King 	int (*finup)(struct ahash_request *req);
1265ec90831SRussell King };
1275ec90831SRussell King 
12887870cfbSIuliana Prodan static inline bool is_cmac_aes(u32 algtype)
12912b8567fSIuliana Prodan {
13012b8567fSIuliana Prodan 	return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) ==
13187870cfbSIuliana Prodan 	       (OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC);
13212b8567fSIuliana Prodan }
133045e3678SYuan Kang /* Common job descriptor seq in/out ptr routines */
134045e3678SYuan Kang 
135045e3678SYuan Kang /* Map state->caam_ctx, and append seq_out_ptr command that points to it */
136ce572085SHoria Geanta static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
137045e3678SYuan Kang 				      struct caam_hash_state *state,
138045e3678SYuan Kang 				      int ctx_len)
139045e3678SYuan Kang {
14065055e21SFranck LENORMAND 	state->ctx_dma_len = ctx_len;
141045e3678SYuan Kang 	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
142045e3678SYuan Kang 					ctx_len, DMA_FROM_DEVICE);
143ce572085SHoria Geanta 	if (dma_mapping_error(jrdev, state->ctx_dma)) {
144ce572085SHoria Geanta 		dev_err(jrdev, "unable to map ctx\n");
14587ec02e7SHoria Geantă 		state->ctx_dma = 0;
146ce572085SHoria Geanta 		return -ENOMEM;
147ce572085SHoria Geanta 	}
148ce572085SHoria Geanta 
149045e3678SYuan Kang 	append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
150ce572085SHoria Geanta 
151ce572085SHoria Geanta 	return 0;
152045e3678SYuan Kang }
153045e3678SYuan Kang 
154944c3d4dSHoria Geantă /* Map current buffer in state (if length > 0) and put it in link table */
155944c3d4dSHoria Geantă static inline int buf_map_to_sec4_sg(struct device *jrdev,
156045e3678SYuan Kang 				     struct sec4_sg_entry *sec4_sg,
157944c3d4dSHoria Geantă 				     struct caam_hash_state *state)
158045e3678SYuan Kang {
15946b49abcSAndrei Botila 	int buflen = state->buflen;
160045e3678SYuan Kang 
161944c3d4dSHoria Geantă 	if (!buflen)
162944c3d4dSHoria Geantă 		return 0;
163045e3678SYuan Kang 
16446b49abcSAndrei Botila 	state->buf_dma = dma_map_single(jrdev, state->buf, buflen,
165944c3d4dSHoria Geantă 					DMA_TO_DEVICE);
166944c3d4dSHoria Geantă 	if (dma_mapping_error(jrdev, state->buf_dma)) {
167944c3d4dSHoria Geantă 		dev_err(jrdev, "unable to map buf\n");
168944c3d4dSHoria Geantă 		state->buf_dma = 0;
169944c3d4dSHoria Geantă 		return -ENOMEM;
170045e3678SYuan Kang 	}
171045e3678SYuan Kang 
172944c3d4dSHoria Geantă 	dma_to_sec4_sg_one(sec4_sg, state->buf_dma, buflen, 0);
173045e3678SYuan Kang 
174944c3d4dSHoria Geantă 	return 0;
175045e3678SYuan Kang }
176045e3678SYuan Kang 
177045e3678SYuan Kang /* Map state->caam_ctx, and add it to link table */
178dfcd8393SHoria Geantă static inline int ctx_map_to_sec4_sg(struct device *jrdev,
179ce572085SHoria Geanta 				     struct caam_hash_state *state, int ctx_len,
180ce572085SHoria Geanta 				     struct sec4_sg_entry *sec4_sg, u32 flag)
181045e3678SYuan Kang {
18265055e21SFranck LENORMAND 	state->ctx_dma_len = ctx_len;
183045e3678SYuan Kang 	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
184ce572085SHoria Geanta 	if (dma_mapping_error(jrdev, state->ctx_dma)) {
185ce572085SHoria Geanta 		dev_err(jrdev, "unable to map ctx\n");
18687ec02e7SHoria Geantă 		state->ctx_dma = 0;
187ce572085SHoria Geanta 		return -ENOMEM;
188ce572085SHoria Geanta 	}
189ce572085SHoria Geanta 
190045e3678SYuan Kang 	dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
191ce572085SHoria Geanta 
192ce572085SHoria Geanta 	return 0;
193045e3678SYuan Kang }
194045e3678SYuan Kang 
195045e3678SYuan Kang static int ahash_set_sh_desc(struct crypto_ahash *ahash)
196045e3678SYuan Kang {
197045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
198045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
199045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
2007e0880b9SHoria Geantă 	struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent);
201045e3678SYuan Kang 	u32 *desc;
202045e3678SYuan Kang 
2037e0880b9SHoria Geantă 	ctx->adata.key_virt = ctx->key;
2047e0880b9SHoria Geantă 
205045e3678SYuan Kang 	/* ahash_update shared descriptor */
206045e3678SYuan Kang 	desc = ctx->sh_desc_update;
2070efa7579SHoria Geantă 	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len,
2080efa7579SHoria Geantă 			  ctx->ctx_len, true, ctrlpriv->era);
209bbf22344SHoria Geantă 	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
2107e0880b9SHoria Geantă 				   desc_bytes(desc), ctx->dir);
2116e005503SSascha Hauer 
2126e005503SSascha Hauer 	print_hex_dump_debug("ahash update shdesc@"__stringify(__LINE__)": ",
2136e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
2146e005503SSascha Hauer 			     1);
215045e3678SYuan Kang 
216045e3678SYuan Kang 	/* ahash_update_first shared descriptor */
217045e3678SYuan Kang 	desc = ctx->sh_desc_update_first;
2180efa7579SHoria Geantă 	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
2190efa7579SHoria Geantă 			  ctx->ctx_len, false, ctrlpriv->era);
220bbf22344SHoria Geantă 	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
2217e0880b9SHoria Geantă 				   desc_bytes(desc), ctx->dir);
2226e005503SSascha Hauer 	print_hex_dump_debug("ahash update first shdesc@"__stringify(__LINE__)
2236e005503SSascha Hauer 			     ": ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
2246e005503SSascha Hauer 			     desc_bytes(desc), 1);
225045e3678SYuan Kang 
226045e3678SYuan Kang 	/* ahash_final shared descriptor */
227045e3678SYuan Kang 	desc = ctx->sh_desc_fin;
2280efa7579SHoria Geantă 	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize,
2290efa7579SHoria Geantă 			  ctx->ctx_len, true, ctrlpriv->era);
230bbf22344SHoria Geantă 	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
2317e0880b9SHoria Geantă 				   desc_bytes(desc), ctx->dir);
2326e005503SSascha Hauer 
2336e005503SSascha Hauer 	print_hex_dump_debug("ahash final shdesc@"__stringify(__LINE__)": ",
234045e3678SYuan Kang 			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
235045e3678SYuan Kang 			     desc_bytes(desc), 1);
236045e3678SYuan Kang 
237045e3678SYuan Kang 	/* ahash_digest shared descriptor */
238045e3678SYuan Kang 	desc = ctx->sh_desc_digest;
2390efa7579SHoria Geantă 	cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize,
2400efa7579SHoria Geantă 			  ctx->ctx_len, false, ctrlpriv->era);
241bbf22344SHoria Geantă 	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
2427e0880b9SHoria Geantă 				   desc_bytes(desc), ctx->dir);
2436e005503SSascha Hauer 
2446e005503SSascha Hauer 	print_hex_dump_debug("ahash digest shdesc@"__stringify(__LINE__)": ",
245045e3678SYuan Kang 			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
246045e3678SYuan Kang 			     desc_bytes(desc), 1);
247045e3678SYuan Kang 
248045e3678SYuan Kang 	return 0;
249045e3678SYuan Kang }
250045e3678SYuan Kang 
25112b8567fSIuliana Prodan static int axcbc_set_sh_desc(struct crypto_ahash *ahash)
25212b8567fSIuliana Prodan {
25312b8567fSIuliana Prodan 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
25412b8567fSIuliana Prodan 	int digestsize = crypto_ahash_digestsize(ahash);
25512b8567fSIuliana Prodan 	struct device *jrdev = ctx->jrdev;
25612b8567fSIuliana Prodan 	u32 *desc;
25712b8567fSIuliana Prodan 
25812b8567fSIuliana Prodan 	/* shared descriptor for ahash_update */
25912b8567fSIuliana Prodan 	desc = ctx->sh_desc_update;
26087870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
261a2fb864cSHoria Geantă 			    ctx->ctx_len, ctx->ctx_len);
26212b8567fSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
26312b8567fSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
26412b8567fSIuliana Prodan 	print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ",
26512b8567fSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
26612b8567fSIuliana Prodan 			     1);
26712b8567fSIuliana Prodan 
26812b8567fSIuliana Prodan 	/* shared descriptor for ahash_{final,finup} */
26912b8567fSIuliana Prodan 	desc = ctx->sh_desc_fin;
27087870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
271a2fb864cSHoria Geantă 			    digestsize, ctx->ctx_len);
27212b8567fSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
27312b8567fSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
27412b8567fSIuliana Prodan 	print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ",
27512b8567fSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
27612b8567fSIuliana Prodan 			     1);
27712b8567fSIuliana Prodan 
27812b8567fSIuliana Prodan 	/* key is immediate data for INIT and INITFINAL states */
27912b8567fSIuliana Prodan 	ctx->adata.key_virt = ctx->key;
28012b8567fSIuliana Prodan 
28112b8567fSIuliana Prodan 	/* shared descriptor for first invocation of ahash_update */
28212b8567fSIuliana Prodan 	desc = ctx->sh_desc_update_first;
28387870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
284a2fb864cSHoria Geantă 			    ctx->ctx_len);
28512b8567fSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
28612b8567fSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
2876e005503SSascha Hauer 	print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__)
2886e005503SSascha Hauer 			     " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
2896e005503SSascha Hauer 			     desc_bytes(desc), 1);
29012b8567fSIuliana Prodan 
29112b8567fSIuliana Prodan 	/* shared descriptor for ahash_digest */
29212b8567fSIuliana Prodan 	desc = ctx->sh_desc_digest;
29387870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
294a2fb864cSHoria Geantă 			    digestsize, ctx->ctx_len);
29512b8567fSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
29612b8567fSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
29712b8567fSIuliana Prodan 	print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ",
29812b8567fSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
29912b8567fSIuliana Prodan 			     1);
30087870cfbSIuliana Prodan 	return 0;
30187870cfbSIuliana Prodan }
30287870cfbSIuliana Prodan 
30387870cfbSIuliana Prodan static int acmac_set_sh_desc(struct crypto_ahash *ahash)
30487870cfbSIuliana Prodan {
30587870cfbSIuliana Prodan 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
30687870cfbSIuliana Prodan 	int digestsize = crypto_ahash_digestsize(ahash);
30787870cfbSIuliana Prodan 	struct device *jrdev = ctx->jrdev;
30887870cfbSIuliana Prodan 	u32 *desc;
30987870cfbSIuliana Prodan 
31087870cfbSIuliana Prodan 	/* shared descriptor for ahash_update */
31187870cfbSIuliana Prodan 	desc = ctx->sh_desc_update;
31287870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
313a2fb864cSHoria Geantă 			    ctx->ctx_len, ctx->ctx_len);
31487870cfbSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
31587870cfbSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
31687870cfbSIuliana Prodan 	print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ",
31787870cfbSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
31887870cfbSIuliana Prodan 			     desc_bytes(desc), 1);
31987870cfbSIuliana Prodan 
32087870cfbSIuliana Prodan 	/* shared descriptor for ahash_{final,finup} */
32187870cfbSIuliana Prodan 	desc = ctx->sh_desc_fin;
32287870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
323a2fb864cSHoria Geantă 			    digestsize, ctx->ctx_len);
32487870cfbSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
32587870cfbSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
32687870cfbSIuliana Prodan 	print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ",
32787870cfbSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
32887870cfbSIuliana Prodan 			     desc_bytes(desc), 1);
32987870cfbSIuliana Prodan 
33087870cfbSIuliana Prodan 	/* shared descriptor for first invocation of ahash_update */
33187870cfbSIuliana Prodan 	desc = ctx->sh_desc_update_first;
33287870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
333a2fb864cSHoria Geantă 			    ctx->ctx_len);
33487870cfbSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
33587870cfbSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
3366e005503SSascha Hauer 	print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__)
3376e005503SSascha Hauer 			     " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
33887870cfbSIuliana Prodan 			     desc_bytes(desc), 1);
33987870cfbSIuliana Prodan 
34087870cfbSIuliana Prodan 	/* shared descriptor for ahash_digest */
34187870cfbSIuliana Prodan 	desc = ctx->sh_desc_digest;
34287870cfbSIuliana Prodan 	cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
343a2fb864cSHoria Geantă 			    digestsize, ctx->ctx_len);
34487870cfbSIuliana Prodan 	dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
34587870cfbSIuliana Prodan 				   desc_bytes(desc), ctx->dir);
34687870cfbSIuliana Prodan 	print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ",
34787870cfbSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, desc,
34887870cfbSIuliana Prodan 			     desc_bytes(desc), 1);
34912b8567fSIuliana Prodan 
35012b8567fSIuliana Prodan 	return 0;
35112b8567fSIuliana Prodan }
35212b8567fSIuliana Prodan 
353045e3678SYuan Kang /* Digest hash size if it is too large */
35430724445SHoria Geantă static int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key,
35530724445SHoria Geantă 			   u32 digestsize)
356045e3678SYuan Kang {
357045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
358045e3678SYuan Kang 	u32 *desc;
359045e3678SYuan Kang 	struct split_key_result result;
36030724445SHoria Geantă 	dma_addr_t key_dma;
3619e6df0fdSMarkus Elfring 	int ret;
362045e3678SYuan Kang 
3639c23b7d3SVakul Garg 	desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
3642af8f4a2SKim Phillips 	if (!desc) {
3652af8f4a2SKim Phillips 		dev_err(jrdev, "unable to allocate key input memory\n");
3662af8f4a2SKim Phillips 		return -ENOMEM;
3672af8f4a2SKim Phillips 	}
368045e3678SYuan Kang 
369045e3678SYuan Kang 	init_job_desc(desc, 0);
370045e3678SYuan Kang 
37130724445SHoria Geantă 	key_dma = dma_map_single(jrdev, key, *keylen, DMA_BIDIRECTIONAL);
37230724445SHoria Geantă 	if (dma_mapping_error(jrdev, key_dma)) {
37330724445SHoria Geantă 		dev_err(jrdev, "unable to map key memory\n");
374045e3678SYuan Kang 		kfree(desc);
375045e3678SYuan Kang 		return -ENOMEM;
376045e3678SYuan Kang 	}
377045e3678SYuan Kang 
378045e3678SYuan Kang 	/* Job descriptor to perform unkeyed hash on key_in */
379db57656bSHoria Geantă 	append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT |
380045e3678SYuan Kang 			 OP_ALG_AS_INITFINAL);
38130724445SHoria Geantă 	append_seq_in_ptr(desc, key_dma, *keylen, 0);
382045e3678SYuan Kang 	append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
383045e3678SYuan Kang 			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
38430724445SHoria Geantă 	append_seq_out_ptr(desc, key_dma, digestsize, 0);
385045e3678SYuan Kang 	append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
386045e3678SYuan Kang 			 LDST_SRCDST_BYTE_CONTEXT);
387045e3678SYuan Kang 
3886e005503SSascha Hauer 	print_hex_dump_debug("key_in@"__stringify(__LINE__)": ",
38930724445SHoria Geantă 			     DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
3906e005503SSascha Hauer 	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
3916e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
3926e005503SSascha Hauer 			     1);
393045e3678SYuan Kang 
394045e3678SYuan Kang 	result.err = 0;
395045e3678SYuan Kang 	init_completion(&result.completion);
396045e3678SYuan Kang 
397045e3678SYuan Kang 	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
398045e3678SYuan Kang 	if (!ret) {
399045e3678SYuan Kang 		/* in progress */
4007459e1d2SHoria Geantă 		wait_for_completion(&result.completion);
401045e3678SYuan Kang 		ret = result.err;
4026e005503SSascha Hauer 
4036e005503SSascha Hauer 		print_hex_dump_debug("digested key@"__stringify(__LINE__)": ",
4046e005503SSascha Hauer 				     DUMP_PREFIX_ADDRESS, 16, 4, key,
4056e005503SSascha Hauer 				     digestsize, 1);
406045e3678SYuan Kang 	}
40730724445SHoria Geantă 	dma_unmap_single(jrdev, key_dma, *keylen, DMA_BIDIRECTIONAL);
408045e3678SYuan Kang 
409e11aa9f1SHoria Geanta 	*keylen = digestsize;
410e11aa9f1SHoria Geanta 
411045e3678SYuan Kang 	kfree(desc);
412045e3678SYuan Kang 
413045e3678SYuan Kang 	return ret;
414045e3678SYuan Kang }
415045e3678SYuan Kang 
416045e3678SYuan Kang static int ahash_setkey(struct crypto_ahash *ahash,
417045e3678SYuan Kang 			const u8 *key, unsigned int keylen)
418045e3678SYuan Kang {
419045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
4206e005503SSascha Hauer 	struct device *jrdev = ctx->jrdev;
421045e3678SYuan Kang 	int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
422045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
4237e0880b9SHoria Geantă 	struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent);
4249e6df0fdSMarkus Elfring 	int ret;
425045e3678SYuan Kang 	u8 *hashed_key = NULL;
426045e3678SYuan Kang 
4276e005503SSascha Hauer 	dev_dbg(jrdev, "keylen %d\n", keylen);
428045e3678SYuan Kang 
429045e3678SYuan Kang 	if (keylen > blocksize) {
43030724445SHoria Geantă 		hashed_key = kmemdup(key, keylen, GFP_KERNEL | GFP_DMA);
431045e3678SYuan Kang 		if (!hashed_key)
432045e3678SYuan Kang 			return -ENOMEM;
43330724445SHoria Geantă 		ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
434045e3678SYuan Kang 		if (ret)
435d6e7a7d0SMarkus Elfring 			goto bad_free_key;
436045e3678SYuan Kang 		key = hashed_key;
437045e3678SYuan Kang 	}
438045e3678SYuan Kang 
4397e0880b9SHoria Geantă 	/*
4407e0880b9SHoria Geantă 	 * If DKP is supported, use it in the shared descriptor to generate
4417e0880b9SHoria Geantă 	 * the split key.
4427e0880b9SHoria Geantă 	 */
4437e0880b9SHoria Geantă 	if (ctrlpriv->era >= 6) {
4447e0880b9SHoria Geantă 		ctx->adata.key_inline = true;
4457e0880b9SHoria Geantă 		ctx->adata.keylen = keylen;
4467e0880b9SHoria Geantă 		ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype &
4477e0880b9SHoria Geantă 						      OP_ALG_ALGSEL_MASK);
4487e0880b9SHoria Geantă 
4497e0880b9SHoria Geantă 		if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE)
450d6e7a7d0SMarkus Elfring 			goto bad_free_key;
451045e3678SYuan Kang 
4527e0880b9SHoria Geantă 		memcpy(ctx->key, key, keylen);
453e9b4913aSHoria Geantă 
454e9b4913aSHoria Geantă 		/*
455e9b4913aSHoria Geantă 		 * In case |user key| > |derived key|, using DKP<imm,imm>
456e9b4913aSHoria Geantă 		 * would result in invalid opcodes (last bytes of user key) in
457e9b4913aSHoria Geantă 		 * the resulting descriptor. Use DKP<ptr,imm> instead => both
458e9b4913aSHoria Geantă 		 * virtual and dma key addresses are needed.
459e9b4913aSHoria Geantă 		 */
460e9b4913aSHoria Geantă 		if (keylen > ctx->adata.keylen_pad)
461e9b4913aSHoria Geantă 			dma_sync_single_for_device(ctx->jrdev,
462e9b4913aSHoria Geantă 						   ctx->adata.key_dma,
463e9b4913aSHoria Geantă 						   ctx->adata.keylen_pad,
464e9b4913aSHoria Geantă 						   DMA_TO_DEVICE);
4657e0880b9SHoria Geantă 	} else {
4667e0880b9SHoria Geantă 		ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key,
4677e0880b9SHoria Geantă 				    keylen, CAAM_MAX_HASH_KEY_SIZE);
4687e0880b9SHoria Geantă 		if (ret)
4697e0880b9SHoria Geantă 			goto bad_free_key;
4707e0880b9SHoria Geantă 	}
471045e3678SYuan Kang 
472045e3678SYuan Kang 	kfree(hashed_key);
473cfb725f6SHoria Geantă 	return ahash_set_sh_desc(ahash);
474d6e7a7d0SMarkus Elfring  bad_free_key:
475045e3678SYuan Kang 	kfree(hashed_key);
476045e3678SYuan Kang 	return -EINVAL;
477045e3678SYuan Kang }
478045e3678SYuan Kang 
47912b8567fSIuliana Prodan static int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key,
48012b8567fSIuliana Prodan 			unsigned int keylen)
48112b8567fSIuliana Prodan {
48212b8567fSIuliana Prodan 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
48312b8567fSIuliana Prodan 	struct device *jrdev = ctx->jrdev;
48412b8567fSIuliana Prodan 
485*674f368aSEric Biggers 	if (keylen != AES_KEYSIZE_128)
486836d8f43SIuliana Prodan 		return -EINVAL;
487836d8f43SIuliana Prodan 
48812b8567fSIuliana Prodan 	memcpy(ctx->key, key, keylen);
489a2fb864cSHoria Geantă 	dma_sync_single_for_device(jrdev, ctx->adata.key_dma, keylen,
490a2fb864cSHoria Geantă 				   DMA_TO_DEVICE);
49112b8567fSIuliana Prodan 	ctx->adata.keylen = keylen;
49212b8567fSIuliana Prodan 
49312b8567fSIuliana Prodan 	print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ",
49412b8567fSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1);
49512b8567fSIuliana Prodan 
49612b8567fSIuliana Prodan 	return axcbc_set_sh_desc(ahash);
49712b8567fSIuliana Prodan }
49887870cfbSIuliana Prodan 
49987870cfbSIuliana Prodan static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
50087870cfbSIuliana Prodan 			unsigned int keylen)
50187870cfbSIuliana Prodan {
50287870cfbSIuliana Prodan 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
503836d8f43SIuliana Prodan 	int err;
504836d8f43SIuliana Prodan 
505836d8f43SIuliana Prodan 	err = aes_check_keylen(keylen);
506*674f368aSEric Biggers 	if (err)
507836d8f43SIuliana Prodan 		return err;
50887870cfbSIuliana Prodan 
50987870cfbSIuliana Prodan 	/* key is immediate data for all cmac shared descriptors */
51087870cfbSIuliana Prodan 	ctx->adata.key_virt = key;
51187870cfbSIuliana Prodan 	ctx->adata.keylen = keylen;
51287870cfbSIuliana Prodan 
51387870cfbSIuliana Prodan 	print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ",
51487870cfbSIuliana Prodan 			     DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
51587870cfbSIuliana Prodan 
51687870cfbSIuliana Prodan 	return acmac_set_sh_desc(ahash);
51787870cfbSIuliana Prodan }
51887870cfbSIuliana Prodan 
519045e3678SYuan Kang /*
520045e3678SYuan Kang  * ahash_edesc - s/w-extended ahash descriptor
521045e3678SYuan Kang  * @sec4_sg_dma: physical mapped address of h/w link table
522045e3678SYuan Kang  * @src_nents: number of segments in input scatterlist
523045e3678SYuan Kang  * @sec4_sg_bytes: length of dma mapped sec4_sg space
524045e3678SYuan Kang  * @hw_desc: the h/w job descriptor followed by any referenced link tables
525343e44b1SRussell King  * @sec4_sg: h/w link table
526045e3678SYuan Kang  */
527045e3678SYuan Kang struct ahash_edesc {
528045e3678SYuan Kang 	dma_addr_t sec4_sg_dma;
529045e3678SYuan Kang 	int src_nents;
530045e3678SYuan Kang 	int sec4_sg_bytes;
5311a3daadcSAndrey Smirnov 	u32 hw_desc[DESC_JOB_IO_LEN_MAX / sizeof(u32)] ____cacheline_aligned;
532343e44b1SRussell King 	struct sec4_sg_entry sec4_sg[0];
533045e3678SYuan Kang };
534045e3678SYuan Kang 
535045e3678SYuan Kang static inline void ahash_unmap(struct device *dev,
536045e3678SYuan Kang 			struct ahash_edesc *edesc,
537045e3678SYuan Kang 			struct ahash_request *req, int dst_len)
538045e3678SYuan Kang {
539944c3d4dSHoria Geantă 	struct caam_hash_state *state = ahash_request_ctx(req);
540944c3d4dSHoria Geantă 
541045e3678SYuan Kang 	if (edesc->src_nents)
54213fb8fd7SLABBE Corentin 		dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
543045e3678SYuan Kang 
544045e3678SYuan Kang 	if (edesc->sec4_sg_bytes)
545045e3678SYuan Kang 		dma_unmap_single(dev, edesc->sec4_sg_dma,
546045e3678SYuan Kang 				 edesc->sec4_sg_bytes, DMA_TO_DEVICE);
547944c3d4dSHoria Geantă 
548944c3d4dSHoria Geantă 	if (state->buf_dma) {
54946b49abcSAndrei Botila 		dma_unmap_single(dev, state->buf_dma, state->buflen,
550944c3d4dSHoria Geantă 				 DMA_TO_DEVICE);
551944c3d4dSHoria Geantă 		state->buf_dma = 0;
552944c3d4dSHoria Geantă 	}
553045e3678SYuan Kang }
554045e3678SYuan Kang 
555045e3678SYuan Kang static inline void ahash_unmap_ctx(struct device *dev,
556045e3678SYuan Kang 			struct ahash_edesc *edesc,
557045e3678SYuan Kang 			struct ahash_request *req, int dst_len, u32 flag)
558045e3678SYuan Kang {
559045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
560045e3678SYuan Kang 
56187ec02e7SHoria Geantă 	if (state->ctx_dma) {
56265055e21SFranck LENORMAND 		dma_unmap_single(dev, state->ctx_dma, state->ctx_dma_len, flag);
56387ec02e7SHoria Geantă 		state->ctx_dma = 0;
56487ec02e7SHoria Geantă 	}
565045e3678SYuan Kang 	ahash_unmap(dev, edesc, req, dst_len);
566045e3678SYuan Kang }
567045e3678SYuan Kang 
568045e3678SYuan Kang static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
569045e3678SYuan Kang 		       void *context)
570045e3678SYuan Kang {
571045e3678SYuan Kang 	struct ahash_request *req = context;
572045e3678SYuan Kang 	struct ahash_edesc *edesc;
573045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
574045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
575c19650d6SHoria Geantă 	struct caam_hash_state *state = ahash_request_ctx(req);
576045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
5771984aaeeSHoria Geantă 	int ecode = 0;
578045e3678SYuan Kang 
5796e005503SSascha Hauer 	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
580045e3678SYuan Kang 
5814ca7c7d8SHoria Geantă 	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
582fa9659cdSMarek Vasut 	if (err)
5831984aaeeSHoria Geantă 		ecode = caam_jr_strstatus(jrdev, err);
584045e3678SYuan Kang 
585c19650d6SHoria Geantă 	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
586c19650d6SHoria Geantă 	memcpy(req->result, state->caam_ctx, digestsize);
587045e3678SYuan Kang 	kfree(edesc);
588045e3678SYuan Kang 
5896e005503SSascha Hauer 	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
590045e3678SYuan Kang 			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
591045e3678SYuan Kang 			     ctx->ctx_len, 1);
592045e3678SYuan Kang 
5931984aaeeSHoria Geantă 	req->base.complete(&req->base, ecode);
594045e3678SYuan Kang }
595045e3678SYuan Kang 
596045e3678SYuan Kang static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err,
597045e3678SYuan Kang 			    void *context)
598045e3678SYuan Kang {
599045e3678SYuan Kang 	struct ahash_request *req = context;
600045e3678SYuan Kang 	struct ahash_edesc *edesc;
601045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
602045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
603045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
604045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
6051984aaeeSHoria Geantă 	int ecode = 0;
606045e3678SYuan Kang 
6076e005503SSascha Hauer 	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
608045e3678SYuan Kang 
6094ca7c7d8SHoria Geantă 	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
610fa9659cdSMarek Vasut 	if (err)
6111984aaeeSHoria Geantă 		ecode = caam_jr_strstatus(jrdev, err);
612045e3678SYuan Kang 
613045e3678SYuan Kang 	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
614045e3678SYuan Kang 	kfree(edesc);
615045e3678SYuan Kang 
61646b49abcSAndrei Botila 	scatterwalk_map_and_copy(state->buf, req->src,
61746b49abcSAndrei Botila 				 req->nbytes - state->next_buflen,
61846b49abcSAndrei Botila 				 state->next_buflen, 0);
61946b49abcSAndrei Botila 	state->buflen = state->next_buflen;
62046b49abcSAndrei Botila 
62146b49abcSAndrei Botila 	print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
62246b49abcSAndrei Botila 			     DUMP_PREFIX_ADDRESS, 16, 4, state->buf,
62346b49abcSAndrei Botila 			     state->buflen, 1);
62446b49abcSAndrei Botila 
6256e005503SSascha Hauer 	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
626045e3678SYuan Kang 			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
627045e3678SYuan Kang 			     ctx->ctx_len, 1);
628045e3678SYuan Kang 	if (req->result)
6296e005503SSascha Hauer 		print_hex_dump_debug("result@"__stringify(__LINE__)": ",
630045e3678SYuan Kang 				     DUMP_PREFIX_ADDRESS, 16, 4, req->result,
631045e3678SYuan Kang 				     digestsize, 1);
632045e3678SYuan Kang 
6331984aaeeSHoria Geantă 	req->base.complete(&req->base, ecode);
634045e3678SYuan Kang }
635045e3678SYuan Kang 
636045e3678SYuan Kang static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
637045e3678SYuan Kang 			       void *context)
638045e3678SYuan Kang {
639045e3678SYuan Kang 	struct ahash_request *req = context;
640045e3678SYuan Kang 	struct ahash_edesc *edesc;
641045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
642045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
643c19650d6SHoria Geantă 	struct caam_hash_state *state = ahash_request_ctx(req);
644045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
6451984aaeeSHoria Geantă 	int ecode = 0;
646045e3678SYuan Kang 
6476e005503SSascha Hauer 	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
648045e3678SYuan Kang 
6494ca7c7d8SHoria Geantă 	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
650fa9659cdSMarek Vasut 	if (err)
6511984aaeeSHoria Geantă 		ecode = caam_jr_strstatus(jrdev, err);
652045e3678SYuan Kang 
653c19650d6SHoria Geantă 	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
654c19650d6SHoria Geantă 	memcpy(req->result, state->caam_ctx, digestsize);
655045e3678SYuan Kang 	kfree(edesc);
656045e3678SYuan Kang 
6576e005503SSascha Hauer 	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
658045e3678SYuan Kang 			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
659045e3678SYuan Kang 			     ctx->ctx_len, 1);
660045e3678SYuan Kang 
6611984aaeeSHoria Geantă 	req->base.complete(&req->base, ecode);
662045e3678SYuan Kang }
663045e3678SYuan Kang 
664045e3678SYuan Kang static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
665045e3678SYuan Kang 			       void *context)
666045e3678SYuan Kang {
667045e3678SYuan Kang 	struct ahash_request *req = context;
668045e3678SYuan Kang 	struct ahash_edesc *edesc;
669045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
670045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
671045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
672045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
6731984aaeeSHoria Geantă 	int ecode = 0;
674045e3678SYuan Kang 
6756e005503SSascha Hauer 	dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
676045e3678SYuan Kang 
6774ca7c7d8SHoria Geantă 	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
678fa9659cdSMarek Vasut 	if (err)
6791984aaeeSHoria Geantă 		ecode = caam_jr_strstatus(jrdev, err);
680045e3678SYuan Kang 
681ef62b231SHoria Geanta 	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_FROM_DEVICE);
682045e3678SYuan Kang 	kfree(edesc);
683045e3678SYuan Kang 
68446b49abcSAndrei Botila 	scatterwalk_map_and_copy(state->buf, req->src,
68546b49abcSAndrei Botila 				 req->nbytes - state->next_buflen,
68646b49abcSAndrei Botila 				 state->next_buflen, 0);
68746b49abcSAndrei Botila 	state->buflen = state->next_buflen;
68846b49abcSAndrei Botila 
68946b49abcSAndrei Botila 	print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
69046b49abcSAndrei Botila 			     DUMP_PREFIX_ADDRESS, 16, 4, state->buf,
69146b49abcSAndrei Botila 			     state->buflen, 1);
69246b49abcSAndrei Botila 
6936e005503SSascha Hauer 	print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
694045e3678SYuan Kang 			     DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
695045e3678SYuan Kang 			     ctx->ctx_len, 1);
696045e3678SYuan Kang 	if (req->result)
6976e005503SSascha Hauer 		print_hex_dump_debug("result@"__stringify(__LINE__)": ",
698045e3678SYuan Kang 				     DUMP_PREFIX_ADDRESS, 16, 4, req->result,
699045e3678SYuan Kang 				     digestsize, 1);
700045e3678SYuan Kang 
7011984aaeeSHoria Geantă 	req->base.complete(&req->base, ecode);
702045e3678SYuan Kang }
703045e3678SYuan Kang 
7045588d039SRussell King /*
7055588d039SRussell King  * Allocate an enhanced descriptor, which contains the hardware descriptor
7065588d039SRussell King  * and space for hardware scatter table containing sg_num entries.
7075588d039SRussell King  */
7085588d039SRussell King static struct ahash_edesc *ahash_edesc_alloc(struct caam_hash_ctx *ctx,
70930a43b44SRussell King 					     int sg_num, u32 *sh_desc,
71030a43b44SRussell King 					     dma_addr_t sh_desc_dma,
71130a43b44SRussell King 					     gfp_t flags)
7125588d039SRussell King {
7135588d039SRussell King 	struct ahash_edesc *edesc;
7145588d039SRussell King 	unsigned int sg_size = sg_num * sizeof(struct sec4_sg_entry);
7155588d039SRussell King 
7165588d039SRussell King 	edesc = kzalloc(sizeof(*edesc) + sg_size, GFP_DMA | flags);
7175588d039SRussell King 	if (!edesc) {
7185588d039SRussell King 		dev_err(ctx->jrdev, "could not allocate extended descriptor\n");
7195588d039SRussell King 		return NULL;
7205588d039SRussell King 	}
7215588d039SRussell King 
72230a43b44SRussell King 	init_job_desc_shared(edesc->hw_desc, sh_desc_dma, desc_len(sh_desc),
72330a43b44SRussell King 			     HDR_SHARE_DEFER | HDR_REVERSE);
72430a43b44SRussell King 
7255588d039SRussell King 	return edesc;
7265588d039SRussell King }
7275588d039SRussell King 
72865cf164aSRussell King static int ahash_edesc_add_src(struct caam_hash_ctx *ctx,
72965cf164aSRussell King 			       struct ahash_edesc *edesc,
73065cf164aSRussell King 			       struct ahash_request *req, int nents,
73165cf164aSRussell King 			       unsigned int first_sg,
73265cf164aSRussell King 			       unsigned int first_bytes, size_t to_hash)
73365cf164aSRussell King {
73465cf164aSRussell King 	dma_addr_t src_dma;
73565cf164aSRussell King 	u32 options;
73665cf164aSRussell King 
73765cf164aSRussell King 	if (nents > 1 || first_sg) {
73865cf164aSRussell King 		struct sec4_sg_entry *sg = edesc->sec4_sg;
739a5e5c133SHoria Geantă 		unsigned int sgsize = sizeof(*sg) *
740a5e5c133SHoria Geantă 				      pad_sg_nents(first_sg + nents);
74165cf164aSRussell King 
742059d73eeSHoria Geantă 		sg_to_sec4_sg_last(req->src, to_hash, sg + first_sg, 0);
74365cf164aSRussell King 
74465cf164aSRussell King 		src_dma = dma_map_single(ctx->jrdev, sg, sgsize, DMA_TO_DEVICE);
74565cf164aSRussell King 		if (dma_mapping_error(ctx->jrdev, src_dma)) {
74665cf164aSRussell King 			dev_err(ctx->jrdev, "unable to map S/G table\n");
74765cf164aSRussell King 			return -ENOMEM;
74865cf164aSRussell King 		}
74965cf164aSRussell King 
75065cf164aSRussell King 		edesc->sec4_sg_bytes = sgsize;
75165cf164aSRussell King 		edesc->sec4_sg_dma = src_dma;
75265cf164aSRussell King 		options = LDST_SGF;
75365cf164aSRussell King 	} else {
75465cf164aSRussell King 		src_dma = sg_dma_address(req->src);
75565cf164aSRussell King 		options = 0;
75665cf164aSRussell King 	}
75765cf164aSRussell King 
75865cf164aSRussell King 	append_seq_in_ptr(edesc->hw_desc, src_dma, first_bytes + to_hash,
75965cf164aSRussell King 			  options);
76065cf164aSRussell King 
76165cf164aSRussell King 	return 0;
76265cf164aSRussell King }
76365cf164aSRussell King 
764045e3678SYuan Kang /* submit update job descriptor */
765045e3678SYuan Kang static int ahash_update_ctx(struct ahash_request *req)
766045e3678SYuan Kang {
767045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
768045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
769045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
770045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
771019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
772019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
77346b49abcSAndrei Botila 	u8 *buf = state->buf;
77446b49abcSAndrei Botila 	int *buflen = &state->buflen;
77546b49abcSAndrei Botila 	int *next_buflen = &state->next_buflen;
77612b8567fSIuliana Prodan 	int blocksize = crypto_ahash_blocksize(ahash);
777045e3678SYuan Kang 	int in_len = *buflen + req->nbytes, to_hash;
77830a43b44SRussell King 	u32 *desc;
779bc13c69eSRussell King 	int src_nents, mapped_nents, sec4_sg_bytes, sec4_sg_src_index;
780045e3678SYuan Kang 	struct ahash_edesc *edesc;
781045e3678SYuan Kang 	int ret = 0;
782045e3678SYuan Kang 
78312b8567fSIuliana Prodan 	*next_buflen = in_len & (blocksize - 1);
784045e3678SYuan Kang 	to_hash = in_len - *next_buflen;
785045e3678SYuan Kang 
78612b8567fSIuliana Prodan 	/*
78787870cfbSIuliana Prodan 	 * For XCBC and CMAC, if to_hash is multiple of block size,
78812b8567fSIuliana Prodan 	 * keep last block in internal buffer
78912b8567fSIuliana Prodan 	 */
79087870cfbSIuliana Prodan 	if ((is_xcbc_aes(ctx->adata.algtype) ||
79187870cfbSIuliana Prodan 	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
79212b8567fSIuliana Prodan 	     (*next_buflen == 0)) {
79312b8567fSIuliana Prodan 		*next_buflen = blocksize;
79412b8567fSIuliana Prodan 		to_hash -= blocksize;
79512b8567fSIuliana Prodan 	}
79612b8567fSIuliana Prodan 
797045e3678SYuan Kang 	if (to_hash) {
798a5e5c133SHoria Geantă 		int pad_nents;
799059d73eeSHoria Geantă 		int src_len = req->nbytes - *next_buflen;
800a5e5c133SHoria Geantă 
801059d73eeSHoria Geantă 		src_nents = sg_nents_for_len(req->src, src_len);
802f9970c28SLABBE Corentin 		if (src_nents < 0) {
803f9970c28SLABBE Corentin 			dev_err(jrdev, "Invalid number of src SG.\n");
804f9970c28SLABBE Corentin 			return src_nents;
805f9970c28SLABBE Corentin 		}
806bc13c69eSRussell King 
807bc13c69eSRussell King 		if (src_nents) {
808bc13c69eSRussell King 			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
809bc13c69eSRussell King 						  DMA_TO_DEVICE);
810bc13c69eSRussell King 			if (!mapped_nents) {
811bc13c69eSRussell King 				dev_err(jrdev, "unable to DMA map source\n");
812bc13c69eSRussell King 				return -ENOMEM;
813bc13c69eSRussell King 			}
814bc13c69eSRussell King 		} else {
815bc13c69eSRussell King 			mapped_nents = 0;
816bc13c69eSRussell King 		}
817bc13c69eSRussell King 
818045e3678SYuan Kang 		sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
819a5e5c133SHoria Geantă 		pad_nents = pad_sg_nents(sec4_sg_src_index + mapped_nents);
820a5e5c133SHoria Geantă 		sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
821045e3678SYuan Kang 
822045e3678SYuan Kang 		/*
823045e3678SYuan Kang 		 * allocate space for base edesc and hw desc commands,
824045e3678SYuan Kang 		 * link tables
825045e3678SYuan Kang 		 */
826a5e5c133SHoria Geantă 		edesc = ahash_edesc_alloc(ctx, pad_nents, ctx->sh_desc_update,
82730a43b44SRussell King 					  ctx->sh_desc_update_dma, flags);
828045e3678SYuan Kang 		if (!edesc) {
829bc13c69eSRussell King 			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
830045e3678SYuan Kang 			return -ENOMEM;
831045e3678SYuan Kang 		}
832045e3678SYuan Kang 
833045e3678SYuan Kang 		edesc->src_nents = src_nents;
834045e3678SYuan Kang 		edesc->sec4_sg_bytes = sec4_sg_bytes;
835045e3678SYuan Kang 
836dfcd8393SHoria Geantă 		ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
837045e3678SYuan Kang 					 edesc->sec4_sg, DMA_BIDIRECTIONAL);
838ce572085SHoria Geanta 		if (ret)
83958b0e5d0SMarkus Elfring 			goto unmap_ctx;
840045e3678SYuan Kang 
841944c3d4dSHoria Geantă 		ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
842944c3d4dSHoria Geantă 		if (ret)
843944c3d4dSHoria Geantă 			goto unmap_ctx;
844045e3678SYuan Kang 
845b4e9e931SIuliana Prodan 		if (mapped_nents)
846059d73eeSHoria Geantă 			sg_to_sec4_sg_last(req->src, src_len,
847bc13c69eSRussell King 					   edesc->sec4_sg + sec4_sg_src_index,
848bc13c69eSRussell King 					   0);
849b4e9e931SIuliana Prodan 		else
850b4e9e931SIuliana Prodan 			sg_to_sec4_set_last(edesc->sec4_sg + sec4_sg_src_index -
851b4e9e931SIuliana Prodan 					    1);
852b4e9e931SIuliana Prodan 
853045e3678SYuan Kang 		desc = edesc->hw_desc;
854045e3678SYuan Kang 
8551da2be33SRuchika Gupta 		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
8561da2be33SRuchika Gupta 						     sec4_sg_bytes,
8571da2be33SRuchika Gupta 						     DMA_TO_DEVICE);
858ce572085SHoria Geanta 		if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
859ce572085SHoria Geanta 			dev_err(jrdev, "unable to map S/G table\n");
86032686d34SRussell King 			ret = -ENOMEM;
86158b0e5d0SMarkus Elfring 			goto unmap_ctx;
862ce572085SHoria Geanta 		}
8631da2be33SRuchika Gupta 
864045e3678SYuan Kang 		append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
865045e3678SYuan Kang 				       to_hash, LDST_SGF);
866045e3678SYuan Kang 
867045e3678SYuan Kang 		append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0);
868045e3678SYuan Kang 
8696e005503SSascha Hauer 		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
870045e3678SYuan Kang 				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
871045e3678SYuan Kang 				     desc_bytes(desc), 1);
872045e3678SYuan Kang 
873045e3678SYuan Kang 		ret = caam_jr_enqueue(jrdev, desc, ahash_done_bi, req);
87432686d34SRussell King 		if (ret)
87558b0e5d0SMarkus Elfring 			goto unmap_ctx;
87632686d34SRussell King 
877045e3678SYuan Kang 		ret = -EINPROGRESS;
878045e3678SYuan Kang 	} else if (*next_buflen) {
879307fd543SCristian Stoica 		scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
880307fd543SCristian Stoica 					 req->nbytes, 0);
881045e3678SYuan Kang 		*buflen = *next_buflen;
8826e005503SSascha Hauer 
8836e005503SSascha Hauer 		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
88446b49abcSAndrei Botila 				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
88546b49abcSAndrei Botila 				     *buflen, 1);
88646b49abcSAndrei Botila 	}
887045e3678SYuan Kang 
888045e3678SYuan Kang 	return ret;
88958b0e5d0SMarkus Elfring unmap_ctx:
89032686d34SRussell King 	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
89132686d34SRussell King 	kfree(edesc);
89232686d34SRussell King 	return ret;
893045e3678SYuan Kang }
894045e3678SYuan Kang 
895045e3678SYuan Kang static int ahash_final_ctx(struct ahash_request *req)
896045e3678SYuan Kang {
897045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
898045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
899045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
900045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
901019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
902019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
90346b49abcSAndrei Botila 	int buflen = state->buflen;
90430a43b44SRussell King 	u32 *desc;
905a5e5c133SHoria Geantă 	int sec4_sg_bytes;
906045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
907045e3678SYuan Kang 	struct ahash_edesc *edesc;
9089e6df0fdSMarkus Elfring 	int ret;
909045e3678SYuan Kang 
910a5e5c133SHoria Geantă 	sec4_sg_bytes = pad_sg_nents(1 + (buflen ? 1 : 0)) *
911a5e5c133SHoria Geantă 			sizeof(struct sec4_sg_entry);
912045e3678SYuan Kang 
913045e3678SYuan Kang 	/* allocate space for base edesc and hw desc commands, link tables */
914a5e5c133SHoria Geantă 	edesc = ahash_edesc_alloc(ctx, 4, ctx->sh_desc_fin,
915a5e5c133SHoria Geantă 				  ctx->sh_desc_fin_dma, flags);
9165588d039SRussell King 	if (!edesc)
917045e3678SYuan Kang 		return -ENOMEM;
918045e3678SYuan Kang 
919045e3678SYuan Kang 	desc = edesc->hw_desc;
920045e3678SYuan Kang 
921045e3678SYuan Kang 	edesc->sec4_sg_bytes = sec4_sg_bytes;
922045e3678SYuan Kang 
923dfcd8393SHoria Geantă 	ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
924c19650d6SHoria Geantă 				 edesc->sec4_sg, DMA_BIDIRECTIONAL);
925ce572085SHoria Geanta 	if (ret)
92658b0e5d0SMarkus Elfring 		goto unmap_ctx;
927045e3678SYuan Kang 
928944c3d4dSHoria Geantă 	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
929944c3d4dSHoria Geantă 	if (ret)
930944c3d4dSHoria Geantă 		goto unmap_ctx;
931944c3d4dSHoria Geantă 
932a5e5c133SHoria Geantă 	sg_to_sec4_set_last(edesc->sec4_sg + (buflen ? 1 : 0));
933045e3678SYuan Kang 
9341da2be33SRuchika Gupta 	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
9351da2be33SRuchika Gupta 					    sec4_sg_bytes, DMA_TO_DEVICE);
936ce572085SHoria Geanta 	if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
937ce572085SHoria Geanta 		dev_err(jrdev, "unable to map S/G table\n");
93832686d34SRussell King 		ret = -ENOMEM;
93958b0e5d0SMarkus Elfring 		goto unmap_ctx;
940ce572085SHoria Geanta 	}
9411da2be33SRuchika Gupta 
942045e3678SYuan Kang 	append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
943045e3678SYuan Kang 			  LDST_SGF);
944c19650d6SHoria Geantă 	append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
945045e3678SYuan Kang 
9466e005503SSascha Hauer 	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
9476e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
9486e005503SSascha Hauer 			     1);
949045e3678SYuan Kang 
950045e3678SYuan Kang 	ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req);
95132686d34SRussell King 	if (ret)
95258b0e5d0SMarkus Elfring 		goto unmap_ctx;
95332686d34SRussell King 
95432686d34SRussell King 	return -EINPROGRESS;
95558b0e5d0SMarkus Elfring  unmap_ctx:
956c19650d6SHoria Geantă 	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
957045e3678SYuan Kang 	kfree(edesc);
958045e3678SYuan Kang 	return ret;
959045e3678SYuan Kang }
960045e3678SYuan Kang 
961045e3678SYuan Kang static int ahash_finup_ctx(struct ahash_request *req)
962045e3678SYuan Kang {
963045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
964045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
965045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
966045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
967019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
968019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
96946b49abcSAndrei Botila 	int buflen = state->buflen;
97030a43b44SRussell King 	u32 *desc;
97165cf164aSRussell King 	int sec4_sg_src_index;
972bc13c69eSRussell King 	int src_nents, mapped_nents;
973045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
974045e3678SYuan Kang 	struct ahash_edesc *edesc;
9759e6df0fdSMarkus Elfring 	int ret;
976045e3678SYuan Kang 
97713fb8fd7SLABBE Corentin 	src_nents = sg_nents_for_len(req->src, req->nbytes);
978f9970c28SLABBE Corentin 	if (src_nents < 0) {
979f9970c28SLABBE Corentin 		dev_err(jrdev, "Invalid number of src SG.\n");
980f9970c28SLABBE Corentin 		return src_nents;
981f9970c28SLABBE Corentin 	}
982bc13c69eSRussell King 
983bc13c69eSRussell King 	if (src_nents) {
984bc13c69eSRussell King 		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
985bc13c69eSRussell King 					  DMA_TO_DEVICE);
986bc13c69eSRussell King 		if (!mapped_nents) {
987bc13c69eSRussell King 			dev_err(jrdev, "unable to DMA map source\n");
988bc13c69eSRussell King 			return -ENOMEM;
989bc13c69eSRussell King 		}
990bc13c69eSRussell King 	} else {
991bc13c69eSRussell King 		mapped_nents = 0;
992bc13c69eSRussell King 	}
993bc13c69eSRussell King 
994045e3678SYuan Kang 	sec4_sg_src_index = 1 + (buflen ? 1 : 0);
995045e3678SYuan Kang 
996045e3678SYuan Kang 	/* allocate space for base edesc and hw desc commands, link tables */
9975588d039SRussell King 	edesc = ahash_edesc_alloc(ctx, sec4_sg_src_index + mapped_nents,
9989a1a1c08SHoria Geantă 				  ctx->sh_desc_fin, ctx->sh_desc_fin_dma,
9995588d039SRussell King 				  flags);
1000045e3678SYuan Kang 	if (!edesc) {
1001bc13c69eSRussell King 		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1002045e3678SYuan Kang 		return -ENOMEM;
1003045e3678SYuan Kang 	}
1004045e3678SYuan Kang 
1005045e3678SYuan Kang 	desc = edesc->hw_desc;
1006045e3678SYuan Kang 
1007045e3678SYuan Kang 	edesc->src_nents = src_nents;
1008045e3678SYuan Kang 
1009dfcd8393SHoria Geantă 	ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
1010c19650d6SHoria Geantă 				 edesc->sec4_sg, DMA_BIDIRECTIONAL);
1011ce572085SHoria Geanta 	if (ret)
101258b0e5d0SMarkus Elfring 		goto unmap_ctx;
1013045e3678SYuan Kang 
1014944c3d4dSHoria Geantă 	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
1015944c3d4dSHoria Geantă 	if (ret)
1016944c3d4dSHoria Geantă 		goto unmap_ctx;
1017045e3678SYuan Kang 
101865cf164aSRussell King 	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents,
101965cf164aSRussell King 				  sec4_sg_src_index, ctx->ctx_len + buflen,
102065cf164aSRussell King 				  req->nbytes);
102165cf164aSRussell King 	if (ret)
102258b0e5d0SMarkus Elfring 		goto unmap_ctx;
1023045e3678SYuan Kang 
1024c19650d6SHoria Geantă 	append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
1025045e3678SYuan Kang 
10266e005503SSascha Hauer 	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
10276e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
10286e005503SSascha Hauer 			     1);
1029045e3678SYuan Kang 
1030045e3678SYuan Kang 	ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req);
103132686d34SRussell King 	if (ret)
103258b0e5d0SMarkus Elfring 		goto unmap_ctx;
103332686d34SRussell King 
103432686d34SRussell King 	return -EINPROGRESS;
103558b0e5d0SMarkus Elfring  unmap_ctx:
1036c19650d6SHoria Geantă 	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
1037045e3678SYuan Kang 	kfree(edesc);
1038045e3678SYuan Kang 	return ret;
1039045e3678SYuan Kang }
1040045e3678SYuan Kang 
1041045e3678SYuan Kang static int ahash_digest(struct ahash_request *req)
1042045e3678SYuan Kang {
1043045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1044045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1045944c3d4dSHoria Geantă 	struct caam_hash_state *state = ahash_request_ctx(req);
1046045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
1047019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
1048019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
104930a43b44SRussell King 	u32 *desc;
1050045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
105165cf164aSRussell King 	int src_nents, mapped_nents;
1052045e3678SYuan Kang 	struct ahash_edesc *edesc;
10539e6df0fdSMarkus Elfring 	int ret;
1054045e3678SYuan Kang 
1055944c3d4dSHoria Geantă 	state->buf_dma = 0;
1056944c3d4dSHoria Geantă 
10573d5a2db6SRussell King 	src_nents = sg_nents_for_len(req->src, req->nbytes);
1058f9970c28SLABBE Corentin 	if (src_nents < 0) {
1059f9970c28SLABBE Corentin 		dev_err(jrdev, "Invalid number of src SG.\n");
1060f9970c28SLABBE Corentin 		return src_nents;
1061f9970c28SLABBE Corentin 	}
1062bc13c69eSRussell King 
1063bc13c69eSRussell King 	if (src_nents) {
1064bc13c69eSRussell King 		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1065bc13c69eSRussell King 					  DMA_TO_DEVICE);
1066bc13c69eSRussell King 		if (!mapped_nents) {
1067bc13c69eSRussell King 			dev_err(jrdev, "unable to map source for DMA\n");
1068bc13c69eSRussell King 			return -ENOMEM;
1069bc13c69eSRussell King 		}
1070bc13c69eSRussell King 	} else {
1071bc13c69eSRussell King 		mapped_nents = 0;
1072bc13c69eSRussell King 	}
1073bc13c69eSRussell King 
1074045e3678SYuan Kang 	/* allocate space for base edesc and hw desc commands, link tables */
10755588d039SRussell King 	edesc = ahash_edesc_alloc(ctx, mapped_nents > 1 ? mapped_nents : 0,
107630a43b44SRussell King 				  ctx->sh_desc_digest, ctx->sh_desc_digest_dma,
10775588d039SRussell King 				  flags);
1078045e3678SYuan Kang 	if (!edesc) {
1079bc13c69eSRussell King 		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1080045e3678SYuan Kang 		return -ENOMEM;
1081045e3678SYuan Kang 	}
1082343e44b1SRussell King 
1083045e3678SYuan Kang 	edesc->src_nents = src_nents;
1084045e3678SYuan Kang 
108565cf164aSRussell King 	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
108665cf164aSRussell King 				  req->nbytes);
108765cf164aSRussell King 	if (ret) {
108832686d34SRussell King 		ahash_unmap(jrdev, edesc, req, digestsize);
108932686d34SRussell King 		kfree(edesc);
109065cf164aSRussell King 		return ret;
1091ce572085SHoria Geanta 	}
109265cf164aSRussell King 
109365cf164aSRussell King 	desc = edesc->hw_desc;
1094045e3678SYuan Kang 
1095c19650d6SHoria Geantă 	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1096c19650d6SHoria Geantă 	if (ret) {
109732686d34SRussell King 		ahash_unmap(jrdev, edesc, req, digestsize);
109832686d34SRussell King 		kfree(edesc);
1099ce572085SHoria Geanta 		return -ENOMEM;
1100ce572085SHoria Geanta 	}
1101045e3678SYuan Kang 
11026e005503SSascha Hauer 	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
11036e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
11046e005503SSascha Hauer 			     1);
1105045e3678SYuan Kang 
1106045e3678SYuan Kang 	ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
1107045e3678SYuan Kang 	if (!ret) {
1108045e3678SYuan Kang 		ret = -EINPROGRESS;
1109045e3678SYuan Kang 	} else {
1110c19650d6SHoria Geantă 		ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1111045e3678SYuan Kang 		kfree(edesc);
1112045e3678SYuan Kang 	}
1113045e3678SYuan Kang 
1114045e3678SYuan Kang 	return ret;
1115045e3678SYuan Kang }
1116045e3678SYuan Kang 
1117045e3678SYuan Kang /* submit ahash final if it the first job descriptor */
1118045e3678SYuan Kang static int ahash_final_no_ctx(struct ahash_request *req)
1119045e3678SYuan Kang {
1120045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1121045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1122045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1123045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
1124019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
1125019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
112646b49abcSAndrei Botila 	u8 *buf = state->buf;
112746b49abcSAndrei Botila 	int buflen = state->buflen;
112830a43b44SRussell King 	u32 *desc;
1129045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
1130045e3678SYuan Kang 	struct ahash_edesc *edesc;
11319e6df0fdSMarkus Elfring 	int ret;
1132045e3678SYuan Kang 
1133045e3678SYuan Kang 	/* allocate space for base edesc and hw desc commands, link tables */
113430a43b44SRussell King 	edesc = ahash_edesc_alloc(ctx, 0, ctx->sh_desc_digest,
113530a43b44SRussell King 				  ctx->sh_desc_digest_dma, flags);
11365588d039SRussell King 	if (!edesc)
1137045e3678SYuan Kang 		return -ENOMEM;
1138045e3678SYuan Kang 
1139045e3678SYuan Kang 	desc = edesc->hw_desc;
1140045e3678SYuan Kang 
114104e6d25cSAymen Sghaier 	if (buflen) {
114204e6d25cSAymen Sghaier 		state->buf_dma = dma_map_single(jrdev, buf, buflen,
114304e6d25cSAymen Sghaier 						DMA_TO_DEVICE);
1144ce572085SHoria Geanta 		if (dma_mapping_error(jrdev, state->buf_dma)) {
1145ce572085SHoria Geanta 			dev_err(jrdev, "unable to map src\n");
114606435f34SMarkus Elfring 			goto unmap;
1147ce572085SHoria Geanta 		}
1148045e3678SYuan Kang 
1149045e3678SYuan Kang 		append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
115004e6d25cSAymen Sghaier 	}
1151045e3678SYuan Kang 
1152c19650d6SHoria Geantă 	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1153c19650d6SHoria Geantă 	if (ret)
115406435f34SMarkus Elfring 		goto unmap;
1155045e3678SYuan Kang 
11566e005503SSascha Hauer 	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
11576e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
11586e005503SSascha Hauer 			     1);
1159045e3678SYuan Kang 
1160045e3678SYuan Kang 	ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
1161045e3678SYuan Kang 	if (!ret) {
1162045e3678SYuan Kang 		ret = -EINPROGRESS;
1163045e3678SYuan Kang 	} else {
1164c19650d6SHoria Geantă 		ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1165045e3678SYuan Kang 		kfree(edesc);
1166045e3678SYuan Kang 	}
1167045e3678SYuan Kang 
1168045e3678SYuan Kang 	return ret;
116906435f34SMarkus Elfring  unmap:
117006435f34SMarkus Elfring 	ahash_unmap(jrdev, edesc, req, digestsize);
117106435f34SMarkus Elfring 	kfree(edesc);
117206435f34SMarkus Elfring 	return -ENOMEM;
117306435f34SMarkus Elfring 
1174045e3678SYuan Kang }
1175045e3678SYuan Kang 
1176045e3678SYuan Kang /* submit ahash update if it the first job descriptor after update */
1177045e3678SYuan Kang static int ahash_update_no_ctx(struct ahash_request *req)
1178045e3678SYuan Kang {
1179045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1180045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1181045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1182045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
1183019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
1184019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
118546b49abcSAndrei Botila 	u8 *buf = state->buf;
118646b49abcSAndrei Botila 	int *buflen = &state->buflen;
118746b49abcSAndrei Botila 	int *next_buflen = &state->next_buflen;
118812b8567fSIuliana Prodan 	int blocksize = crypto_ahash_blocksize(ahash);
1189045e3678SYuan Kang 	int in_len = *buflen + req->nbytes, to_hash;
1190bc13c69eSRussell King 	int sec4_sg_bytes, src_nents, mapped_nents;
1191045e3678SYuan Kang 	struct ahash_edesc *edesc;
119230a43b44SRussell King 	u32 *desc;
1193045e3678SYuan Kang 	int ret = 0;
1194045e3678SYuan Kang 
119512b8567fSIuliana Prodan 	*next_buflen = in_len & (blocksize - 1);
1196045e3678SYuan Kang 	to_hash = in_len - *next_buflen;
1197045e3678SYuan Kang 
119812b8567fSIuliana Prodan 	/*
119987870cfbSIuliana Prodan 	 * For XCBC and CMAC, if to_hash is multiple of block size,
120012b8567fSIuliana Prodan 	 * keep last block in internal buffer
120112b8567fSIuliana Prodan 	 */
120287870cfbSIuliana Prodan 	if ((is_xcbc_aes(ctx->adata.algtype) ||
120387870cfbSIuliana Prodan 	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
120412b8567fSIuliana Prodan 	     (*next_buflen == 0)) {
120512b8567fSIuliana Prodan 		*next_buflen = blocksize;
120612b8567fSIuliana Prodan 		to_hash -= blocksize;
120712b8567fSIuliana Prodan 	}
120812b8567fSIuliana Prodan 
1209045e3678SYuan Kang 	if (to_hash) {
1210a5e5c133SHoria Geantă 		int pad_nents;
1211059d73eeSHoria Geantă 		int src_len = req->nbytes - *next_buflen;
1212a5e5c133SHoria Geantă 
1213059d73eeSHoria Geantă 		src_nents = sg_nents_for_len(req->src, src_len);
1214f9970c28SLABBE Corentin 		if (src_nents < 0) {
1215f9970c28SLABBE Corentin 			dev_err(jrdev, "Invalid number of src SG.\n");
1216f9970c28SLABBE Corentin 			return src_nents;
1217f9970c28SLABBE Corentin 		}
1218bc13c69eSRussell King 
1219bc13c69eSRussell King 		if (src_nents) {
1220bc13c69eSRussell King 			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1221bc13c69eSRussell King 						  DMA_TO_DEVICE);
1222bc13c69eSRussell King 			if (!mapped_nents) {
1223bc13c69eSRussell King 				dev_err(jrdev, "unable to DMA map source\n");
1224bc13c69eSRussell King 				return -ENOMEM;
1225bc13c69eSRussell King 			}
1226bc13c69eSRussell King 		} else {
1227bc13c69eSRussell King 			mapped_nents = 0;
1228bc13c69eSRussell King 		}
1229bc13c69eSRussell King 
1230a5e5c133SHoria Geantă 		pad_nents = pad_sg_nents(1 + mapped_nents);
1231a5e5c133SHoria Geantă 		sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
1232045e3678SYuan Kang 
1233045e3678SYuan Kang 		/*
1234045e3678SYuan Kang 		 * allocate space for base edesc and hw desc commands,
1235045e3678SYuan Kang 		 * link tables
1236045e3678SYuan Kang 		 */
1237a5e5c133SHoria Geantă 		edesc = ahash_edesc_alloc(ctx, pad_nents,
123830a43b44SRussell King 					  ctx->sh_desc_update_first,
123930a43b44SRussell King 					  ctx->sh_desc_update_first_dma,
124030a43b44SRussell King 					  flags);
1241045e3678SYuan Kang 		if (!edesc) {
1242bc13c69eSRussell King 			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1243045e3678SYuan Kang 			return -ENOMEM;
1244045e3678SYuan Kang 		}
1245045e3678SYuan Kang 
1246045e3678SYuan Kang 		edesc->src_nents = src_nents;
1247045e3678SYuan Kang 		edesc->sec4_sg_bytes = sec4_sg_bytes;
1248045e3678SYuan Kang 
1249944c3d4dSHoria Geantă 		ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
1250944c3d4dSHoria Geantă 		if (ret)
1251944c3d4dSHoria Geantă 			goto unmap_ctx;
1252944c3d4dSHoria Geantă 
1253059d73eeSHoria Geantă 		sg_to_sec4_sg_last(req->src, src_len, edesc->sec4_sg + 1, 0);
1254bc13c69eSRussell King 
1255045e3678SYuan Kang 		desc = edesc->hw_desc;
1256045e3678SYuan Kang 
12571da2be33SRuchika Gupta 		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
12581da2be33SRuchika Gupta 						    sec4_sg_bytes,
12591da2be33SRuchika Gupta 						    DMA_TO_DEVICE);
1260ce572085SHoria Geanta 		if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1261ce572085SHoria Geanta 			dev_err(jrdev, "unable to map S/G table\n");
126232686d34SRussell King 			ret = -ENOMEM;
126358b0e5d0SMarkus Elfring 			goto unmap_ctx;
1264ce572085SHoria Geanta 		}
12651da2be33SRuchika Gupta 
1266045e3678SYuan Kang 		append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
1267045e3678SYuan Kang 
1268ce572085SHoria Geanta 		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
1269ce572085SHoria Geanta 		if (ret)
127058b0e5d0SMarkus Elfring 			goto unmap_ctx;
1271045e3678SYuan Kang 
12726e005503SSascha Hauer 		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
1273045e3678SYuan Kang 				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
1274045e3678SYuan Kang 				     desc_bytes(desc), 1);
1275045e3678SYuan Kang 
1276045e3678SYuan Kang 		ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst, req);
127732686d34SRussell King 		if (ret)
127858b0e5d0SMarkus Elfring 			goto unmap_ctx;
127932686d34SRussell King 
1280045e3678SYuan Kang 		ret = -EINPROGRESS;
1281045e3678SYuan Kang 		state->update = ahash_update_ctx;
1282045e3678SYuan Kang 		state->finup = ahash_finup_ctx;
1283045e3678SYuan Kang 		state->final = ahash_final_ctx;
1284045e3678SYuan Kang 	} else if (*next_buflen) {
1285307fd543SCristian Stoica 		scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
1286307fd543SCristian Stoica 					 req->nbytes, 0);
1287045e3678SYuan Kang 		*buflen = *next_buflen;
12886e005503SSascha Hauer 
12896e005503SSascha Hauer 		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
129046b49abcSAndrei Botila 				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
129146b49abcSAndrei Botila 				     *buflen, 1);
129246b49abcSAndrei Botila 	}
1293045e3678SYuan Kang 
1294045e3678SYuan Kang 	return ret;
129558b0e5d0SMarkus Elfring  unmap_ctx:
129632686d34SRussell King 	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
129732686d34SRussell King 	kfree(edesc);
129832686d34SRussell King 	return ret;
1299045e3678SYuan Kang }
1300045e3678SYuan Kang 
1301045e3678SYuan Kang /* submit ahash finup if it the first job descriptor after update */
1302045e3678SYuan Kang static int ahash_finup_no_ctx(struct ahash_request *req)
1303045e3678SYuan Kang {
1304045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1305045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1306045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1307045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
1308019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
1309019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
131046b49abcSAndrei Botila 	int buflen = state->buflen;
131130a43b44SRussell King 	u32 *desc;
1312bc13c69eSRussell King 	int sec4_sg_bytes, sec4_sg_src_index, src_nents, mapped_nents;
1313045e3678SYuan Kang 	int digestsize = crypto_ahash_digestsize(ahash);
1314045e3678SYuan Kang 	struct ahash_edesc *edesc;
13159e6df0fdSMarkus Elfring 	int ret;
1316045e3678SYuan Kang 
131713fb8fd7SLABBE Corentin 	src_nents = sg_nents_for_len(req->src, req->nbytes);
1318f9970c28SLABBE Corentin 	if (src_nents < 0) {
1319f9970c28SLABBE Corentin 		dev_err(jrdev, "Invalid number of src SG.\n");
1320f9970c28SLABBE Corentin 		return src_nents;
1321f9970c28SLABBE Corentin 	}
1322bc13c69eSRussell King 
1323bc13c69eSRussell King 	if (src_nents) {
1324bc13c69eSRussell King 		mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1325bc13c69eSRussell King 					  DMA_TO_DEVICE);
1326bc13c69eSRussell King 		if (!mapped_nents) {
1327bc13c69eSRussell King 			dev_err(jrdev, "unable to DMA map source\n");
1328bc13c69eSRussell King 			return -ENOMEM;
1329bc13c69eSRussell King 		}
1330bc13c69eSRussell King 	} else {
1331bc13c69eSRussell King 		mapped_nents = 0;
1332bc13c69eSRussell King 	}
1333bc13c69eSRussell King 
1334045e3678SYuan Kang 	sec4_sg_src_index = 2;
1335bc13c69eSRussell King 	sec4_sg_bytes = (sec4_sg_src_index + mapped_nents) *
1336045e3678SYuan Kang 			 sizeof(struct sec4_sg_entry);
1337045e3678SYuan Kang 
1338045e3678SYuan Kang 	/* allocate space for base edesc and hw desc commands, link tables */
133930a43b44SRussell King 	edesc = ahash_edesc_alloc(ctx, sec4_sg_src_index + mapped_nents,
134030a43b44SRussell King 				  ctx->sh_desc_digest, ctx->sh_desc_digest_dma,
134130a43b44SRussell King 				  flags);
1342045e3678SYuan Kang 	if (!edesc) {
1343bc13c69eSRussell King 		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1344045e3678SYuan Kang 		return -ENOMEM;
1345045e3678SYuan Kang 	}
1346045e3678SYuan Kang 
1347045e3678SYuan Kang 	desc = edesc->hw_desc;
1348045e3678SYuan Kang 
1349045e3678SYuan Kang 	edesc->src_nents = src_nents;
1350045e3678SYuan Kang 	edesc->sec4_sg_bytes = sec4_sg_bytes;
1351045e3678SYuan Kang 
1352944c3d4dSHoria Geantă 	ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
1353944c3d4dSHoria Geantă 	if (ret)
1354944c3d4dSHoria Geantă 		goto unmap;
1355045e3678SYuan Kang 
135665cf164aSRussell King 	ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 1, buflen,
135765cf164aSRussell King 				  req->nbytes);
135865cf164aSRussell King 	if (ret) {
1359ce572085SHoria Geanta 		dev_err(jrdev, "unable to map S/G table\n");
136006435f34SMarkus Elfring 		goto unmap;
1361ce572085SHoria Geanta 	}
13621da2be33SRuchika Gupta 
1363c19650d6SHoria Geantă 	ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1364c19650d6SHoria Geantă 	if (ret)
136506435f34SMarkus Elfring 		goto unmap;
1366045e3678SYuan Kang 
13676e005503SSascha Hauer 	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
13686e005503SSascha Hauer 			     DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
13696e005503SSascha Hauer 			     1);
1370045e3678SYuan Kang 
1371045e3678SYuan Kang 	ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
1372045e3678SYuan Kang 	if (!ret) {
1373045e3678SYuan Kang 		ret = -EINPROGRESS;
1374045e3678SYuan Kang 	} else {
1375c19650d6SHoria Geantă 		ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
1376045e3678SYuan Kang 		kfree(edesc);
1377045e3678SYuan Kang 	}
1378045e3678SYuan Kang 
1379045e3678SYuan Kang 	return ret;
138006435f34SMarkus Elfring  unmap:
138106435f34SMarkus Elfring 	ahash_unmap(jrdev, edesc, req, digestsize);
138206435f34SMarkus Elfring 	kfree(edesc);
138306435f34SMarkus Elfring 	return -ENOMEM;
138406435f34SMarkus Elfring 
1385045e3678SYuan Kang }
1386045e3678SYuan Kang 
1387045e3678SYuan Kang /* submit first update job descriptor after init */
1388045e3678SYuan Kang static int ahash_update_first(struct ahash_request *req)
1389045e3678SYuan Kang {
1390045e3678SYuan Kang 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1391045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
1392045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1393045e3678SYuan Kang 	struct device *jrdev = ctx->jrdev;
1394019d62dbSHoria Geantă 	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
1395019d62dbSHoria Geantă 		       GFP_KERNEL : GFP_ATOMIC;
139646b49abcSAndrei Botila 	u8 *buf = state->buf;
139746b49abcSAndrei Botila 	int *buflen = &state->buflen;
139846b49abcSAndrei Botila 	int *next_buflen = &state->next_buflen;
1399045e3678SYuan Kang 	int to_hash;
140012b8567fSIuliana Prodan 	int blocksize = crypto_ahash_blocksize(ahash);
140130a43b44SRussell King 	u32 *desc;
140265cf164aSRussell King 	int src_nents, mapped_nents;
1403045e3678SYuan Kang 	struct ahash_edesc *edesc;
1404045e3678SYuan Kang 	int ret = 0;
1405045e3678SYuan Kang 
140612b8567fSIuliana Prodan 	*next_buflen = req->nbytes & (blocksize - 1);
1407045e3678SYuan Kang 	to_hash = req->nbytes - *next_buflen;
1408045e3678SYuan Kang 
140912b8567fSIuliana Prodan 	/*
141087870cfbSIuliana Prodan 	 * For XCBC and CMAC, if to_hash is multiple of block size,
141112b8567fSIuliana Prodan 	 * keep last block in internal buffer
141212b8567fSIuliana Prodan 	 */
141387870cfbSIuliana Prodan 	if ((is_xcbc_aes(ctx->adata.algtype) ||
141487870cfbSIuliana Prodan 	     is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
141512b8567fSIuliana Prodan 	     (*next_buflen == 0)) {
141612b8567fSIuliana Prodan 		*next_buflen = blocksize;
141712b8567fSIuliana Prodan 		to_hash -= blocksize;
141812b8567fSIuliana Prodan 	}
141912b8567fSIuliana Prodan 
1420045e3678SYuan Kang 	if (to_hash) {
14213d5a2db6SRussell King 		src_nents = sg_nents_for_len(req->src,
14223d5a2db6SRussell King 					     req->nbytes - *next_buflen);
1423f9970c28SLABBE Corentin 		if (src_nents < 0) {
1424f9970c28SLABBE Corentin 			dev_err(jrdev, "Invalid number of src SG.\n");
1425f9970c28SLABBE Corentin 			return src_nents;
1426f9970c28SLABBE Corentin 		}
1427bc13c69eSRussell King 
1428bc13c69eSRussell King 		if (src_nents) {
1429bc13c69eSRussell King 			mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1430bc13c69eSRussell King 						  DMA_TO_DEVICE);
1431bc13c69eSRussell King 			if (!mapped_nents) {
1432bc13c69eSRussell King 				dev_err(jrdev, "unable to map source for DMA\n");
1433bc13c69eSRussell King 				return -ENOMEM;
1434bc13c69eSRussell King 			}
1435bc13c69eSRussell King 		} else {
1436bc13c69eSRussell King 			mapped_nents = 0;
1437bc13c69eSRussell King 		}
1438045e3678SYuan Kang 
1439045e3678SYuan Kang 		/*
1440045e3678SYuan Kang 		 * allocate space for base edesc and hw desc commands,
1441045e3678SYuan Kang 		 * link tables
1442045e3678SYuan Kang 		 */
14435588d039SRussell King 		edesc = ahash_edesc_alloc(ctx, mapped_nents > 1 ?
144430a43b44SRussell King 					  mapped_nents : 0,
144530a43b44SRussell King 					  ctx->sh_desc_update_first,
144630a43b44SRussell King 					  ctx->sh_desc_update_first_dma,
144730a43b44SRussell King 					  flags);
1448045e3678SYuan Kang 		if (!edesc) {
1449bc13c69eSRussell King 			dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1450045e3678SYuan Kang 			return -ENOMEM;
1451045e3678SYuan Kang 		}
1452045e3678SYuan Kang 
1453045e3678SYuan Kang 		edesc->src_nents = src_nents;
1454045e3678SYuan Kang 
145565cf164aSRussell King 		ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
145665cf164aSRussell King 					  to_hash);
145765cf164aSRussell King 		if (ret)
145858b0e5d0SMarkus Elfring 			goto unmap_ctx;
1459045e3678SYuan Kang 
1460045e3678SYuan Kang 		desc = edesc->hw_desc;
1461045e3678SYuan Kang 
1462ce572085SHoria Geanta 		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
1463ce572085SHoria Geanta 		if (ret)
146458b0e5d0SMarkus Elfring 			goto unmap_ctx;
1465045e3678SYuan Kang 
14666e005503SSascha Hauer 		print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
1467045e3678SYuan Kang 				     DUMP_PREFIX_ADDRESS, 16, 4, desc,
1468045e3678SYuan Kang 				     desc_bytes(desc), 1);
1469045e3678SYuan Kang 
147032686d34SRussell King 		ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst, req);
147132686d34SRussell King 		if (ret)
147258b0e5d0SMarkus Elfring 			goto unmap_ctx;
147332686d34SRussell King 
1474045e3678SYuan Kang 		ret = -EINPROGRESS;
1475045e3678SYuan Kang 		state->update = ahash_update_ctx;
1476045e3678SYuan Kang 		state->finup = ahash_finup_ctx;
1477045e3678SYuan Kang 		state->final = ahash_final_ctx;
1478045e3678SYuan Kang 	} else if (*next_buflen) {
1479045e3678SYuan Kang 		state->update = ahash_update_no_ctx;
1480045e3678SYuan Kang 		state->finup = ahash_finup_no_ctx;
1481045e3678SYuan Kang 		state->final = ahash_final_no_ctx;
148246b49abcSAndrei Botila 		scatterwalk_map_and_copy(buf, req->src, 0,
1483307fd543SCristian Stoica 					 req->nbytes, 0);
148446b49abcSAndrei Botila 		*buflen = *next_buflen;
14856e005503SSascha Hauer 
148646b49abcSAndrei Botila 		print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
148746b49abcSAndrei Botila 				     DUMP_PREFIX_ADDRESS, 16, 4, buf,
148846b49abcSAndrei Botila 				     *buflen, 1);
148946b49abcSAndrei Botila 	}
1490045e3678SYuan Kang 
1491045e3678SYuan Kang 	return ret;
149258b0e5d0SMarkus Elfring  unmap_ctx:
149332686d34SRussell King 	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
149432686d34SRussell King 	kfree(edesc);
149532686d34SRussell King 	return ret;
1496045e3678SYuan Kang }
1497045e3678SYuan Kang 
1498045e3678SYuan Kang static int ahash_finup_first(struct ahash_request *req)
1499045e3678SYuan Kang {
1500045e3678SYuan Kang 	return ahash_digest(req);
1501045e3678SYuan Kang }
1502045e3678SYuan Kang 
1503045e3678SYuan Kang static int ahash_init(struct ahash_request *req)
1504045e3678SYuan Kang {
1505045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1506045e3678SYuan Kang 
1507045e3678SYuan Kang 	state->update = ahash_update_first;
1508045e3678SYuan Kang 	state->finup = ahash_finup_first;
1509045e3678SYuan Kang 	state->final = ahash_final_no_ctx;
1510045e3678SYuan Kang 
151187ec02e7SHoria Geantă 	state->ctx_dma = 0;
151265055e21SFranck LENORMAND 	state->ctx_dma_len = 0;
1513de0e35ecSHoria Geanta 	state->buf_dma = 0;
151446b49abcSAndrei Botila 	state->buflen = 0;
151546b49abcSAndrei Botila 	state->next_buflen = 0;
1516045e3678SYuan Kang 
1517045e3678SYuan Kang 	return 0;
1518045e3678SYuan Kang }
1519045e3678SYuan Kang 
1520045e3678SYuan Kang static int ahash_update(struct ahash_request *req)
1521045e3678SYuan Kang {
1522045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1523045e3678SYuan Kang 
1524045e3678SYuan Kang 	return state->update(req);
1525045e3678SYuan Kang }
1526045e3678SYuan Kang 
1527045e3678SYuan Kang static int ahash_finup(struct ahash_request *req)
1528045e3678SYuan Kang {
1529045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1530045e3678SYuan Kang 
1531045e3678SYuan Kang 	return state->finup(req);
1532045e3678SYuan Kang }
1533045e3678SYuan Kang 
1534045e3678SYuan Kang static int ahash_final(struct ahash_request *req)
1535045e3678SYuan Kang {
1536045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
1537045e3678SYuan Kang 
1538045e3678SYuan Kang 	return state->final(req);
1539045e3678SYuan Kang }
1540045e3678SYuan Kang 
1541045e3678SYuan Kang static int ahash_export(struct ahash_request *req, void *out)
1542045e3678SYuan Kang {
1543045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
15445ec90831SRussell King 	struct caam_export_state *export = out;
154546b49abcSAndrei Botila 	u8 *buf = state->buf;
154646b49abcSAndrei Botila 	int len = state->buflen;
15475ec90831SRussell King 
15485ec90831SRussell King 	memcpy(export->buf, buf, len);
15495ec90831SRussell King 	memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx));
15505ec90831SRussell King 	export->buflen = len;
15515ec90831SRussell King 	export->update = state->update;
15525ec90831SRussell King 	export->final = state->final;
15535ec90831SRussell King 	export->finup = state->finup;
1554434b4212SRussell King 
1555045e3678SYuan Kang 	return 0;
1556045e3678SYuan Kang }
1557045e3678SYuan Kang 
1558045e3678SYuan Kang static int ahash_import(struct ahash_request *req, const void *in)
1559045e3678SYuan Kang {
1560045e3678SYuan Kang 	struct caam_hash_state *state = ahash_request_ctx(req);
15615ec90831SRussell King 	const struct caam_export_state *export = in;
1562045e3678SYuan Kang 
15635ec90831SRussell King 	memset(state, 0, sizeof(*state));
156446b49abcSAndrei Botila 	memcpy(state->buf, export->buf, export->buflen);
15655ec90831SRussell King 	memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx));
156646b49abcSAndrei Botila 	state->buflen = export->buflen;
15675ec90831SRussell King 	state->update = export->update;
15685ec90831SRussell King 	state->final = export->final;
15695ec90831SRussell King 	state->finup = export->finup;
1570434b4212SRussell King 
1571045e3678SYuan Kang 	return 0;
1572045e3678SYuan Kang }
1573045e3678SYuan Kang 
1574045e3678SYuan Kang struct caam_hash_template {
1575045e3678SYuan Kang 	char name[CRYPTO_MAX_ALG_NAME];
1576045e3678SYuan Kang 	char driver_name[CRYPTO_MAX_ALG_NAME];
1577b0e09baeSYuan Kang 	char hmac_name[CRYPTO_MAX_ALG_NAME];
1578b0e09baeSYuan Kang 	char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
1579045e3678SYuan Kang 	unsigned int blocksize;
1580045e3678SYuan Kang 	struct ahash_alg template_ahash;
1581045e3678SYuan Kang 	u32 alg_type;
1582045e3678SYuan Kang };
1583045e3678SYuan Kang 
1584045e3678SYuan Kang /* ahash descriptors */
1585045e3678SYuan Kang static struct caam_hash_template driver_hash[] = {
1586045e3678SYuan Kang 	{
1587b0e09baeSYuan Kang 		.name = "sha1",
1588b0e09baeSYuan Kang 		.driver_name = "sha1-caam",
1589b0e09baeSYuan Kang 		.hmac_name = "hmac(sha1)",
1590b0e09baeSYuan Kang 		.hmac_driver_name = "hmac-sha1-caam",
1591045e3678SYuan Kang 		.blocksize = SHA1_BLOCK_SIZE,
1592045e3678SYuan Kang 		.template_ahash = {
1593045e3678SYuan Kang 			.init = ahash_init,
1594045e3678SYuan Kang 			.update = ahash_update,
1595045e3678SYuan Kang 			.final = ahash_final,
1596045e3678SYuan Kang 			.finup = ahash_finup,
1597045e3678SYuan Kang 			.digest = ahash_digest,
1598045e3678SYuan Kang 			.export = ahash_export,
1599045e3678SYuan Kang 			.import = ahash_import,
1600045e3678SYuan Kang 			.setkey = ahash_setkey,
1601045e3678SYuan Kang 			.halg = {
1602045e3678SYuan Kang 				.digestsize = SHA1_DIGEST_SIZE,
16035ec90831SRussell King 				.statesize = sizeof(struct caam_export_state),
1604045e3678SYuan Kang 			},
1605045e3678SYuan Kang 		},
1606045e3678SYuan Kang 		.alg_type = OP_ALG_ALGSEL_SHA1,
1607045e3678SYuan Kang 	}, {
1608b0e09baeSYuan Kang 		.name = "sha224",
1609b0e09baeSYuan Kang 		.driver_name = "sha224-caam",
1610b0e09baeSYuan Kang 		.hmac_name = "hmac(sha224)",
1611b0e09baeSYuan Kang 		.hmac_driver_name = "hmac-sha224-caam",
1612045e3678SYuan Kang 		.blocksize = SHA224_BLOCK_SIZE,
1613045e3678SYuan Kang 		.template_ahash = {
1614045e3678SYuan Kang 			.init = ahash_init,
1615045e3678SYuan Kang 			.update = ahash_update,
1616045e3678SYuan Kang 			.final = ahash_final,
1617045e3678SYuan Kang 			.finup = ahash_finup,
1618045e3678SYuan Kang 			.digest = ahash_digest,
1619045e3678SYuan Kang 			.export = ahash_export,
1620045e3678SYuan Kang 			.import = ahash_import,
1621045e3678SYuan Kang 			.setkey = ahash_setkey,
1622045e3678SYuan Kang 			.halg = {
1623045e3678SYuan Kang 				.digestsize = SHA224_DIGEST_SIZE,
16245ec90831SRussell King 				.statesize = sizeof(struct caam_export_state),
1625045e3678SYuan Kang 			},
1626045e3678SYuan Kang 		},
1627045e3678SYuan Kang 		.alg_type = OP_ALG_ALGSEL_SHA224,
1628045e3678SYuan Kang 	}, {
1629b0e09baeSYuan Kang 		.name = "sha256",
1630b0e09baeSYuan Kang 		.driver_name = "sha256-caam",
1631b0e09baeSYuan Kang 		.hmac_name = "hmac(sha256)",
1632b0e09baeSYuan Kang 		.hmac_driver_name = "hmac-sha256-caam",
1633045e3678SYuan Kang 		.blocksize = SHA256_BLOCK_SIZE,
1634045e3678SYuan Kang 		.template_ahash = {
1635045e3678SYuan Kang 			.init = ahash_init,
1636045e3678SYuan Kang 			.update = ahash_update,
1637045e3678SYuan Kang 			.final = ahash_final,
1638045e3678SYuan Kang 			.finup = ahash_finup,
1639045e3678SYuan Kang 			.digest = ahash_digest,
1640045e3678SYuan Kang 			.export = ahash_export,
1641045e3678SYuan Kang 			.import = ahash_import,
1642045e3678SYuan Kang 			.setkey = ahash_setkey,
1643045e3678SYuan Kang 			.halg = {
1644045e3678SYuan Kang 				.digestsize = SHA256_DIGEST_SIZE,
16455ec90831SRussell King 				.statesize = sizeof(struct caam_export_state),
1646045e3678SYuan Kang 			},
1647045e3678SYuan Kang 		},
1648045e3678SYuan Kang 		.alg_type = OP_ALG_ALGSEL_SHA256,
1649045e3678SYuan Kang 	}, {
1650b0e09baeSYuan Kang 		.name = "sha384",
1651b0e09baeSYuan Kang 		.driver_name = "sha384-caam",
1652b0e09baeSYuan Kang 		.hmac_name = "hmac(sha384)",
1653b0e09baeSYuan Kang 		.hmac_driver_name = "hmac-sha384-caam",
1654045e3678SYuan Kang 		.blocksize = SHA384_BLOCK_SIZE,
1655045e3678SYuan Kang 		.template_ahash = {
1656045e3678SYuan Kang 			.init = ahash_init,
1657045e3678SYuan Kang 			.update = ahash_update,
1658045e3678SYuan Kang 			.final = ahash_final,
1659045e3678SYuan Kang 			.finup = ahash_finup,
1660045e3678SYuan Kang 			.digest = ahash_digest,
1661045e3678SYuan Kang 			.export = ahash_export,
1662045e3678SYuan Kang 			.import = ahash_import,
1663045e3678SYuan Kang 			.setkey = ahash_setkey,
1664045e3678SYuan Kang 			.halg = {
1665045e3678SYuan Kang 				.digestsize = SHA384_DIGEST_SIZE,
16665ec90831SRussell King 				.statesize = sizeof(struct caam_export_state),
1667045e3678SYuan Kang 			},
1668045e3678SYuan Kang 		},
1669045e3678SYuan Kang 		.alg_type = OP_ALG_ALGSEL_SHA384,
1670045e3678SYuan Kang 	}, {
1671b0e09baeSYuan Kang 		.name = "sha512",
1672b0e09baeSYuan Kang 		.driver_name = "sha512-caam",
1673b0e09baeSYuan Kang 		.hmac_name = "hmac(sha512)",
1674b0e09baeSYuan Kang 		.hmac_driver_name = "hmac-sha512-caam",
1675045e3678SYuan Kang 		.blocksize = SHA512_BLOCK_SIZE,
1676045e3678SYuan Kang 		.template_ahash = {
1677045e3678SYuan Kang 			.init = ahash_init,
1678045e3678SYuan Kang 			.update = ahash_update,
1679045e3678SYuan Kang 			.final = ahash_final,
1680045e3678SYuan Kang 			.finup = ahash_finup,
1681045e3678SYuan Kang 			.digest = ahash_digest,
1682045e3678SYuan Kang 			.export = ahash_export,
1683045e3678SYuan Kang 			.import = ahash_import,
1684045e3678SYuan Kang 			.setkey = ahash_setkey,
1685045e3678SYuan Kang 			.halg = {
1686045e3678SYuan Kang 				.digestsize = SHA512_DIGEST_SIZE,
16875ec90831SRussell King 				.statesize = sizeof(struct caam_export_state),
1688045e3678SYuan Kang 			},
1689045e3678SYuan Kang 		},
1690045e3678SYuan Kang 		.alg_type = OP_ALG_ALGSEL_SHA512,
1691045e3678SYuan Kang 	}, {
1692b0e09baeSYuan Kang 		.name = "md5",
1693b0e09baeSYuan Kang 		.driver_name = "md5-caam",
1694b0e09baeSYuan Kang 		.hmac_name = "hmac(md5)",
1695b0e09baeSYuan Kang 		.hmac_driver_name = "hmac-md5-caam",
1696045e3678SYuan Kang 		.blocksize = MD5_BLOCK_WORDS * 4,
1697045e3678SYuan Kang 		.template_ahash = {
1698045e3678SYuan Kang 			.init = ahash_init,
1699045e3678SYuan Kang 			.update = ahash_update,
1700045e3678SYuan Kang 			.final = ahash_final,
1701045e3678SYuan Kang 			.finup = ahash_finup,
1702045e3678SYuan Kang 			.digest = ahash_digest,
1703045e3678SYuan Kang 			.export = ahash_export,
1704045e3678SYuan Kang 			.import = ahash_import,
1705045e3678SYuan Kang 			.setkey = ahash_setkey,
1706045e3678SYuan Kang 			.halg = {
1707045e3678SYuan Kang 				.digestsize = MD5_DIGEST_SIZE,
17085ec90831SRussell King 				.statesize = sizeof(struct caam_export_state),
1709045e3678SYuan Kang 			},
1710045e3678SYuan Kang 		},
1711045e3678SYuan Kang 		.alg_type = OP_ALG_ALGSEL_MD5,
171212b8567fSIuliana Prodan 	}, {
171312b8567fSIuliana Prodan 		.hmac_name = "xcbc(aes)",
171412b8567fSIuliana Prodan 		.hmac_driver_name = "xcbc-aes-caam",
171512b8567fSIuliana Prodan 		.blocksize = AES_BLOCK_SIZE,
171612b8567fSIuliana Prodan 		.template_ahash = {
171712b8567fSIuliana Prodan 			.init = ahash_init,
171812b8567fSIuliana Prodan 			.update = ahash_update,
171912b8567fSIuliana Prodan 			.final = ahash_final,
172012b8567fSIuliana Prodan 			.finup = ahash_finup,
172112b8567fSIuliana Prodan 			.digest = ahash_digest,
172212b8567fSIuliana Prodan 			.export = ahash_export,
172312b8567fSIuliana Prodan 			.import = ahash_import,
172412b8567fSIuliana Prodan 			.setkey = axcbc_setkey,
172512b8567fSIuliana Prodan 			.halg = {
172612b8567fSIuliana Prodan 				.digestsize = AES_BLOCK_SIZE,
172712b8567fSIuliana Prodan 				.statesize = sizeof(struct caam_export_state),
172812b8567fSIuliana Prodan 			},
172912b8567fSIuliana Prodan 		 },
173012b8567fSIuliana Prodan 		.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
173187870cfbSIuliana Prodan 	}, {
173287870cfbSIuliana Prodan 		.hmac_name = "cmac(aes)",
173387870cfbSIuliana Prodan 		.hmac_driver_name = "cmac-aes-caam",
173487870cfbSIuliana Prodan 		.blocksize = AES_BLOCK_SIZE,
173587870cfbSIuliana Prodan 		.template_ahash = {
173687870cfbSIuliana Prodan 			.init = ahash_init,
173787870cfbSIuliana Prodan 			.update = ahash_update,
173887870cfbSIuliana Prodan 			.final = ahash_final,
173987870cfbSIuliana Prodan 			.finup = ahash_finup,
174087870cfbSIuliana Prodan 			.digest = ahash_digest,
174187870cfbSIuliana Prodan 			.export = ahash_export,
174287870cfbSIuliana Prodan 			.import = ahash_import,
174387870cfbSIuliana Prodan 			.setkey = acmac_setkey,
174487870cfbSIuliana Prodan 			.halg = {
174587870cfbSIuliana Prodan 				.digestsize = AES_BLOCK_SIZE,
174687870cfbSIuliana Prodan 				.statesize = sizeof(struct caam_export_state),
174787870cfbSIuliana Prodan 			},
174887870cfbSIuliana Prodan 		 },
174987870cfbSIuliana Prodan 		.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC,
1750045e3678SYuan Kang 	},
1751045e3678SYuan Kang };
1752045e3678SYuan Kang 
1753045e3678SYuan Kang struct caam_hash_alg {
1754045e3678SYuan Kang 	struct list_head entry;
1755045e3678SYuan Kang 	int alg_type;
1756045e3678SYuan Kang 	struct ahash_alg ahash_alg;
1757045e3678SYuan Kang };
1758045e3678SYuan Kang 
1759045e3678SYuan Kang static int caam_hash_cra_init(struct crypto_tfm *tfm)
1760045e3678SYuan Kang {
1761045e3678SYuan Kang 	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
1762045e3678SYuan Kang 	struct crypto_alg *base = tfm->__crt_alg;
1763045e3678SYuan Kang 	struct hash_alg_common *halg =
1764045e3678SYuan Kang 		 container_of(base, struct hash_alg_common, base);
1765045e3678SYuan Kang 	struct ahash_alg *alg =
1766045e3678SYuan Kang 		 container_of(halg, struct ahash_alg, halg);
1767045e3678SYuan Kang 	struct caam_hash_alg *caam_hash =
1768045e3678SYuan Kang 		 container_of(alg, struct caam_hash_alg, ahash_alg);
1769045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
1770045e3678SYuan Kang 	/* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
1771045e3678SYuan Kang 	static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
1772045e3678SYuan Kang 					 HASH_MSG_LEN + SHA1_DIGEST_SIZE,
1773045e3678SYuan Kang 					 HASH_MSG_LEN + 32,
1774045e3678SYuan Kang 					 HASH_MSG_LEN + SHA256_DIGEST_SIZE,
1775045e3678SYuan Kang 					 HASH_MSG_LEN + 64,
1776045e3678SYuan Kang 					 HASH_MSG_LEN + SHA512_DIGEST_SIZE };
1777bbf22344SHoria Geantă 	dma_addr_t dma_addr;
17787e0880b9SHoria Geantă 	struct caam_drv_private *priv;
1779045e3678SYuan Kang 
1780045e3678SYuan Kang 	/*
1781cfc6f11bSRuchika Gupta 	 * Get a Job ring from Job Ring driver to ensure in-order
1782045e3678SYuan Kang 	 * crypto request processing per tfm
1783045e3678SYuan Kang 	 */
1784cfc6f11bSRuchika Gupta 	ctx->jrdev = caam_jr_alloc();
1785cfc6f11bSRuchika Gupta 	if (IS_ERR(ctx->jrdev)) {
1786cfc6f11bSRuchika Gupta 		pr_err("Job Ring Device allocation for transform failed\n");
1787cfc6f11bSRuchika Gupta 		return PTR_ERR(ctx->jrdev);
1788cfc6f11bSRuchika Gupta 	}
1789bbf22344SHoria Geantă 
17907e0880b9SHoria Geantă 	priv = dev_get_drvdata(ctx->jrdev->parent);
179112b8567fSIuliana Prodan 
179212b8567fSIuliana Prodan 	if (is_xcbc_aes(caam_hash->alg_type)) {
179312b8567fSIuliana Prodan 		ctx->dir = DMA_TO_DEVICE;
1794e9b4913aSHoria Geantă 		ctx->key_dir = DMA_BIDIRECTIONAL;
179512b8567fSIuliana Prodan 		ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
179612b8567fSIuliana Prodan 		ctx->ctx_len = 48;
1797e9b4913aSHoria Geantă 	} else if (is_cmac_aes(caam_hash->alg_type)) {
1798e9b4913aSHoria Geantă 		ctx->dir = DMA_TO_DEVICE;
1799e9b4913aSHoria Geantă 		ctx->key_dir = DMA_NONE;
1800e9b4913aSHoria Geantă 		ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
1801e9b4913aSHoria Geantă 		ctx->ctx_len = 32;
1802e9b4913aSHoria Geantă 	} else {
1803e9b4913aSHoria Geantă 		if (priv->era >= 6) {
1804e9b4913aSHoria Geantă 			ctx->dir = DMA_BIDIRECTIONAL;
1805e9b4913aSHoria Geantă 			ctx->key_dir = alg->setkey ? DMA_TO_DEVICE : DMA_NONE;
1806e9b4913aSHoria Geantă 		} else {
1807e9b4913aSHoria Geantă 			ctx->dir = DMA_TO_DEVICE;
1808e9b4913aSHoria Geantă 			ctx->key_dir = DMA_NONE;
1809e9b4913aSHoria Geantă 		}
1810e9b4913aSHoria Geantă 		ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
1811e9b4913aSHoria Geantă 		ctx->ctx_len = runninglen[(ctx->adata.algtype &
1812e9b4913aSHoria Geantă 					   OP_ALG_ALGSEL_SUBMASK) >>
1813e9b4913aSHoria Geantă 					  OP_ALG_ALGSEL_SHIFT];
1814e9b4913aSHoria Geantă 	}
181512b8567fSIuliana Prodan 
1816e9b4913aSHoria Geantă 	if (ctx->key_dir != DMA_NONE) {
1817a2fb864cSHoria Geantă 		ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key,
181812b8567fSIuliana Prodan 							  ARRAY_SIZE(ctx->key),
1819e9b4913aSHoria Geantă 							  ctx->key_dir,
182012b8567fSIuliana Prodan 							  DMA_ATTR_SKIP_CPU_SYNC);
1821a2fb864cSHoria Geantă 		if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) {
182212b8567fSIuliana Prodan 			dev_err(ctx->jrdev, "unable to map key\n");
182312b8567fSIuliana Prodan 			caam_jr_free(ctx->jrdev);
182412b8567fSIuliana Prodan 			return -ENOMEM;
182512b8567fSIuliana Prodan 		}
182612b8567fSIuliana Prodan 	}
18277e0880b9SHoria Geantă 
1828bbf22344SHoria Geantă 	dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update,
18298e731ee5SHoria Geantă 					offsetof(struct caam_hash_ctx, key),
18307e0880b9SHoria Geantă 					ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
1831bbf22344SHoria Geantă 	if (dma_mapping_error(ctx->jrdev, dma_addr)) {
1832bbf22344SHoria Geantă 		dev_err(ctx->jrdev, "unable to map shared descriptors\n");
183312b8567fSIuliana Prodan 
1834e9b4913aSHoria Geantă 		if (ctx->key_dir != DMA_NONE)
1835a2fb864cSHoria Geantă 			dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
183612b8567fSIuliana Prodan 					       ARRAY_SIZE(ctx->key),
1837e9b4913aSHoria Geantă 					       ctx->key_dir,
183812b8567fSIuliana Prodan 					       DMA_ATTR_SKIP_CPU_SYNC);
183912b8567fSIuliana Prodan 
1840bbf22344SHoria Geantă 		caam_jr_free(ctx->jrdev);
1841bbf22344SHoria Geantă 		return -ENOMEM;
1842bbf22344SHoria Geantă 	}
1843bbf22344SHoria Geantă 
1844bbf22344SHoria Geantă 	ctx->sh_desc_update_dma = dma_addr;
1845bbf22344SHoria Geantă 	ctx->sh_desc_update_first_dma = dma_addr +
1846bbf22344SHoria Geantă 					offsetof(struct caam_hash_ctx,
1847bbf22344SHoria Geantă 						 sh_desc_update_first);
1848bbf22344SHoria Geantă 	ctx->sh_desc_fin_dma = dma_addr + offsetof(struct caam_hash_ctx,
1849bbf22344SHoria Geantă 						   sh_desc_fin);
1850bbf22344SHoria Geantă 	ctx->sh_desc_digest_dma = dma_addr + offsetof(struct caam_hash_ctx,
1851bbf22344SHoria Geantă 						      sh_desc_digest);
1852bbf22344SHoria Geantă 
1853045e3678SYuan Kang 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
1854045e3678SYuan Kang 				 sizeof(struct caam_hash_state));
18559a2537d0SIuliana Prodan 
18569a2537d0SIuliana Prodan 	/*
18579a2537d0SIuliana Prodan 	 * For keyed hash algorithms shared descriptors
18589a2537d0SIuliana Prodan 	 * will be created later in setkey() callback
18599a2537d0SIuliana Prodan 	 */
18609a2537d0SIuliana Prodan 	return alg->setkey ? 0 : ahash_set_sh_desc(ahash);
1861045e3678SYuan Kang }
1862045e3678SYuan Kang 
1863045e3678SYuan Kang static void caam_hash_cra_exit(struct crypto_tfm *tfm)
1864045e3678SYuan Kang {
1865045e3678SYuan Kang 	struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
1866045e3678SYuan Kang 
1867bbf22344SHoria Geantă 	dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma,
186812b8567fSIuliana Prodan 			       offsetof(struct caam_hash_ctx, key),
18697e0880b9SHoria Geantă 			       ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
1870e9b4913aSHoria Geantă 	if (ctx->key_dir != DMA_NONE)
1871a2fb864cSHoria Geantă 		dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
1872e9b4913aSHoria Geantă 				       ARRAY_SIZE(ctx->key), ctx->key_dir,
187312b8567fSIuliana Prodan 				       DMA_ATTR_SKIP_CPU_SYNC);
1874cfc6f11bSRuchika Gupta 	caam_jr_free(ctx->jrdev);
1875045e3678SYuan Kang }
1876045e3678SYuan Kang 
18771b46c90cSHoria Geantă void caam_algapi_hash_exit(void)
1878045e3678SYuan Kang {
1879045e3678SYuan Kang 	struct caam_hash_alg *t_alg, *n;
1880045e3678SYuan Kang 
1881cfc6f11bSRuchika Gupta 	if (!hash_list.next)
1882045e3678SYuan Kang 		return;
1883045e3678SYuan Kang 
1884cfc6f11bSRuchika Gupta 	list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
1885045e3678SYuan Kang 		crypto_unregister_ahash(&t_alg->ahash_alg);
1886045e3678SYuan Kang 		list_del(&t_alg->entry);
1887045e3678SYuan Kang 		kfree(t_alg);
1888045e3678SYuan Kang 	}
1889045e3678SYuan Kang }
1890045e3678SYuan Kang 
1891045e3678SYuan Kang static struct caam_hash_alg *
1892cfc6f11bSRuchika Gupta caam_hash_alloc(struct caam_hash_template *template,
1893b0e09baeSYuan Kang 		bool keyed)
1894045e3678SYuan Kang {
1895045e3678SYuan Kang 	struct caam_hash_alg *t_alg;
1896045e3678SYuan Kang 	struct ahash_alg *halg;
1897045e3678SYuan Kang 	struct crypto_alg *alg;
1898045e3678SYuan Kang 
18999c4f9733SFabio Estevam 	t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
1900045e3678SYuan Kang 	if (!t_alg) {
1901cfc6f11bSRuchika Gupta 		pr_err("failed to allocate t_alg\n");
1902045e3678SYuan Kang 		return ERR_PTR(-ENOMEM);
1903045e3678SYuan Kang 	}
1904045e3678SYuan Kang 
1905045e3678SYuan Kang 	t_alg->ahash_alg = template->template_ahash;
1906045e3678SYuan Kang 	halg = &t_alg->ahash_alg;
1907045e3678SYuan Kang 	alg = &halg->halg.base;
1908045e3678SYuan Kang 
1909b0e09baeSYuan Kang 	if (keyed) {
1910b0e09baeSYuan Kang 		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
1911b0e09baeSYuan Kang 			 template->hmac_name);
1912b0e09baeSYuan Kang 		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
1913b0e09baeSYuan Kang 			 template->hmac_driver_name);
1914b0e09baeSYuan Kang 	} else {
1915b0e09baeSYuan Kang 		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
1916b0e09baeSYuan Kang 			 template->name);
1917045e3678SYuan Kang 		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
1918045e3678SYuan Kang 			 template->driver_name);
1919a0118c8bSRussell King 		t_alg->ahash_alg.setkey = NULL;
1920b0e09baeSYuan Kang 	}
1921045e3678SYuan Kang 	alg->cra_module = THIS_MODULE;
1922045e3678SYuan Kang 	alg->cra_init = caam_hash_cra_init;
1923045e3678SYuan Kang 	alg->cra_exit = caam_hash_cra_exit;
1924045e3678SYuan Kang 	alg->cra_ctxsize = sizeof(struct caam_hash_ctx);
1925045e3678SYuan Kang 	alg->cra_priority = CAAM_CRA_PRIORITY;
1926045e3678SYuan Kang 	alg->cra_blocksize = template->blocksize;
1927045e3678SYuan Kang 	alg->cra_alignmask = 0;
19286a38f622SEric Biggers 	alg->cra_flags = CRYPTO_ALG_ASYNC;
1929045e3678SYuan Kang 
1930045e3678SYuan Kang 	t_alg->alg_type = template->alg_type;
1931045e3678SYuan Kang 
1932045e3678SYuan Kang 	return t_alg;
1933045e3678SYuan Kang }
1934045e3678SYuan Kang 
19351b46c90cSHoria Geantă int caam_algapi_hash_init(struct device *ctrldev)
1936045e3678SYuan Kang {
1937045e3678SYuan Kang 	int i = 0, err = 0;
19381b46c90cSHoria Geantă 	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
1939bf83490eSVictoria Milhoan 	unsigned int md_limit = SHA512_DIGEST_SIZE;
1940d239b10dSHoria Geantă 	u32 md_inst, md_vid;
1941045e3678SYuan Kang 
1942bf83490eSVictoria Milhoan 	/*
1943bf83490eSVictoria Milhoan 	 * Register crypto algorithms the device supports.  First, identify
1944bf83490eSVictoria Milhoan 	 * presence and attributes of MD block.
1945bf83490eSVictoria Milhoan 	 */
1946d239b10dSHoria Geantă 	if (priv->era < 10) {
1947d239b10dSHoria Geantă 		md_vid = (rd_reg32(&priv->ctrl->perfmon.cha_id_ls) &
1948d239b10dSHoria Geantă 			  CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
1949d239b10dSHoria Geantă 		md_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) &
1950d239b10dSHoria Geantă 			   CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
1951d239b10dSHoria Geantă 	} else {
1952d239b10dSHoria Geantă 		u32 mdha = rd_reg32(&priv->ctrl->vreg.mdha);
1953d239b10dSHoria Geantă 
1954d239b10dSHoria Geantă 		md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT;
1955d239b10dSHoria Geantă 		md_inst = mdha & CHA_VER_NUM_MASK;
1956d239b10dSHoria Geantă 	}
1957bf83490eSVictoria Milhoan 
1958bf83490eSVictoria Milhoan 	/*
1959bf83490eSVictoria Milhoan 	 * Skip registration of any hashing algorithms if MD block
1960bf83490eSVictoria Milhoan 	 * is not present.
1961bf83490eSVictoria Milhoan 	 */
19621b46c90cSHoria Geantă 	if (!md_inst)
19630435d47eSIuliana Prodan 		return 0;
1964bf83490eSVictoria Milhoan 
1965bf83490eSVictoria Milhoan 	/* Limit digest size based on LP256 */
1966d239b10dSHoria Geantă 	if (md_vid == CHA_VER_VID_MD_LP256)
1967bf83490eSVictoria Milhoan 		md_limit = SHA256_DIGEST_SIZE;
1968bf83490eSVictoria Milhoan 
1969cfc6f11bSRuchika Gupta 	INIT_LIST_HEAD(&hash_list);
1970045e3678SYuan Kang 
1971045e3678SYuan Kang 	/* register crypto algorithms the device supports */
1972045e3678SYuan Kang 	for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
1973045e3678SYuan Kang 		struct caam_hash_alg *t_alg;
1974bf83490eSVictoria Milhoan 		struct caam_hash_template *alg = driver_hash + i;
1975bf83490eSVictoria Milhoan 
1976bf83490eSVictoria Milhoan 		/* If MD size is not supported by device, skip registration */
197712b8567fSIuliana Prodan 		if (is_mdha(alg->alg_type) &&
197812b8567fSIuliana Prodan 		    alg->template_ahash.halg.digestsize > md_limit)
1979bf83490eSVictoria Milhoan 			continue;
1980045e3678SYuan Kang 
1981b0e09baeSYuan Kang 		/* register hmac version */
1982bf83490eSVictoria Milhoan 		t_alg = caam_hash_alloc(alg, true);
1983b0e09baeSYuan Kang 		if (IS_ERR(t_alg)) {
1984b0e09baeSYuan Kang 			err = PTR_ERR(t_alg);
19850f103b37SIuliana Prodan 			pr_warn("%s alg allocation failed\n",
19860f103b37SIuliana Prodan 				alg->hmac_driver_name);
1987b0e09baeSYuan Kang 			continue;
1988b0e09baeSYuan Kang 		}
1989b0e09baeSYuan Kang 
1990b0e09baeSYuan Kang 		err = crypto_register_ahash(&t_alg->ahash_alg);
1991b0e09baeSYuan Kang 		if (err) {
19926ea30f0aSRussell King 			pr_warn("%s alg registration failed: %d\n",
19936ea30f0aSRussell King 				t_alg->ahash_alg.halg.base.cra_driver_name,
19946ea30f0aSRussell King 				err);
1995b0e09baeSYuan Kang 			kfree(t_alg);
1996b0e09baeSYuan Kang 		} else
1997cfc6f11bSRuchika Gupta 			list_add_tail(&t_alg->entry, &hash_list);
1998b0e09baeSYuan Kang 
199912b8567fSIuliana Prodan 		if ((alg->alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES)
200012b8567fSIuliana Prodan 			continue;
200112b8567fSIuliana Prodan 
2002b0e09baeSYuan Kang 		/* register unkeyed version */
2003bf83490eSVictoria Milhoan 		t_alg = caam_hash_alloc(alg, false);
2004045e3678SYuan Kang 		if (IS_ERR(t_alg)) {
2005045e3678SYuan Kang 			err = PTR_ERR(t_alg);
2006bf83490eSVictoria Milhoan 			pr_warn("%s alg allocation failed\n", alg->driver_name);
2007045e3678SYuan Kang 			continue;
2008045e3678SYuan Kang 		}
2009045e3678SYuan Kang 
2010045e3678SYuan Kang 		err = crypto_register_ahash(&t_alg->ahash_alg);
2011045e3678SYuan Kang 		if (err) {
20126ea30f0aSRussell King 			pr_warn("%s alg registration failed: %d\n",
20136ea30f0aSRussell King 				t_alg->ahash_alg.halg.base.cra_driver_name,
20146ea30f0aSRussell King 				err);
2015045e3678SYuan Kang 			kfree(t_alg);
2016045e3678SYuan Kang 		} else
2017cfc6f11bSRuchika Gupta 			list_add_tail(&t_alg->entry, &hash_list);
2018045e3678SYuan Kang 	}
2019045e3678SYuan Kang 
2020045e3678SYuan Kang 	return err;
2021045e3678SYuan Kang }
2022