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.
6ae1dd17dSHoria GeantA * Copyright 2018-2019, 2023 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"
684ac1a2d8SHerbert Xu #include <crypto/internal/engine.h>
69623814c0SHerbert Xu #include <crypto/internal/hash.h>
70199354d7SHerbert Xu #include <linux/dma-mapping.h>
71623814c0SHerbert Xu #include <linux/err.h>
72199354d7SHerbert Xu #include <linux/kernel.h>
73623814c0SHerbert Xu #include <linux/slab.h>
74623814c0SHerbert Xu #include <linux/string.h>
75045e3678SYuan Kang
76045e3678SYuan Kang #define CAAM_CRA_PRIORITY 3000
77045e3678SYuan Kang
78045e3678SYuan Kang /* max hash key is max split key size */
79045e3678SYuan Kang #define CAAM_MAX_HASH_KEY_SIZE (SHA512_DIGEST_SIZE * 2)
80045e3678SYuan Kang
81045e3678SYuan Kang #define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE
82045e3678SYuan Kang #define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE
83045e3678SYuan Kang
84045e3678SYuan Kang #define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \
85045e3678SYuan Kang CAAM_MAX_HASH_KEY_SIZE)
86045e3678SYuan Kang #define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ)
87045e3678SYuan Kang
88045e3678SYuan Kang /* caam context sizes for hashes: running digest + 8 */
89045e3678SYuan Kang #define HASH_MSG_LEN 8
90045e3678SYuan Kang #define MAX_CTX_LEN (HASH_MSG_LEN + SHA512_DIGEST_SIZE)
91045e3678SYuan Kang
92cfc6f11bSRuchika Gupta static struct list_head hash_list;
93cfc6f11bSRuchika Gupta
94045e3678SYuan Kang /* ahash per-session context */
95045e3678SYuan Kang struct caam_hash_ctx {
96e11793f5SRussell King u32 sh_desc_update[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
97e11793f5SRussell King u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
98e11793f5SRussell King u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
99e11793f5SRussell King u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
10012b8567fSIuliana Prodan u8 key[CAAM_MAX_HASH_KEY_SIZE] ____cacheline_aligned;
101e11793f5SRussell King dma_addr_t sh_desc_update_dma ____cacheline_aligned;
102045e3678SYuan Kang dma_addr_t sh_desc_update_first_dma;
103045e3678SYuan Kang dma_addr_t sh_desc_fin_dma;
104045e3678SYuan Kang dma_addr_t sh_desc_digest_dma;
1057e0880b9SHoria Geantă enum dma_data_direction dir;
106e9b4913aSHoria Geantă enum dma_data_direction key_dir;
107e11793f5SRussell King struct device *jrdev;
108045e3678SYuan Kang int ctx_len;
109db57656bSHoria Geantă struct alginfo adata;
110045e3678SYuan Kang };
111045e3678SYuan Kang
112045e3678SYuan Kang /* ahash state */
113045e3678SYuan Kang struct caam_hash_state {
114045e3678SYuan Kang dma_addr_t buf_dma;
115045e3678SYuan Kang dma_addr_t ctx_dma;
11665055e21SFranck LENORMAND int ctx_dma_len;
11746b49abcSAndrei Botila u8 buf[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
11846b49abcSAndrei Botila int buflen;
11946b49abcSAndrei Botila int next_buflen;
120e7472422SVictoria Milhoan u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned;
12121b014f0SIuliana Prodan int (*update)(struct ahash_request *req) ____cacheline_aligned;
122045e3678SYuan Kang int (*final)(struct ahash_request *req);
123045e3678SYuan Kang int (*finup)(struct ahash_request *req);
12421b014f0SIuliana Prodan struct ahash_edesc *edesc;
12521b014f0SIuliana Prodan void (*ahash_op_done)(struct device *jrdev, u32 *desc, u32 err,
12621b014f0SIuliana Prodan void *context);
127045e3678SYuan Kang };
128045e3678SYuan Kang
1295ec90831SRussell King struct caam_export_state {
1305ec90831SRussell King u8 buf[CAAM_MAX_HASH_BLOCK_SIZE];
1315ec90831SRussell King u8 caam_ctx[MAX_CTX_LEN];
1325ec90831SRussell King int buflen;
1335ec90831SRussell King int (*update)(struct ahash_request *req);
1345ec90831SRussell King int (*final)(struct ahash_request *req);
1355ec90831SRussell King int (*finup)(struct ahash_request *req);
1365ec90831SRussell King };
1375ec90831SRussell King
is_cmac_aes(u32 algtype)13887870cfbSIuliana Prodan static inline bool is_cmac_aes(u32 algtype)
13912b8567fSIuliana Prodan {
14012b8567fSIuliana Prodan return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) ==
14187870cfbSIuliana Prodan (OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC);
14212b8567fSIuliana Prodan }
143045e3678SYuan Kang /* Common job descriptor seq in/out ptr routines */
144045e3678SYuan Kang
145045e3678SYuan Kang /* Map state->caam_ctx, and append seq_out_ptr command that points to it */
map_seq_out_ptr_ctx(u32 * desc,struct device * jrdev,struct caam_hash_state * state,int ctx_len)146ce572085SHoria Geanta static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
147045e3678SYuan Kang struct caam_hash_state *state,
148045e3678SYuan Kang int ctx_len)
149045e3678SYuan Kang {
15065055e21SFranck LENORMAND state->ctx_dma_len = ctx_len;
151045e3678SYuan Kang state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
152045e3678SYuan Kang ctx_len, DMA_FROM_DEVICE);
153ce572085SHoria Geanta if (dma_mapping_error(jrdev, state->ctx_dma)) {
154ce572085SHoria Geanta dev_err(jrdev, "unable to map ctx\n");
15587ec02e7SHoria Geantă state->ctx_dma = 0;
156ce572085SHoria Geanta return -ENOMEM;
157ce572085SHoria Geanta }
158ce572085SHoria Geanta
159045e3678SYuan Kang append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
160ce572085SHoria Geanta
161ce572085SHoria Geanta return 0;
162045e3678SYuan Kang }
163045e3678SYuan Kang
164944c3d4dSHoria Geantă /* Map current buffer in state (if length > 0) and put it in link table */
buf_map_to_sec4_sg(struct device * jrdev,struct sec4_sg_entry * sec4_sg,struct caam_hash_state * state)165944c3d4dSHoria Geantă static inline int buf_map_to_sec4_sg(struct device *jrdev,
166045e3678SYuan Kang struct sec4_sg_entry *sec4_sg,
167944c3d4dSHoria Geantă struct caam_hash_state *state)
168045e3678SYuan Kang {
16946b49abcSAndrei Botila int buflen = state->buflen;
170045e3678SYuan Kang
171944c3d4dSHoria Geantă if (!buflen)
172944c3d4dSHoria Geantă return 0;
173045e3678SYuan Kang
17446b49abcSAndrei Botila state->buf_dma = dma_map_single(jrdev, state->buf, buflen,
175944c3d4dSHoria Geantă DMA_TO_DEVICE);
176944c3d4dSHoria Geantă if (dma_mapping_error(jrdev, state->buf_dma)) {
177944c3d4dSHoria Geantă dev_err(jrdev, "unable to map buf\n");
178944c3d4dSHoria Geantă state->buf_dma = 0;
179944c3d4dSHoria Geantă return -ENOMEM;
180045e3678SYuan Kang }
181045e3678SYuan Kang
182944c3d4dSHoria Geantă dma_to_sec4_sg_one(sec4_sg, state->buf_dma, buflen, 0);
183045e3678SYuan Kang
184944c3d4dSHoria Geantă return 0;
185045e3678SYuan Kang }
186045e3678SYuan Kang
187045e3678SYuan Kang /* Map state->caam_ctx, and add it to link table */
ctx_map_to_sec4_sg(struct device * jrdev,struct caam_hash_state * state,int ctx_len,struct sec4_sg_entry * sec4_sg,u32 flag)188dfcd8393SHoria Geantă static inline int ctx_map_to_sec4_sg(struct device *jrdev,
189ce572085SHoria Geanta struct caam_hash_state *state, int ctx_len,
190ce572085SHoria Geanta struct sec4_sg_entry *sec4_sg, u32 flag)
191045e3678SYuan Kang {
19265055e21SFranck LENORMAND state->ctx_dma_len = ctx_len;
193045e3678SYuan Kang state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
194ce572085SHoria Geanta if (dma_mapping_error(jrdev, state->ctx_dma)) {
195ce572085SHoria Geanta dev_err(jrdev, "unable to map ctx\n");
19687ec02e7SHoria Geantă state->ctx_dma = 0;
197ce572085SHoria Geanta return -ENOMEM;
198ce572085SHoria Geanta }
199ce572085SHoria Geanta
200045e3678SYuan Kang dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
201ce572085SHoria Geanta
202ce572085SHoria Geanta return 0;
203045e3678SYuan Kang }
204045e3678SYuan Kang
ahash_set_sh_desc(struct crypto_ahash * ahash)205045e3678SYuan Kang static int ahash_set_sh_desc(struct crypto_ahash *ahash)
206045e3678SYuan Kang {
2074cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
208045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
209045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
2107e0880b9SHoria Geantă struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent);
211045e3678SYuan Kang u32 *desc;
212045e3678SYuan Kang
2137e0880b9SHoria Geantă ctx->adata.key_virt = ctx->key;
2147e0880b9SHoria Geantă
215045e3678SYuan Kang /* ahash_update shared descriptor */
216045e3678SYuan Kang desc = ctx->sh_desc_update;
2170efa7579SHoria Geantă cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len,
2180efa7579SHoria Geantă ctx->ctx_len, true, ctrlpriv->era);
219bbf22344SHoria Geantă dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
2207e0880b9SHoria Geantă desc_bytes(desc), ctx->dir);
2216e005503SSascha Hauer
2226e005503SSascha Hauer print_hex_dump_debug("ahash update shdesc@"__stringify(__LINE__)": ",
2236e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
2246e005503SSascha Hauer 1);
225045e3678SYuan Kang
226045e3678SYuan Kang /* ahash_update_first shared descriptor */
227045e3678SYuan Kang desc = ctx->sh_desc_update_first;
2280efa7579SHoria Geantă cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
2290efa7579SHoria Geantă ctx->ctx_len, false, ctrlpriv->era);
230bbf22344SHoria Geantă dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
2317e0880b9SHoria Geantă desc_bytes(desc), ctx->dir);
2326e005503SSascha Hauer print_hex_dump_debug("ahash update first shdesc@"__stringify(__LINE__)
2336e005503SSascha Hauer ": ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
2346e005503SSascha Hauer desc_bytes(desc), 1);
235045e3678SYuan Kang
236045e3678SYuan Kang /* ahash_final shared descriptor */
237045e3678SYuan Kang desc = ctx->sh_desc_fin;
2380efa7579SHoria Geantă cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize,
2390efa7579SHoria Geantă ctx->ctx_len, true, ctrlpriv->era);
240bbf22344SHoria Geantă dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
2417e0880b9SHoria Geantă desc_bytes(desc), ctx->dir);
2426e005503SSascha Hauer
2436e005503SSascha Hauer print_hex_dump_debug("ahash final shdesc@"__stringify(__LINE__)": ",
244045e3678SYuan Kang DUMP_PREFIX_ADDRESS, 16, 4, desc,
245045e3678SYuan Kang desc_bytes(desc), 1);
246045e3678SYuan Kang
247045e3678SYuan Kang /* ahash_digest shared descriptor */
248045e3678SYuan Kang desc = ctx->sh_desc_digest;
2490efa7579SHoria Geantă cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize,
2500efa7579SHoria Geantă ctx->ctx_len, false, ctrlpriv->era);
251bbf22344SHoria Geantă dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
2527e0880b9SHoria Geantă desc_bytes(desc), ctx->dir);
2536e005503SSascha Hauer
2546e005503SSascha Hauer print_hex_dump_debug("ahash digest shdesc@"__stringify(__LINE__)": ",
255045e3678SYuan Kang DUMP_PREFIX_ADDRESS, 16, 4, desc,
256045e3678SYuan Kang desc_bytes(desc), 1);
257045e3678SYuan Kang
258045e3678SYuan Kang return 0;
259045e3678SYuan Kang }
260045e3678SYuan Kang
axcbc_set_sh_desc(struct crypto_ahash * ahash)26112b8567fSIuliana Prodan static int axcbc_set_sh_desc(struct crypto_ahash *ahash)
26212b8567fSIuliana Prodan {
2634cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
26412b8567fSIuliana Prodan int digestsize = crypto_ahash_digestsize(ahash);
26512b8567fSIuliana Prodan struct device *jrdev = ctx->jrdev;
26612b8567fSIuliana Prodan u32 *desc;
26712b8567fSIuliana Prodan
26812b8567fSIuliana Prodan /* shared descriptor for ahash_update */
26912b8567fSIuliana Prodan desc = ctx->sh_desc_update;
27087870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
271a2fb864cSHoria Geantă ctx->ctx_len, ctx->ctx_len);
27212b8567fSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
27312b8567fSIuliana Prodan desc_bytes(desc), ctx->dir);
27412b8567fSIuliana Prodan print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ",
27512b8567fSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
27612b8567fSIuliana Prodan 1);
27712b8567fSIuliana Prodan
27812b8567fSIuliana Prodan /* shared descriptor for ahash_{final,finup} */
27912b8567fSIuliana Prodan desc = ctx->sh_desc_fin;
28087870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
281a2fb864cSHoria Geantă digestsize, ctx->ctx_len);
28212b8567fSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
28312b8567fSIuliana Prodan desc_bytes(desc), ctx->dir);
28412b8567fSIuliana Prodan print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ",
28512b8567fSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
28612b8567fSIuliana Prodan 1);
28712b8567fSIuliana Prodan
28812b8567fSIuliana Prodan /* key is immediate data for INIT and INITFINAL states */
28912b8567fSIuliana Prodan ctx->adata.key_virt = ctx->key;
29012b8567fSIuliana Prodan
29112b8567fSIuliana Prodan /* shared descriptor for first invocation of ahash_update */
29212b8567fSIuliana Prodan desc = ctx->sh_desc_update_first;
29387870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
294a2fb864cSHoria Geantă ctx->ctx_len);
29512b8567fSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
29612b8567fSIuliana Prodan desc_bytes(desc), ctx->dir);
2976e005503SSascha Hauer print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__)
2986e005503SSascha Hauer " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
2996e005503SSascha Hauer desc_bytes(desc), 1);
30012b8567fSIuliana Prodan
30112b8567fSIuliana Prodan /* shared descriptor for ahash_digest */
30212b8567fSIuliana Prodan desc = ctx->sh_desc_digest;
30387870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
304a2fb864cSHoria Geantă digestsize, ctx->ctx_len);
30512b8567fSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
30612b8567fSIuliana Prodan desc_bytes(desc), ctx->dir);
30712b8567fSIuliana Prodan print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ",
30812b8567fSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
30912b8567fSIuliana Prodan 1);
31087870cfbSIuliana Prodan return 0;
31187870cfbSIuliana Prodan }
31287870cfbSIuliana Prodan
acmac_set_sh_desc(struct crypto_ahash * ahash)31387870cfbSIuliana Prodan static int acmac_set_sh_desc(struct crypto_ahash *ahash)
31487870cfbSIuliana Prodan {
3154cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
31687870cfbSIuliana Prodan int digestsize = crypto_ahash_digestsize(ahash);
31787870cfbSIuliana Prodan struct device *jrdev = ctx->jrdev;
31887870cfbSIuliana Prodan u32 *desc;
31987870cfbSIuliana Prodan
32087870cfbSIuliana Prodan /* shared descriptor for ahash_update */
32187870cfbSIuliana Prodan desc = ctx->sh_desc_update;
32287870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE,
323a2fb864cSHoria Geantă ctx->ctx_len, ctx->ctx_len);
32487870cfbSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma,
32587870cfbSIuliana Prodan desc_bytes(desc), ctx->dir);
32687870cfbSIuliana Prodan print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ",
32787870cfbSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, desc,
32887870cfbSIuliana Prodan desc_bytes(desc), 1);
32987870cfbSIuliana Prodan
33087870cfbSIuliana Prodan /* shared descriptor for ahash_{final,finup} */
33187870cfbSIuliana Prodan desc = ctx->sh_desc_fin;
33287870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE,
333a2fb864cSHoria Geantă digestsize, ctx->ctx_len);
33487870cfbSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
33587870cfbSIuliana Prodan desc_bytes(desc), ctx->dir);
33687870cfbSIuliana Prodan print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ",
33787870cfbSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, desc,
33887870cfbSIuliana Prodan desc_bytes(desc), 1);
33987870cfbSIuliana Prodan
34087870cfbSIuliana Prodan /* shared descriptor for first invocation of ahash_update */
34187870cfbSIuliana Prodan desc = ctx->sh_desc_update_first;
34287870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len,
343a2fb864cSHoria Geantă ctx->ctx_len);
34487870cfbSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
34587870cfbSIuliana Prodan desc_bytes(desc), ctx->dir);
3466e005503SSascha Hauer print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__)
3476e005503SSascha Hauer " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc,
34887870cfbSIuliana Prodan desc_bytes(desc), 1);
34987870cfbSIuliana Prodan
35087870cfbSIuliana Prodan /* shared descriptor for ahash_digest */
35187870cfbSIuliana Prodan desc = ctx->sh_desc_digest;
35287870cfbSIuliana Prodan cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL,
353a2fb864cSHoria Geantă digestsize, ctx->ctx_len);
35487870cfbSIuliana Prodan dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
35587870cfbSIuliana Prodan desc_bytes(desc), ctx->dir);
35687870cfbSIuliana Prodan print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ",
35787870cfbSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, desc,
35887870cfbSIuliana Prodan desc_bytes(desc), 1);
35912b8567fSIuliana Prodan
36012b8567fSIuliana Prodan return 0;
36112b8567fSIuliana Prodan }
36212b8567fSIuliana Prodan
363045e3678SYuan Kang /* Digest hash size if it is too large */
hash_digest_key(struct caam_hash_ctx * ctx,u32 * keylen,u8 * key,u32 digestsize)36430724445SHoria Geantă static int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key,
36530724445SHoria Geantă u32 digestsize)
366045e3678SYuan Kang {
367045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
368045e3678SYuan Kang u32 *desc;
369045e3678SYuan Kang struct split_key_result result;
37030724445SHoria Geantă dma_addr_t key_dma;
3719e6df0fdSMarkus Elfring int ret;
372045e3678SYuan Kang
373199354d7SHerbert Xu desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL);
3743de0152bSChristophe JAILLET if (!desc)
3752af8f4a2SKim Phillips return -ENOMEM;
376045e3678SYuan Kang
377045e3678SYuan Kang init_job_desc(desc, 0);
378045e3678SYuan Kang
37930724445SHoria Geantă key_dma = dma_map_single(jrdev, key, *keylen, DMA_BIDIRECTIONAL);
38030724445SHoria Geantă if (dma_mapping_error(jrdev, key_dma)) {
38130724445SHoria Geantă dev_err(jrdev, "unable to map key memory\n");
382045e3678SYuan Kang kfree(desc);
383045e3678SYuan Kang return -ENOMEM;
384045e3678SYuan Kang }
385045e3678SYuan Kang
386045e3678SYuan Kang /* Job descriptor to perform unkeyed hash on key_in */
387db57656bSHoria Geantă append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT |
388045e3678SYuan Kang OP_ALG_AS_INITFINAL);
38930724445SHoria Geantă append_seq_in_ptr(desc, key_dma, *keylen, 0);
390045e3678SYuan Kang append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
391045e3678SYuan Kang FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
39230724445SHoria Geantă append_seq_out_ptr(desc, key_dma, digestsize, 0);
393045e3678SYuan Kang append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
394045e3678SYuan Kang LDST_SRCDST_BYTE_CONTEXT);
395045e3678SYuan Kang
3966e005503SSascha Hauer print_hex_dump_debug("key_in@"__stringify(__LINE__)": ",
39730724445SHoria Geantă DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
3986e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
3996e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
4006e005503SSascha Hauer 1);
401045e3678SYuan Kang
402045e3678SYuan Kang result.err = 0;
403045e3678SYuan Kang init_completion(&result.completion);
404045e3678SYuan Kang
405045e3678SYuan Kang ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
4064d370a10SIuliana Prodan if (ret == -EINPROGRESS) {
407045e3678SYuan Kang /* in progress */
4087459e1d2SHoria Geantă wait_for_completion(&result.completion);
409045e3678SYuan Kang ret = result.err;
4106e005503SSascha Hauer
4116e005503SSascha Hauer print_hex_dump_debug("digested key@"__stringify(__LINE__)": ",
4126e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, key,
4136e005503SSascha Hauer digestsize, 1);
414045e3678SYuan Kang }
41530724445SHoria Geantă dma_unmap_single(jrdev, key_dma, *keylen, DMA_BIDIRECTIONAL);
416045e3678SYuan Kang
417e11aa9f1SHoria Geanta *keylen = digestsize;
418e11aa9f1SHoria Geanta
419045e3678SYuan Kang kfree(desc);
420045e3678SYuan Kang
421045e3678SYuan Kang return ret;
422045e3678SYuan Kang }
423045e3678SYuan Kang
ahash_setkey(struct crypto_ahash * ahash,const u8 * key,unsigned int keylen)424045e3678SYuan Kang static int ahash_setkey(struct crypto_ahash *ahash,
425045e3678SYuan Kang const u8 *key, unsigned int keylen)
426045e3678SYuan Kang {
4274cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
4286e005503SSascha Hauer struct device *jrdev = ctx->jrdev;
429045e3678SYuan Kang int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
430045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
4317e0880b9SHoria Geantă struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent);
4329e6df0fdSMarkus Elfring int ret;
433045e3678SYuan Kang u8 *hashed_key = NULL;
434045e3678SYuan Kang
4356e005503SSascha Hauer dev_dbg(jrdev, "keylen %d\n", keylen);
436045e3678SYuan Kang
437045e3678SYuan Kang if (keylen > blocksize) {
438199354d7SHerbert Xu unsigned int aligned_len =
439199354d7SHerbert Xu ALIGN(keylen, dma_get_cache_alignment());
440199354d7SHerbert Xu
441199354d7SHerbert Xu if (aligned_len < keylen)
442199354d7SHerbert Xu return -EOVERFLOW;
443199354d7SHerbert Xu
444199354d7SHerbert Xu hashed_key = kmemdup(key, keylen, GFP_KERNEL);
445045e3678SYuan Kang if (!hashed_key)
446045e3678SYuan Kang return -ENOMEM;
44730724445SHoria Geantă ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
448045e3678SYuan Kang if (ret)
449d6e7a7d0SMarkus Elfring goto bad_free_key;
450045e3678SYuan Kang key = hashed_key;
451045e3678SYuan Kang }
452045e3678SYuan Kang
4537e0880b9SHoria Geantă /*
4547e0880b9SHoria Geantă * If DKP is supported, use it in the shared descriptor to generate
4557e0880b9SHoria Geantă * the split key.
4567e0880b9SHoria Geantă */
4577e0880b9SHoria Geantă if (ctrlpriv->era >= 6) {
4587e0880b9SHoria Geantă ctx->adata.key_inline = true;
4597e0880b9SHoria Geantă ctx->adata.keylen = keylen;
4607e0880b9SHoria Geantă ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype &
4617e0880b9SHoria Geantă OP_ALG_ALGSEL_MASK);
4627e0880b9SHoria Geantă
4637e0880b9SHoria Geantă if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE)
464d6e7a7d0SMarkus Elfring goto bad_free_key;
465045e3678SYuan Kang
4667e0880b9SHoria Geantă memcpy(ctx->key, key, keylen);
467e9b4913aSHoria Geantă
468e9b4913aSHoria Geantă /*
469e9b4913aSHoria Geantă * In case |user key| > |derived key|, using DKP<imm,imm>
470e9b4913aSHoria Geantă * would result in invalid opcodes (last bytes of user key) in
471e9b4913aSHoria Geantă * the resulting descriptor. Use DKP<ptr,imm> instead => both
472e9b4913aSHoria Geantă * virtual and dma key addresses are needed.
473e9b4913aSHoria Geantă */
474e9b4913aSHoria Geantă if (keylen > ctx->adata.keylen_pad)
475e9b4913aSHoria Geantă dma_sync_single_for_device(ctx->jrdev,
476e9b4913aSHoria Geantă ctx->adata.key_dma,
477e9b4913aSHoria Geantă ctx->adata.keylen_pad,
478e9b4913aSHoria Geantă DMA_TO_DEVICE);
4797e0880b9SHoria Geantă } else {
4807e0880b9SHoria Geantă ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key,
4817e0880b9SHoria Geantă keylen, CAAM_MAX_HASH_KEY_SIZE);
4827e0880b9SHoria Geantă if (ret)
4837e0880b9SHoria Geantă goto bad_free_key;
4847e0880b9SHoria Geantă }
485045e3678SYuan Kang
486045e3678SYuan Kang kfree(hashed_key);
487cfb725f6SHoria Geantă return ahash_set_sh_desc(ahash);
488d6e7a7d0SMarkus Elfring bad_free_key:
489045e3678SYuan Kang kfree(hashed_key);
490045e3678SYuan Kang return -EINVAL;
491045e3678SYuan Kang }
492045e3678SYuan Kang
axcbc_setkey(struct crypto_ahash * ahash,const u8 * key,unsigned int keylen)49312b8567fSIuliana Prodan static int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key,
49412b8567fSIuliana Prodan unsigned int keylen)
49512b8567fSIuliana Prodan {
4964cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
49712b8567fSIuliana Prodan struct device *jrdev = ctx->jrdev;
49812b8567fSIuliana Prodan
499674f368aSEric Biggers if (keylen != AES_KEYSIZE_128)
500836d8f43SIuliana Prodan return -EINVAL;
501836d8f43SIuliana Prodan
50212b8567fSIuliana Prodan memcpy(ctx->key, key, keylen);
503a2fb864cSHoria Geantă dma_sync_single_for_device(jrdev, ctx->adata.key_dma, keylen,
504a2fb864cSHoria Geantă DMA_TO_DEVICE);
50512b8567fSIuliana Prodan ctx->adata.keylen = keylen;
50612b8567fSIuliana Prodan
50712b8567fSIuliana Prodan print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ",
50812b8567fSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1);
50912b8567fSIuliana Prodan
51012b8567fSIuliana Prodan return axcbc_set_sh_desc(ahash);
51112b8567fSIuliana Prodan }
51287870cfbSIuliana Prodan
acmac_setkey(struct crypto_ahash * ahash,const u8 * key,unsigned int keylen)51387870cfbSIuliana Prodan static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key,
51487870cfbSIuliana Prodan unsigned int keylen)
51587870cfbSIuliana Prodan {
5164cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
517836d8f43SIuliana Prodan int err;
518836d8f43SIuliana Prodan
519836d8f43SIuliana Prodan err = aes_check_keylen(keylen);
520674f368aSEric Biggers if (err)
521836d8f43SIuliana Prodan return err;
52287870cfbSIuliana Prodan
52387870cfbSIuliana Prodan /* key is immediate data for all cmac shared descriptors */
52487870cfbSIuliana Prodan ctx->adata.key_virt = key;
52587870cfbSIuliana Prodan ctx->adata.keylen = keylen;
52687870cfbSIuliana Prodan
52787870cfbSIuliana Prodan print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ",
52887870cfbSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
52987870cfbSIuliana Prodan
53087870cfbSIuliana Prodan return acmac_set_sh_desc(ahash);
53187870cfbSIuliana Prodan }
53287870cfbSIuliana Prodan
533045e3678SYuan Kang /*
534045e3678SYuan Kang * ahash_edesc - s/w-extended ahash descriptor
535045e3678SYuan Kang * @sec4_sg_dma: physical mapped address of h/w link table
536045e3678SYuan Kang * @src_nents: number of segments in input scatterlist
537045e3678SYuan Kang * @sec4_sg_bytes: length of dma mapped sec4_sg space
53821b014f0SIuliana Prodan * @bklog: stored to determine if the request needs backlog
539045e3678SYuan Kang * @hw_desc: the h/w job descriptor followed by any referenced link tables
540343e44b1SRussell King * @sec4_sg: h/w link table
541045e3678SYuan Kang */
542045e3678SYuan Kang struct ahash_edesc {
543045e3678SYuan Kang dma_addr_t sec4_sg_dma;
544045e3678SYuan Kang int src_nents;
545045e3678SYuan Kang int sec4_sg_bytes;
54621b014f0SIuliana Prodan bool bklog;
5471a3daadcSAndrey Smirnov u32 hw_desc[DESC_JOB_IO_LEN_MAX / sizeof(u32)] ____cacheline_aligned;
5485a8a0765SGustavo A. R. Silva struct sec4_sg_entry sec4_sg[];
549045e3678SYuan Kang };
550045e3678SYuan Kang
ahash_unmap(struct device * dev,struct ahash_edesc * edesc,struct ahash_request * req,int dst_len)551045e3678SYuan Kang static inline void ahash_unmap(struct device *dev,
552045e3678SYuan Kang struct ahash_edesc *edesc,
553045e3678SYuan Kang struct ahash_request *req, int dst_len)
554045e3678SYuan Kang {
5554cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
556944c3d4dSHoria Geantă
557045e3678SYuan Kang if (edesc->src_nents)
55813fb8fd7SLABBE Corentin dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
559045e3678SYuan Kang
560045e3678SYuan Kang if (edesc->sec4_sg_bytes)
561045e3678SYuan Kang dma_unmap_single(dev, edesc->sec4_sg_dma,
562045e3678SYuan Kang edesc->sec4_sg_bytes, DMA_TO_DEVICE);
563944c3d4dSHoria Geantă
564944c3d4dSHoria Geantă if (state->buf_dma) {
56546b49abcSAndrei Botila dma_unmap_single(dev, state->buf_dma, state->buflen,
566944c3d4dSHoria Geantă DMA_TO_DEVICE);
567944c3d4dSHoria Geantă state->buf_dma = 0;
568944c3d4dSHoria Geantă }
569045e3678SYuan Kang }
570045e3678SYuan Kang
ahash_unmap_ctx(struct device * dev,struct ahash_edesc * edesc,struct ahash_request * req,int dst_len,u32 flag)571045e3678SYuan Kang static inline void ahash_unmap_ctx(struct device *dev,
572045e3678SYuan Kang struct ahash_edesc *edesc,
573045e3678SYuan Kang struct ahash_request *req, int dst_len, u32 flag)
574045e3678SYuan Kang {
5754cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
576045e3678SYuan Kang
57787ec02e7SHoria Geantă if (state->ctx_dma) {
57865055e21SFranck LENORMAND dma_unmap_single(dev, state->ctx_dma, state->ctx_dma_len, flag);
57987ec02e7SHoria Geantă state->ctx_dma = 0;
58087ec02e7SHoria Geantă }
581045e3678SYuan Kang ahash_unmap(dev, edesc, req, dst_len);
582045e3678SYuan Kang }
583045e3678SYuan Kang
ahash_done_cpy(struct device * jrdev,u32 * desc,u32 err,void * context,enum dma_data_direction dir)584c3f7394eSIuliana Prodan static inline void ahash_done_cpy(struct device *jrdev, u32 *desc, u32 err,
585c3f7394eSIuliana Prodan void *context, enum dma_data_direction dir)
586045e3678SYuan Kang {
587045e3678SYuan Kang struct ahash_request *req = context;
58821b014f0SIuliana Prodan struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
589045e3678SYuan Kang struct ahash_edesc *edesc;
590045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
591045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
5924cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
5934cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
5941984aaeeSHoria Geantă int ecode = 0;
59563db32e6SIuliana Prodan bool has_bklog;
596045e3678SYuan Kang
5976e005503SSascha Hauer dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
598045e3678SYuan Kang
59921b014f0SIuliana Prodan edesc = state->edesc;
60063db32e6SIuliana Prodan has_bklog = edesc->bklog;
60121b014f0SIuliana Prodan
602fa9659cdSMarek Vasut if (err)
6031984aaeeSHoria Geantă ecode = caam_jr_strstatus(jrdev, err);
604045e3678SYuan Kang
605c3f7394eSIuliana Prodan ahash_unmap_ctx(jrdev, edesc, req, digestsize, dir);
606c19650d6SHoria Geantă memcpy(req->result, state->caam_ctx, digestsize);
607045e3678SYuan Kang kfree(edesc);
608045e3678SYuan Kang
6096e005503SSascha Hauer print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
610045e3678SYuan Kang DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
611045e3678SYuan Kang ctx->ctx_len, 1);
612045e3678SYuan Kang
61321b014f0SIuliana Prodan /*
61421b014f0SIuliana Prodan * If no backlog flag, the completion of the request is done
61521b014f0SIuliana Prodan * by CAAM, not crypto engine.
61621b014f0SIuliana Prodan */
61763db32e6SIuliana Prodan if (!has_bklog)
6184bc713a4SHerbert Xu ahash_request_complete(req, ecode);
61921b014f0SIuliana Prodan else
62021b014f0SIuliana Prodan crypto_finalize_hash_request(jrp->engine, req, ecode);
621045e3678SYuan Kang }
622045e3678SYuan Kang
ahash_done(struct device * jrdev,u32 * desc,u32 err,void * context)623c3f7394eSIuliana Prodan static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
624c3f7394eSIuliana Prodan void *context)
625c3f7394eSIuliana Prodan {
626c3f7394eSIuliana Prodan ahash_done_cpy(jrdev, desc, err, context, DMA_FROM_DEVICE);
627c3f7394eSIuliana Prodan }
628c3f7394eSIuliana Prodan
ahash_done_ctx_src(struct device * jrdev,u32 * desc,u32 err,void * context)629c3f7394eSIuliana Prodan static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
630c3f7394eSIuliana Prodan void *context)
631c3f7394eSIuliana Prodan {
632c3f7394eSIuliana Prodan ahash_done_cpy(jrdev, desc, err, context, DMA_BIDIRECTIONAL);
633c3f7394eSIuliana Prodan }
634c3f7394eSIuliana Prodan
ahash_done_switch(struct device * jrdev,u32 * desc,u32 err,void * context,enum dma_data_direction dir)635c3f7394eSIuliana Prodan static inline void ahash_done_switch(struct device *jrdev, u32 *desc, u32 err,
636c3f7394eSIuliana Prodan void *context, enum dma_data_direction dir)
637c3f7394eSIuliana Prodan {
638c3f7394eSIuliana Prodan struct ahash_request *req = context;
63921b014f0SIuliana Prodan struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev);
640c3f7394eSIuliana Prodan struct ahash_edesc *edesc;
641c3f7394eSIuliana Prodan struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
6424cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
6434cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
644c3f7394eSIuliana Prodan int digestsize = crypto_ahash_digestsize(ahash);
645c3f7394eSIuliana Prodan int ecode = 0;
64663db32e6SIuliana Prodan bool has_bklog;
647c3f7394eSIuliana Prodan
648c3f7394eSIuliana Prodan dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
649c3f7394eSIuliana Prodan
65021b014f0SIuliana Prodan edesc = state->edesc;
65163db32e6SIuliana Prodan has_bklog = edesc->bklog;
652c3f7394eSIuliana Prodan if (err)
653c3f7394eSIuliana Prodan ecode = caam_jr_strstatus(jrdev, err);
654c3f7394eSIuliana Prodan
655c3f7394eSIuliana Prodan ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, dir);
656c3f7394eSIuliana Prodan kfree(edesc);
657c3f7394eSIuliana Prodan
658c3f7394eSIuliana Prodan scatterwalk_map_and_copy(state->buf, req->src,
659c3f7394eSIuliana Prodan req->nbytes - state->next_buflen,
660c3f7394eSIuliana Prodan state->next_buflen, 0);
661c3f7394eSIuliana Prodan state->buflen = state->next_buflen;
662c3f7394eSIuliana Prodan
663c3f7394eSIuliana Prodan print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
664c3f7394eSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, state->buf,
665c3f7394eSIuliana Prodan state->buflen, 1);
666c3f7394eSIuliana Prodan
667c3f7394eSIuliana Prodan print_hex_dump_debug("ctx@"__stringify(__LINE__)": ",
668c3f7394eSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
669c3f7394eSIuliana Prodan ctx->ctx_len, 1);
670c3f7394eSIuliana Prodan if (req->result)
671c3f7394eSIuliana Prodan print_hex_dump_debug("result@"__stringify(__LINE__)": ",
672c3f7394eSIuliana Prodan DUMP_PREFIX_ADDRESS, 16, 4, req->result,
673c3f7394eSIuliana Prodan digestsize, 1);
674c3f7394eSIuliana Prodan
67521b014f0SIuliana Prodan /*
67621b014f0SIuliana Prodan * If no backlog flag, the completion of the request is done
67721b014f0SIuliana Prodan * by CAAM, not crypto engine.
67821b014f0SIuliana Prodan */
67963db32e6SIuliana Prodan if (!has_bklog)
6804bc713a4SHerbert Xu ahash_request_complete(req, ecode);
68121b014f0SIuliana Prodan else
68221b014f0SIuliana Prodan crypto_finalize_hash_request(jrp->engine, req, ecode);
68321b014f0SIuliana Prodan
684c3f7394eSIuliana Prodan }
685c3f7394eSIuliana Prodan
ahash_done_bi(struct device * jrdev,u32 * desc,u32 err,void * context)686045e3678SYuan Kang static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err,
687045e3678SYuan Kang void *context)
688045e3678SYuan Kang {
689c3f7394eSIuliana Prodan ahash_done_switch(jrdev, desc, err, context, DMA_BIDIRECTIONAL);
690045e3678SYuan Kang }
691045e3678SYuan Kang
ahash_done_ctx_dst(struct device * jrdev,u32 * desc,u32 err,void * context)692045e3678SYuan Kang static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
693045e3678SYuan Kang void *context)
694045e3678SYuan Kang {
695c3f7394eSIuliana Prodan ahash_done_switch(jrdev, desc, err, context, DMA_FROM_DEVICE);
696045e3678SYuan Kang }
697045e3678SYuan Kang
6985588d039SRussell King /*
6995588d039SRussell King * Allocate an enhanced descriptor, which contains the hardware descriptor
7005588d039SRussell King * and space for hardware scatter table containing sg_num entries.
7015588d039SRussell King */
ahash_edesc_alloc(struct ahash_request * req,int sg_num,u32 * sh_desc,dma_addr_t sh_desc_dma)7022ba1e798SIuliana Prodan static struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req,
70330a43b44SRussell King int sg_num, u32 *sh_desc,
7042ba1e798SIuliana Prodan dma_addr_t sh_desc_dma)
7055588d039SRussell King {
7064cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
7072ba1e798SIuliana Prodan gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
7082ba1e798SIuliana Prodan GFP_KERNEL : GFP_ATOMIC;
7095588d039SRussell King struct ahash_edesc *edesc;
7105588d039SRussell King
711*5124bc96SHerbert Xu sg_num = pad_sg_nents(sg_num);
7126df04505SChristophe JAILLET edesc = kzalloc(struct_size(edesc, sec4_sg, sg_num), flags);
7133de0152bSChristophe JAILLET if (!edesc)
7145588d039SRussell King return NULL;
7155588d039SRussell King
71621b014f0SIuliana Prodan state->edesc = edesc;
71721b014f0SIuliana Prodan
71830a43b44SRussell King init_job_desc_shared(edesc->hw_desc, sh_desc_dma, desc_len(sh_desc),
71930a43b44SRussell King HDR_SHARE_DEFER | HDR_REVERSE);
72030a43b44SRussell King
7215588d039SRussell King return edesc;
7225588d039SRussell King }
7235588d039SRussell King
ahash_edesc_add_src(struct caam_hash_ctx * ctx,struct ahash_edesc * edesc,struct ahash_request * req,int nents,unsigned int first_sg,unsigned int first_bytes,size_t to_hash)72465cf164aSRussell King static int ahash_edesc_add_src(struct caam_hash_ctx *ctx,
72565cf164aSRussell King struct ahash_edesc *edesc,
72665cf164aSRussell King struct ahash_request *req, int nents,
72765cf164aSRussell King unsigned int first_sg,
72865cf164aSRussell King unsigned int first_bytes, size_t to_hash)
72965cf164aSRussell King {
73065cf164aSRussell King dma_addr_t src_dma;
73165cf164aSRussell King u32 options;
73265cf164aSRussell King
73365cf164aSRussell King if (nents > 1 || first_sg) {
73465cf164aSRussell King struct sec4_sg_entry *sg = edesc->sec4_sg;
735a5e5c133SHoria Geantă unsigned int sgsize = sizeof(*sg) *
736a5e5c133SHoria Geantă pad_sg_nents(first_sg + nents);
73765cf164aSRussell King
738059d73eeSHoria Geantă sg_to_sec4_sg_last(req->src, to_hash, sg + first_sg, 0);
73965cf164aSRussell King
74065cf164aSRussell King src_dma = dma_map_single(ctx->jrdev, sg, sgsize, DMA_TO_DEVICE);
74165cf164aSRussell King if (dma_mapping_error(ctx->jrdev, src_dma)) {
74265cf164aSRussell King dev_err(ctx->jrdev, "unable to map S/G table\n");
74365cf164aSRussell King return -ENOMEM;
74465cf164aSRussell King }
74565cf164aSRussell King
74665cf164aSRussell King edesc->sec4_sg_bytes = sgsize;
74765cf164aSRussell King edesc->sec4_sg_dma = src_dma;
74865cf164aSRussell King options = LDST_SGF;
74965cf164aSRussell King } else {
75065cf164aSRussell King src_dma = sg_dma_address(req->src);
75165cf164aSRussell King options = 0;
75265cf164aSRussell King }
75365cf164aSRussell King
75465cf164aSRussell King append_seq_in_ptr(edesc->hw_desc, src_dma, first_bytes + to_hash,
75565cf164aSRussell King options);
75665cf164aSRussell King
75765cf164aSRussell King return 0;
75865cf164aSRussell King }
75965cf164aSRussell King
ahash_do_one_req(struct crypto_engine * engine,void * areq)76021b014f0SIuliana Prodan static int ahash_do_one_req(struct crypto_engine *engine, void *areq)
76121b014f0SIuliana Prodan {
76221b014f0SIuliana Prodan struct ahash_request *req = ahash_request_cast(areq);
7634cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(crypto_ahash_reqtfm(req));
7644cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
76521b014f0SIuliana Prodan struct device *jrdev = ctx->jrdev;
76621b014f0SIuliana Prodan u32 *desc = state->edesc->hw_desc;
76721b014f0SIuliana Prodan int ret;
76821b014f0SIuliana Prodan
76921b014f0SIuliana Prodan state->edesc->bklog = true;
77021b014f0SIuliana Prodan
77121b014f0SIuliana Prodan ret = caam_jr_enqueue(jrdev, desc, state->ahash_op_done, req);
77221b014f0SIuliana Prodan
773087e1d71SGaurav Jain if (ret == -ENOSPC && engine->retry_support)
774087e1d71SGaurav Jain return ret;
775087e1d71SGaurav Jain
77621b014f0SIuliana Prodan if (ret != -EINPROGRESS) {
77721b014f0SIuliana Prodan ahash_unmap(jrdev, state->edesc, req, 0);
77821b014f0SIuliana Prodan kfree(state->edesc);
77921b014f0SIuliana Prodan } else {
78021b014f0SIuliana Prodan ret = 0;
78121b014f0SIuliana Prodan }
78221b014f0SIuliana Prodan
78321b014f0SIuliana Prodan return ret;
78421b014f0SIuliana Prodan }
78521b014f0SIuliana Prodan
ahash_enqueue_req(struct device * jrdev,void (* cbk)(struct device * jrdev,u32 * desc,u32 err,void * context),struct ahash_request * req,int dst_len,enum dma_data_direction dir)78621b014f0SIuliana Prodan static int ahash_enqueue_req(struct device *jrdev,
78721b014f0SIuliana Prodan void (*cbk)(struct device *jrdev, u32 *desc,
78821b014f0SIuliana Prodan u32 err, void *context),
78921b014f0SIuliana Prodan struct ahash_request *req,
79021b014f0SIuliana Prodan int dst_len, enum dma_data_direction dir)
79121b014f0SIuliana Prodan {
79221b014f0SIuliana Prodan struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev);
7934cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
79421b014f0SIuliana Prodan struct ahash_edesc *edesc = state->edesc;
79521b014f0SIuliana Prodan u32 *desc = edesc->hw_desc;
79621b014f0SIuliana Prodan int ret;
79721b014f0SIuliana Prodan
79821b014f0SIuliana Prodan state->ahash_op_done = cbk;
79921b014f0SIuliana Prodan
80021b014f0SIuliana Prodan /*
80121b014f0SIuliana Prodan * Only the backlog request are sent to crypto-engine since the others
80221b014f0SIuliana Prodan * can be handled by CAAM, if free, especially since JR has up to 1024
80321b014f0SIuliana Prodan * entries (more than the 10 entries from crypto-engine).
80421b014f0SIuliana Prodan */
80521b014f0SIuliana Prodan if (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
80621b014f0SIuliana Prodan ret = crypto_transfer_hash_request_to_engine(jrpriv->engine,
80721b014f0SIuliana Prodan req);
80821b014f0SIuliana Prodan else
80921b014f0SIuliana Prodan ret = caam_jr_enqueue(jrdev, desc, cbk, req);
81021b014f0SIuliana Prodan
81121b014f0SIuliana Prodan if ((ret != -EINPROGRESS) && (ret != -EBUSY)) {
81221b014f0SIuliana Prodan ahash_unmap_ctx(jrdev, edesc, req, dst_len, dir);
81321b014f0SIuliana Prodan kfree(edesc);
81421b014f0SIuliana Prodan }
81521b014f0SIuliana Prodan
81621b014f0SIuliana Prodan return ret;
81721b014f0SIuliana Prodan }
81821b014f0SIuliana Prodan
819045e3678SYuan Kang /* submit update job descriptor */
ahash_update_ctx(struct ahash_request * req)820045e3678SYuan Kang static int ahash_update_ctx(struct ahash_request *req)
821045e3678SYuan Kang {
822045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
8234cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
8244cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
825045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
82646b49abcSAndrei Botila u8 *buf = state->buf;
82746b49abcSAndrei Botila int *buflen = &state->buflen;
82846b49abcSAndrei Botila int *next_buflen = &state->next_buflen;
82912b8567fSIuliana Prodan int blocksize = crypto_ahash_blocksize(ahash);
830045e3678SYuan Kang int in_len = *buflen + req->nbytes, to_hash;
83130a43b44SRussell King u32 *desc;
832bc13c69eSRussell King int src_nents, mapped_nents, sec4_sg_bytes, sec4_sg_src_index;
833045e3678SYuan Kang struct ahash_edesc *edesc;
834045e3678SYuan Kang int ret = 0;
835045e3678SYuan Kang
83612b8567fSIuliana Prodan *next_buflen = in_len & (blocksize - 1);
837045e3678SYuan Kang to_hash = in_len - *next_buflen;
838045e3678SYuan Kang
83912b8567fSIuliana Prodan /*
84087870cfbSIuliana Prodan * For XCBC and CMAC, if to_hash is multiple of block size,
84112b8567fSIuliana Prodan * keep last block in internal buffer
84212b8567fSIuliana Prodan */
84387870cfbSIuliana Prodan if ((is_xcbc_aes(ctx->adata.algtype) ||
84487870cfbSIuliana Prodan is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
84512b8567fSIuliana Prodan (*next_buflen == 0)) {
84612b8567fSIuliana Prodan *next_buflen = blocksize;
84712b8567fSIuliana Prodan to_hash -= blocksize;
84812b8567fSIuliana Prodan }
84912b8567fSIuliana Prodan
850045e3678SYuan Kang if (to_hash) {
851a5e5c133SHoria Geantă int pad_nents;
852059d73eeSHoria Geantă int src_len = req->nbytes - *next_buflen;
853a5e5c133SHoria Geantă
854059d73eeSHoria Geantă src_nents = sg_nents_for_len(req->src, src_len);
855f9970c28SLABBE Corentin if (src_nents < 0) {
856f9970c28SLABBE Corentin dev_err(jrdev, "Invalid number of src SG.\n");
857f9970c28SLABBE Corentin return src_nents;
858f9970c28SLABBE Corentin }
859bc13c69eSRussell King
860bc13c69eSRussell King if (src_nents) {
861bc13c69eSRussell King mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
862bc13c69eSRussell King DMA_TO_DEVICE);
863bc13c69eSRussell King if (!mapped_nents) {
864bc13c69eSRussell King dev_err(jrdev, "unable to DMA map source\n");
865bc13c69eSRussell King return -ENOMEM;
866bc13c69eSRussell King }
867bc13c69eSRussell King } else {
868bc13c69eSRussell King mapped_nents = 0;
869bc13c69eSRussell King }
870bc13c69eSRussell King
871045e3678SYuan Kang sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
872a5e5c133SHoria Geantă pad_nents = pad_sg_nents(sec4_sg_src_index + mapped_nents);
873a5e5c133SHoria Geantă sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
874045e3678SYuan Kang
875045e3678SYuan Kang /*
876045e3678SYuan Kang * allocate space for base edesc and hw desc commands,
877045e3678SYuan Kang * link tables
878045e3678SYuan Kang */
8792ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, pad_nents, ctx->sh_desc_update,
8802ba1e798SIuliana Prodan ctx->sh_desc_update_dma);
881045e3678SYuan Kang if (!edesc) {
882bc13c69eSRussell King dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
883045e3678SYuan Kang return -ENOMEM;
884045e3678SYuan Kang }
885045e3678SYuan Kang
886045e3678SYuan Kang edesc->src_nents = src_nents;
887045e3678SYuan Kang edesc->sec4_sg_bytes = sec4_sg_bytes;
888045e3678SYuan Kang
889dfcd8393SHoria Geantă ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
890045e3678SYuan Kang edesc->sec4_sg, DMA_BIDIRECTIONAL);
891ce572085SHoria Geanta if (ret)
89258b0e5d0SMarkus Elfring goto unmap_ctx;
893045e3678SYuan Kang
894944c3d4dSHoria Geantă ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
895944c3d4dSHoria Geantă if (ret)
896944c3d4dSHoria Geantă goto unmap_ctx;
897045e3678SYuan Kang
898b4e9e931SIuliana Prodan if (mapped_nents)
899059d73eeSHoria Geantă sg_to_sec4_sg_last(req->src, src_len,
900bc13c69eSRussell King edesc->sec4_sg + sec4_sg_src_index,
901bc13c69eSRussell King 0);
902b4e9e931SIuliana Prodan else
903b4e9e931SIuliana Prodan sg_to_sec4_set_last(edesc->sec4_sg + sec4_sg_src_index -
904b4e9e931SIuliana Prodan 1);
905b4e9e931SIuliana Prodan
906045e3678SYuan Kang desc = edesc->hw_desc;
907045e3678SYuan Kang
9081da2be33SRuchika Gupta edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
9091da2be33SRuchika Gupta sec4_sg_bytes,
9101da2be33SRuchika Gupta DMA_TO_DEVICE);
911ce572085SHoria Geanta if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
912ce572085SHoria Geanta dev_err(jrdev, "unable to map S/G table\n");
91332686d34SRussell King ret = -ENOMEM;
91458b0e5d0SMarkus Elfring goto unmap_ctx;
915ce572085SHoria Geanta }
9161da2be33SRuchika Gupta
917045e3678SYuan Kang append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
918045e3678SYuan Kang to_hash, LDST_SGF);
919045e3678SYuan Kang
920045e3678SYuan Kang append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0);
921045e3678SYuan Kang
9226e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
923045e3678SYuan Kang DUMP_PREFIX_ADDRESS, 16, 4, desc,
924045e3678SYuan Kang desc_bytes(desc), 1);
925045e3678SYuan Kang
92621b014f0SIuliana Prodan ret = ahash_enqueue_req(jrdev, ahash_done_bi, req,
92721b014f0SIuliana Prodan ctx->ctx_len, DMA_BIDIRECTIONAL);
928045e3678SYuan Kang } else if (*next_buflen) {
929307fd543SCristian Stoica scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
930307fd543SCristian Stoica req->nbytes, 0);
931045e3678SYuan Kang *buflen = *next_buflen;
9326e005503SSascha Hauer
9336e005503SSascha Hauer print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
93446b49abcSAndrei Botila DUMP_PREFIX_ADDRESS, 16, 4, buf,
93546b49abcSAndrei Botila *buflen, 1);
93646b49abcSAndrei Botila }
937045e3678SYuan Kang
938045e3678SYuan Kang return ret;
93958b0e5d0SMarkus Elfring unmap_ctx:
94032686d34SRussell King ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
94132686d34SRussell King kfree(edesc);
94232686d34SRussell King return ret;
943045e3678SYuan Kang }
944045e3678SYuan Kang
ahash_final_ctx(struct ahash_request * req)945045e3678SYuan Kang static int ahash_final_ctx(struct ahash_request *req)
946045e3678SYuan Kang {
947045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
9484cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
9494cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
950045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
95146b49abcSAndrei Botila int buflen = state->buflen;
95230a43b44SRussell King u32 *desc;
953a5e5c133SHoria Geantă int sec4_sg_bytes;
954045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
955045e3678SYuan Kang struct ahash_edesc *edesc;
9569e6df0fdSMarkus Elfring int ret;
957045e3678SYuan Kang
958a5e5c133SHoria Geantă sec4_sg_bytes = pad_sg_nents(1 + (buflen ? 1 : 0)) *
959a5e5c133SHoria Geantă sizeof(struct sec4_sg_entry);
960045e3678SYuan Kang
961045e3678SYuan Kang /* allocate space for base edesc and hw desc commands, link tables */
9622ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, 4, ctx->sh_desc_fin,
9632ba1e798SIuliana Prodan ctx->sh_desc_fin_dma);
9645588d039SRussell King if (!edesc)
965045e3678SYuan Kang return -ENOMEM;
966045e3678SYuan Kang
967045e3678SYuan Kang desc = edesc->hw_desc;
968045e3678SYuan Kang
969045e3678SYuan Kang edesc->sec4_sg_bytes = sec4_sg_bytes;
970045e3678SYuan Kang
971dfcd8393SHoria Geantă ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
972c19650d6SHoria Geantă edesc->sec4_sg, DMA_BIDIRECTIONAL);
973ce572085SHoria Geanta if (ret)
97458b0e5d0SMarkus Elfring goto unmap_ctx;
975045e3678SYuan Kang
976944c3d4dSHoria Geantă ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
977944c3d4dSHoria Geantă if (ret)
978944c3d4dSHoria Geantă goto unmap_ctx;
979944c3d4dSHoria Geantă
980a5e5c133SHoria Geantă sg_to_sec4_set_last(edesc->sec4_sg + (buflen ? 1 : 0));
981045e3678SYuan Kang
9821da2be33SRuchika Gupta edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
9831da2be33SRuchika Gupta sec4_sg_bytes, DMA_TO_DEVICE);
984ce572085SHoria Geanta if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
985ce572085SHoria Geanta dev_err(jrdev, "unable to map S/G table\n");
98632686d34SRussell King ret = -ENOMEM;
98758b0e5d0SMarkus Elfring goto unmap_ctx;
988ce572085SHoria Geanta }
9891da2be33SRuchika Gupta
990045e3678SYuan Kang append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
991045e3678SYuan Kang LDST_SGF);
992c19650d6SHoria Geantă append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
993045e3678SYuan Kang
9946e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
9956e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
9966e005503SSascha Hauer 1);
997045e3678SYuan Kang
99821b014f0SIuliana Prodan return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req,
99921b014f0SIuliana Prodan digestsize, DMA_BIDIRECTIONAL);
100058b0e5d0SMarkus Elfring unmap_ctx:
1001c19650d6SHoria Geantă ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
1002045e3678SYuan Kang kfree(edesc);
1003045e3678SYuan Kang return ret;
1004045e3678SYuan Kang }
1005045e3678SYuan Kang
ahash_finup_ctx(struct ahash_request * req)1006045e3678SYuan Kang static int ahash_finup_ctx(struct ahash_request *req)
1007045e3678SYuan Kang {
1008045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
10094cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
10104cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1011045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
101246b49abcSAndrei Botila int buflen = state->buflen;
101330a43b44SRussell King u32 *desc;
101465cf164aSRussell King int sec4_sg_src_index;
1015bc13c69eSRussell King int src_nents, mapped_nents;
1016045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
1017045e3678SYuan Kang struct ahash_edesc *edesc;
10189e6df0fdSMarkus Elfring int ret;
1019045e3678SYuan Kang
102013fb8fd7SLABBE Corentin src_nents = sg_nents_for_len(req->src, req->nbytes);
1021f9970c28SLABBE Corentin if (src_nents < 0) {
1022f9970c28SLABBE Corentin dev_err(jrdev, "Invalid number of src SG.\n");
1023f9970c28SLABBE Corentin return src_nents;
1024f9970c28SLABBE Corentin }
1025bc13c69eSRussell King
1026bc13c69eSRussell King if (src_nents) {
1027bc13c69eSRussell King mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1028bc13c69eSRussell King DMA_TO_DEVICE);
1029bc13c69eSRussell King if (!mapped_nents) {
1030bc13c69eSRussell King dev_err(jrdev, "unable to DMA map source\n");
1031bc13c69eSRussell King return -ENOMEM;
1032bc13c69eSRussell King }
1033bc13c69eSRussell King } else {
1034bc13c69eSRussell King mapped_nents = 0;
1035bc13c69eSRussell King }
1036bc13c69eSRussell King
1037045e3678SYuan Kang sec4_sg_src_index = 1 + (buflen ? 1 : 0);
1038045e3678SYuan Kang
1039045e3678SYuan Kang /* allocate space for base edesc and hw desc commands, link tables */
10402ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents,
10412ba1e798SIuliana Prodan ctx->sh_desc_fin, ctx->sh_desc_fin_dma);
1042045e3678SYuan Kang if (!edesc) {
1043bc13c69eSRussell King dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1044045e3678SYuan Kang return -ENOMEM;
1045045e3678SYuan Kang }
1046045e3678SYuan Kang
1047045e3678SYuan Kang desc = edesc->hw_desc;
1048045e3678SYuan Kang
1049045e3678SYuan Kang edesc->src_nents = src_nents;
1050045e3678SYuan Kang
1051dfcd8393SHoria Geantă ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len,
1052c19650d6SHoria Geantă edesc->sec4_sg, DMA_BIDIRECTIONAL);
1053ce572085SHoria Geanta if (ret)
105458b0e5d0SMarkus Elfring goto unmap_ctx;
1055045e3678SYuan Kang
1056944c3d4dSHoria Geantă ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state);
1057944c3d4dSHoria Geantă if (ret)
1058944c3d4dSHoria Geantă goto unmap_ctx;
1059045e3678SYuan Kang
106065cf164aSRussell King ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents,
106165cf164aSRussell King sec4_sg_src_index, ctx->ctx_len + buflen,
106265cf164aSRussell King req->nbytes);
106365cf164aSRussell King if (ret)
106458b0e5d0SMarkus Elfring goto unmap_ctx;
1065045e3678SYuan Kang
1066c19650d6SHoria Geantă append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0);
1067045e3678SYuan Kang
10686e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
10696e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
10706e005503SSascha Hauer 1);
1071045e3678SYuan Kang
107221b014f0SIuliana Prodan return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req,
107321b014f0SIuliana Prodan digestsize, DMA_BIDIRECTIONAL);
107458b0e5d0SMarkus Elfring unmap_ctx:
1075c19650d6SHoria Geantă ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL);
1076045e3678SYuan Kang kfree(edesc);
1077045e3678SYuan Kang return ret;
1078045e3678SYuan Kang }
1079045e3678SYuan Kang
ahash_digest(struct ahash_request * req)1080045e3678SYuan Kang static int ahash_digest(struct ahash_request *req)
1081045e3678SYuan Kang {
1082045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
10834cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
10844cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1085045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
108630a43b44SRussell King u32 *desc;
1087045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
108865cf164aSRussell King int src_nents, mapped_nents;
1089045e3678SYuan Kang struct ahash_edesc *edesc;
10909e6df0fdSMarkus Elfring int ret;
1091045e3678SYuan Kang
1092944c3d4dSHoria Geantă state->buf_dma = 0;
1093944c3d4dSHoria Geantă
10943d5a2db6SRussell King src_nents = sg_nents_for_len(req->src, req->nbytes);
1095f9970c28SLABBE Corentin if (src_nents < 0) {
1096f9970c28SLABBE Corentin dev_err(jrdev, "Invalid number of src SG.\n");
1097f9970c28SLABBE Corentin return src_nents;
1098f9970c28SLABBE Corentin }
1099bc13c69eSRussell King
1100bc13c69eSRussell King if (src_nents) {
1101bc13c69eSRussell King mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1102bc13c69eSRussell King DMA_TO_DEVICE);
1103bc13c69eSRussell King if (!mapped_nents) {
1104bc13c69eSRussell King dev_err(jrdev, "unable to map source for DMA\n");
1105bc13c69eSRussell King return -ENOMEM;
1106bc13c69eSRussell King }
1107bc13c69eSRussell King } else {
1108bc13c69eSRussell King mapped_nents = 0;
1109bc13c69eSRussell King }
1110bc13c69eSRussell King
1111045e3678SYuan Kang /* allocate space for base edesc and hw desc commands, link tables */
11122ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, mapped_nents > 1 ? mapped_nents : 0,
11132ba1e798SIuliana Prodan ctx->sh_desc_digest, ctx->sh_desc_digest_dma);
1114045e3678SYuan Kang if (!edesc) {
1115bc13c69eSRussell King dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1116045e3678SYuan Kang return -ENOMEM;
1117045e3678SYuan Kang }
1118343e44b1SRussell King
1119045e3678SYuan Kang edesc->src_nents = src_nents;
1120045e3678SYuan Kang
112165cf164aSRussell King ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
112265cf164aSRussell King req->nbytes);
112365cf164aSRussell King if (ret) {
112432686d34SRussell King ahash_unmap(jrdev, edesc, req, digestsize);
112532686d34SRussell King kfree(edesc);
112665cf164aSRussell King return ret;
1127ce572085SHoria Geanta }
112865cf164aSRussell King
112965cf164aSRussell King desc = edesc->hw_desc;
1130045e3678SYuan Kang
1131c19650d6SHoria Geantă ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1132c19650d6SHoria Geantă if (ret) {
113332686d34SRussell King ahash_unmap(jrdev, edesc, req, digestsize);
113432686d34SRussell King kfree(edesc);
1135ce572085SHoria Geanta return -ENOMEM;
1136ce572085SHoria Geanta }
1137045e3678SYuan Kang
11386e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
11396e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
11406e005503SSascha Hauer 1);
1141045e3678SYuan Kang
114221b014f0SIuliana Prodan return ahash_enqueue_req(jrdev, ahash_done, req, digestsize,
114321b014f0SIuliana Prodan DMA_FROM_DEVICE);
1144045e3678SYuan Kang }
1145045e3678SYuan Kang
1146045e3678SYuan Kang /* submit ahash final if it the first job descriptor */
ahash_final_no_ctx(struct ahash_request * req)1147045e3678SYuan Kang static int ahash_final_no_ctx(struct ahash_request *req)
1148045e3678SYuan Kang {
1149045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
11504cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
11514cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1152045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
115346b49abcSAndrei Botila u8 *buf = state->buf;
115446b49abcSAndrei Botila int buflen = state->buflen;
115530a43b44SRussell King u32 *desc;
1156045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
1157045e3678SYuan Kang struct ahash_edesc *edesc;
11589e6df0fdSMarkus Elfring int ret;
1159045e3678SYuan Kang
1160045e3678SYuan Kang /* allocate space for base edesc and hw desc commands, link tables */
11612ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, 0, ctx->sh_desc_digest,
11622ba1e798SIuliana Prodan ctx->sh_desc_digest_dma);
11635588d039SRussell King if (!edesc)
1164045e3678SYuan Kang return -ENOMEM;
1165045e3678SYuan Kang
1166045e3678SYuan Kang desc = edesc->hw_desc;
1167045e3678SYuan Kang
116804e6d25cSAymen Sghaier if (buflen) {
116904e6d25cSAymen Sghaier state->buf_dma = dma_map_single(jrdev, buf, buflen,
117004e6d25cSAymen Sghaier DMA_TO_DEVICE);
1171ce572085SHoria Geanta if (dma_mapping_error(jrdev, state->buf_dma)) {
1172ce572085SHoria Geanta dev_err(jrdev, "unable to map src\n");
117306435f34SMarkus Elfring goto unmap;
1174ce572085SHoria Geanta }
1175045e3678SYuan Kang
1176045e3678SYuan Kang append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
117704e6d25cSAymen Sghaier }
1178045e3678SYuan Kang
1179c19650d6SHoria Geantă ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1180c19650d6SHoria Geantă if (ret)
118106435f34SMarkus Elfring goto unmap;
1182045e3678SYuan Kang
11836e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
11846e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
11856e005503SSascha Hauer 1);
1186045e3678SYuan Kang
118721b014f0SIuliana Prodan return ahash_enqueue_req(jrdev, ahash_done, req,
118821b014f0SIuliana Prodan digestsize, DMA_FROM_DEVICE);
118906435f34SMarkus Elfring unmap:
119006435f34SMarkus Elfring ahash_unmap(jrdev, edesc, req, digestsize);
119106435f34SMarkus Elfring kfree(edesc);
119206435f34SMarkus Elfring return -ENOMEM;
1193045e3678SYuan Kang }
1194045e3678SYuan Kang
1195045e3678SYuan Kang /* submit ahash update if it the first job descriptor after update */
ahash_update_no_ctx(struct ahash_request * req)1196045e3678SYuan Kang static int ahash_update_no_ctx(struct ahash_request *req)
1197045e3678SYuan Kang {
1198045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
11994cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
12004cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1201045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
120246b49abcSAndrei Botila u8 *buf = state->buf;
120346b49abcSAndrei Botila int *buflen = &state->buflen;
120446b49abcSAndrei Botila int *next_buflen = &state->next_buflen;
120512b8567fSIuliana Prodan int blocksize = crypto_ahash_blocksize(ahash);
1206045e3678SYuan Kang int in_len = *buflen + req->nbytes, to_hash;
1207bc13c69eSRussell King int sec4_sg_bytes, src_nents, mapped_nents;
1208045e3678SYuan Kang struct ahash_edesc *edesc;
120930a43b44SRussell King u32 *desc;
1210045e3678SYuan Kang int ret = 0;
1211045e3678SYuan Kang
121212b8567fSIuliana Prodan *next_buflen = in_len & (blocksize - 1);
1213045e3678SYuan Kang to_hash = in_len - *next_buflen;
1214045e3678SYuan Kang
121512b8567fSIuliana Prodan /*
121687870cfbSIuliana Prodan * For XCBC and CMAC, if to_hash is multiple of block size,
121712b8567fSIuliana Prodan * keep last block in internal buffer
121812b8567fSIuliana Prodan */
121987870cfbSIuliana Prodan if ((is_xcbc_aes(ctx->adata.algtype) ||
122087870cfbSIuliana Prodan is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
122112b8567fSIuliana Prodan (*next_buflen == 0)) {
122212b8567fSIuliana Prodan *next_buflen = blocksize;
122312b8567fSIuliana Prodan to_hash -= blocksize;
122412b8567fSIuliana Prodan }
122512b8567fSIuliana Prodan
1226045e3678SYuan Kang if (to_hash) {
1227a5e5c133SHoria Geantă int pad_nents;
1228059d73eeSHoria Geantă int src_len = req->nbytes - *next_buflen;
1229a5e5c133SHoria Geantă
1230059d73eeSHoria Geantă src_nents = sg_nents_for_len(req->src, src_len);
1231f9970c28SLABBE Corentin if (src_nents < 0) {
1232f9970c28SLABBE Corentin dev_err(jrdev, "Invalid number of src SG.\n");
1233f9970c28SLABBE Corentin return src_nents;
1234f9970c28SLABBE Corentin }
1235bc13c69eSRussell King
1236bc13c69eSRussell King if (src_nents) {
1237bc13c69eSRussell King mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1238bc13c69eSRussell King DMA_TO_DEVICE);
1239bc13c69eSRussell King if (!mapped_nents) {
1240bc13c69eSRussell King dev_err(jrdev, "unable to DMA map source\n");
1241bc13c69eSRussell King return -ENOMEM;
1242bc13c69eSRussell King }
1243bc13c69eSRussell King } else {
1244bc13c69eSRussell King mapped_nents = 0;
1245bc13c69eSRussell King }
1246bc13c69eSRussell King
1247a5e5c133SHoria Geantă pad_nents = pad_sg_nents(1 + mapped_nents);
1248a5e5c133SHoria Geantă sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry);
1249045e3678SYuan Kang
1250045e3678SYuan Kang /*
1251045e3678SYuan Kang * allocate space for base edesc and hw desc commands,
1252045e3678SYuan Kang * link tables
1253045e3678SYuan Kang */
12542ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, pad_nents,
125530a43b44SRussell King ctx->sh_desc_update_first,
12562ba1e798SIuliana Prodan ctx->sh_desc_update_first_dma);
1257045e3678SYuan Kang if (!edesc) {
1258bc13c69eSRussell King dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1259045e3678SYuan Kang return -ENOMEM;
1260045e3678SYuan Kang }
1261045e3678SYuan Kang
1262045e3678SYuan Kang edesc->src_nents = src_nents;
1263045e3678SYuan Kang edesc->sec4_sg_bytes = sec4_sg_bytes;
1264045e3678SYuan Kang
1265944c3d4dSHoria Geantă ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
1266944c3d4dSHoria Geantă if (ret)
1267944c3d4dSHoria Geantă goto unmap_ctx;
1268944c3d4dSHoria Geantă
1269059d73eeSHoria Geantă sg_to_sec4_sg_last(req->src, src_len, edesc->sec4_sg + 1, 0);
1270bc13c69eSRussell King
1271045e3678SYuan Kang desc = edesc->hw_desc;
1272045e3678SYuan Kang
12731da2be33SRuchika Gupta edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
12741da2be33SRuchika Gupta sec4_sg_bytes,
12751da2be33SRuchika Gupta DMA_TO_DEVICE);
1276ce572085SHoria Geanta if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
1277ce572085SHoria Geanta dev_err(jrdev, "unable to map S/G table\n");
127832686d34SRussell King ret = -ENOMEM;
127958b0e5d0SMarkus Elfring goto unmap_ctx;
1280ce572085SHoria Geanta }
12811da2be33SRuchika Gupta
1282045e3678SYuan Kang append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
1283045e3678SYuan Kang
1284ce572085SHoria Geanta ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
1285ce572085SHoria Geanta if (ret)
128658b0e5d0SMarkus Elfring goto unmap_ctx;
1287045e3678SYuan Kang
12886e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
1289045e3678SYuan Kang DUMP_PREFIX_ADDRESS, 16, 4, desc,
1290045e3678SYuan Kang desc_bytes(desc), 1);
1291045e3678SYuan Kang
129221b014f0SIuliana Prodan ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req,
129321b014f0SIuliana Prodan ctx->ctx_len, DMA_TO_DEVICE);
129421b014f0SIuliana Prodan if ((ret != -EINPROGRESS) && (ret != -EBUSY))
129521b014f0SIuliana Prodan return ret;
1296045e3678SYuan Kang state->update = ahash_update_ctx;
1297045e3678SYuan Kang state->finup = ahash_finup_ctx;
1298045e3678SYuan Kang state->final = ahash_final_ctx;
1299045e3678SYuan Kang } else if (*next_buflen) {
1300307fd543SCristian Stoica scatterwalk_map_and_copy(buf + *buflen, req->src, 0,
1301307fd543SCristian Stoica req->nbytes, 0);
1302045e3678SYuan Kang *buflen = *next_buflen;
13036e005503SSascha Hauer
13046e005503SSascha Hauer print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
130546b49abcSAndrei Botila DUMP_PREFIX_ADDRESS, 16, 4, buf,
130646b49abcSAndrei Botila *buflen, 1);
130746b49abcSAndrei Botila }
1308045e3678SYuan Kang
1309045e3678SYuan Kang return ret;
131058b0e5d0SMarkus Elfring unmap_ctx:
131132686d34SRussell King ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
131232686d34SRussell King kfree(edesc);
131332686d34SRussell King return ret;
1314045e3678SYuan Kang }
1315045e3678SYuan Kang
1316045e3678SYuan Kang /* submit ahash finup if it the first job descriptor after update */
ahash_finup_no_ctx(struct ahash_request * req)1317045e3678SYuan Kang static int ahash_finup_no_ctx(struct ahash_request *req)
1318045e3678SYuan Kang {
1319045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
13204cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
13214cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1322045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
132346b49abcSAndrei Botila int buflen = state->buflen;
132430a43b44SRussell King u32 *desc;
1325bc13c69eSRussell King int sec4_sg_bytes, sec4_sg_src_index, src_nents, mapped_nents;
1326045e3678SYuan Kang int digestsize = crypto_ahash_digestsize(ahash);
1327045e3678SYuan Kang struct ahash_edesc *edesc;
13289e6df0fdSMarkus Elfring int ret;
1329045e3678SYuan Kang
133013fb8fd7SLABBE Corentin src_nents = sg_nents_for_len(req->src, req->nbytes);
1331f9970c28SLABBE Corentin if (src_nents < 0) {
1332f9970c28SLABBE Corentin dev_err(jrdev, "Invalid number of src SG.\n");
1333f9970c28SLABBE Corentin return src_nents;
1334f9970c28SLABBE Corentin }
1335bc13c69eSRussell King
1336bc13c69eSRussell King if (src_nents) {
1337bc13c69eSRussell King mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1338bc13c69eSRussell King DMA_TO_DEVICE);
1339bc13c69eSRussell King if (!mapped_nents) {
1340bc13c69eSRussell King dev_err(jrdev, "unable to DMA map source\n");
1341bc13c69eSRussell King return -ENOMEM;
1342bc13c69eSRussell King }
1343bc13c69eSRussell King } else {
1344bc13c69eSRussell King mapped_nents = 0;
1345bc13c69eSRussell King }
1346bc13c69eSRussell King
1347045e3678SYuan Kang sec4_sg_src_index = 2;
1348bc13c69eSRussell King sec4_sg_bytes = (sec4_sg_src_index + mapped_nents) *
1349045e3678SYuan Kang sizeof(struct sec4_sg_entry);
1350045e3678SYuan Kang
1351045e3678SYuan Kang /* allocate space for base edesc and hw desc commands, link tables */
13522ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents,
13532ba1e798SIuliana Prodan ctx->sh_desc_digest, ctx->sh_desc_digest_dma);
1354045e3678SYuan Kang if (!edesc) {
1355bc13c69eSRussell King dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1356045e3678SYuan Kang return -ENOMEM;
1357045e3678SYuan Kang }
1358045e3678SYuan Kang
1359045e3678SYuan Kang desc = edesc->hw_desc;
1360045e3678SYuan Kang
1361045e3678SYuan Kang edesc->src_nents = src_nents;
1362045e3678SYuan Kang edesc->sec4_sg_bytes = sec4_sg_bytes;
1363045e3678SYuan Kang
1364944c3d4dSHoria Geantă ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state);
1365944c3d4dSHoria Geantă if (ret)
1366944c3d4dSHoria Geantă goto unmap;
1367045e3678SYuan Kang
136865cf164aSRussell King ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 1, buflen,
136965cf164aSRussell King req->nbytes);
137065cf164aSRussell King if (ret) {
1371ce572085SHoria Geanta dev_err(jrdev, "unable to map S/G table\n");
137206435f34SMarkus Elfring goto unmap;
1373ce572085SHoria Geanta }
13741da2be33SRuchika Gupta
1375c19650d6SHoria Geantă ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize);
1376c19650d6SHoria Geantă if (ret)
137706435f34SMarkus Elfring goto unmap;
1378045e3678SYuan Kang
13796e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
13806e005503SSascha Hauer DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
13816e005503SSascha Hauer 1);
1382045e3678SYuan Kang
138321b014f0SIuliana Prodan return ahash_enqueue_req(jrdev, ahash_done, req,
138421b014f0SIuliana Prodan digestsize, DMA_FROM_DEVICE);
138506435f34SMarkus Elfring unmap:
138606435f34SMarkus Elfring ahash_unmap(jrdev, edesc, req, digestsize);
138706435f34SMarkus Elfring kfree(edesc);
138806435f34SMarkus Elfring return -ENOMEM;
138906435f34SMarkus Elfring
1390045e3678SYuan Kang }
1391045e3678SYuan Kang
1392045e3678SYuan Kang /* submit first update job descriptor after init */
ahash_update_first(struct ahash_request * req)1393045e3678SYuan Kang static int ahash_update_first(struct ahash_request *req)
1394045e3678SYuan Kang {
1395045e3678SYuan Kang struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
13964cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
13974cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1398045e3678SYuan Kang struct device *jrdev = ctx->jrdev;
139946b49abcSAndrei Botila u8 *buf = state->buf;
140046b49abcSAndrei Botila int *buflen = &state->buflen;
140146b49abcSAndrei Botila int *next_buflen = &state->next_buflen;
1402045e3678SYuan Kang int to_hash;
140312b8567fSIuliana Prodan int blocksize = crypto_ahash_blocksize(ahash);
140430a43b44SRussell King u32 *desc;
140565cf164aSRussell King int src_nents, mapped_nents;
1406045e3678SYuan Kang struct ahash_edesc *edesc;
1407045e3678SYuan Kang int ret = 0;
1408045e3678SYuan Kang
140912b8567fSIuliana Prodan *next_buflen = req->nbytes & (blocksize - 1);
1410045e3678SYuan Kang to_hash = req->nbytes - *next_buflen;
1411045e3678SYuan Kang
141212b8567fSIuliana Prodan /*
141387870cfbSIuliana Prodan * For XCBC and CMAC, if to_hash is multiple of block size,
141412b8567fSIuliana Prodan * keep last block in internal buffer
141512b8567fSIuliana Prodan */
141687870cfbSIuliana Prodan if ((is_xcbc_aes(ctx->adata.algtype) ||
141787870cfbSIuliana Prodan is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize &&
141812b8567fSIuliana Prodan (*next_buflen == 0)) {
141912b8567fSIuliana Prodan *next_buflen = blocksize;
142012b8567fSIuliana Prodan to_hash -= blocksize;
142112b8567fSIuliana Prodan }
142212b8567fSIuliana Prodan
1423045e3678SYuan Kang if (to_hash) {
14243d5a2db6SRussell King src_nents = sg_nents_for_len(req->src,
14253d5a2db6SRussell King req->nbytes - *next_buflen);
1426f9970c28SLABBE Corentin if (src_nents < 0) {
1427f9970c28SLABBE Corentin dev_err(jrdev, "Invalid number of src SG.\n");
1428f9970c28SLABBE Corentin return src_nents;
1429f9970c28SLABBE Corentin }
1430bc13c69eSRussell King
1431bc13c69eSRussell King if (src_nents) {
1432bc13c69eSRussell King mapped_nents = dma_map_sg(jrdev, req->src, src_nents,
1433bc13c69eSRussell King DMA_TO_DEVICE);
1434bc13c69eSRussell King if (!mapped_nents) {
1435bc13c69eSRussell King dev_err(jrdev, "unable to map source for DMA\n");
1436bc13c69eSRussell King return -ENOMEM;
1437bc13c69eSRussell King }
1438bc13c69eSRussell King } else {
1439bc13c69eSRussell King mapped_nents = 0;
1440bc13c69eSRussell King }
1441045e3678SYuan Kang
1442045e3678SYuan Kang /*
1443045e3678SYuan Kang * allocate space for base edesc and hw desc commands,
1444045e3678SYuan Kang * link tables
1445045e3678SYuan Kang */
14462ba1e798SIuliana Prodan edesc = ahash_edesc_alloc(req, mapped_nents > 1 ?
144730a43b44SRussell King mapped_nents : 0,
144830a43b44SRussell King ctx->sh_desc_update_first,
14492ba1e798SIuliana Prodan ctx->sh_desc_update_first_dma);
1450045e3678SYuan Kang if (!edesc) {
1451bc13c69eSRussell King dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
1452045e3678SYuan Kang return -ENOMEM;
1453045e3678SYuan Kang }
1454045e3678SYuan Kang
1455045e3678SYuan Kang edesc->src_nents = src_nents;
1456045e3678SYuan Kang
145765cf164aSRussell King ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0,
145865cf164aSRussell King to_hash);
145965cf164aSRussell King if (ret)
146058b0e5d0SMarkus Elfring goto unmap_ctx;
1461045e3678SYuan Kang
1462045e3678SYuan Kang desc = edesc->hw_desc;
1463045e3678SYuan Kang
1464ce572085SHoria Geanta ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
1465ce572085SHoria Geanta if (ret)
146658b0e5d0SMarkus Elfring goto unmap_ctx;
1467045e3678SYuan Kang
14686e005503SSascha Hauer print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
1469045e3678SYuan Kang DUMP_PREFIX_ADDRESS, 16, 4, desc,
1470045e3678SYuan Kang desc_bytes(desc), 1);
1471045e3678SYuan Kang
147221b014f0SIuliana Prodan ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req,
147321b014f0SIuliana Prodan ctx->ctx_len, DMA_TO_DEVICE);
147421b014f0SIuliana Prodan if ((ret != -EINPROGRESS) && (ret != -EBUSY))
147521b014f0SIuliana Prodan return ret;
1476045e3678SYuan Kang state->update = ahash_update_ctx;
1477045e3678SYuan Kang state->finup = ahash_finup_ctx;
1478045e3678SYuan Kang state->final = ahash_final_ctx;
1479045e3678SYuan Kang } else if (*next_buflen) {
1480045e3678SYuan Kang state->update = ahash_update_no_ctx;
1481045e3678SYuan Kang state->finup = ahash_finup_no_ctx;
1482045e3678SYuan Kang state->final = ahash_final_no_ctx;
148346b49abcSAndrei Botila scatterwalk_map_and_copy(buf, req->src, 0,
1484307fd543SCristian Stoica req->nbytes, 0);
148546b49abcSAndrei Botila *buflen = *next_buflen;
14866e005503SSascha Hauer
148746b49abcSAndrei Botila print_hex_dump_debug("buf@" __stringify(__LINE__)": ",
148846b49abcSAndrei Botila DUMP_PREFIX_ADDRESS, 16, 4, buf,
148946b49abcSAndrei Botila *buflen, 1);
149046b49abcSAndrei Botila }
1491045e3678SYuan Kang
1492045e3678SYuan Kang return ret;
149358b0e5d0SMarkus Elfring unmap_ctx:
149432686d34SRussell King ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
149532686d34SRussell King kfree(edesc);
149632686d34SRussell King return ret;
1497045e3678SYuan Kang }
1498045e3678SYuan Kang
ahash_finup_first(struct ahash_request * req)1499045e3678SYuan Kang static int ahash_finup_first(struct ahash_request *req)
1500045e3678SYuan Kang {
1501045e3678SYuan Kang return ahash_digest(req);
1502045e3678SYuan Kang }
1503045e3678SYuan Kang
ahash_init(struct ahash_request * req)1504045e3678SYuan Kang static int ahash_init(struct ahash_request *req)
1505045e3678SYuan Kang {
15064cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1507045e3678SYuan Kang
1508045e3678SYuan Kang state->update = ahash_update_first;
1509045e3678SYuan Kang state->finup = ahash_finup_first;
1510045e3678SYuan Kang state->final = ahash_final_no_ctx;
1511045e3678SYuan Kang
151287ec02e7SHoria Geantă state->ctx_dma = 0;
151365055e21SFranck LENORMAND state->ctx_dma_len = 0;
1514de0e35ecSHoria Geanta state->buf_dma = 0;
151546b49abcSAndrei Botila state->buflen = 0;
151646b49abcSAndrei Botila state->next_buflen = 0;
1517045e3678SYuan Kang
1518045e3678SYuan Kang return 0;
1519045e3678SYuan Kang }
1520045e3678SYuan Kang
ahash_update(struct ahash_request * req)1521045e3678SYuan Kang static int ahash_update(struct ahash_request *req)
1522045e3678SYuan Kang {
15234cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1524045e3678SYuan Kang
1525045e3678SYuan Kang return state->update(req);
1526045e3678SYuan Kang }
1527045e3678SYuan Kang
ahash_finup(struct ahash_request * req)1528045e3678SYuan Kang static int ahash_finup(struct ahash_request *req)
1529045e3678SYuan Kang {
15304cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1531045e3678SYuan Kang
1532045e3678SYuan Kang return state->finup(req);
1533045e3678SYuan Kang }
1534045e3678SYuan Kang
ahash_final(struct ahash_request * req)1535045e3678SYuan Kang static int ahash_final(struct ahash_request *req)
1536045e3678SYuan Kang {
15374cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
1538045e3678SYuan Kang
1539045e3678SYuan Kang return state->final(req);
1540045e3678SYuan Kang }
1541045e3678SYuan Kang
ahash_export(struct ahash_request * req,void * out)1542045e3678SYuan Kang static int ahash_export(struct ahash_request *req, void *out)
1543045e3678SYuan Kang {
15444cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
15455ec90831SRussell King struct caam_export_state *export = out;
154646b49abcSAndrei Botila u8 *buf = state->buf;
154746b49abcSAndrei Botila int len = state->buflen;
15485ec90831SRussell King
15495ec90831SRussell King memcpy(export->buf, buf, len);
15505ec90831SRussell King memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx));
15515ec90831SRussell King export->buflen = len;
15525ec90831SRussell King export->update = state->update;
15535ec90831SRussell King export->final = state->final;
15545ec90831SRussell King export->finup = state->finup;
1555434b4212SRussell King
1556045e3678SYuan Kang return 0;
1557045e3678SYuan Kang }
1558045e3678SYuan Kang
ahash_import(struct ahash_request * req,const void * in)1559045e3678SYuan Kang static int ahash_import(struct ahash_request *req, const void *in)
1560045e3678SYuan Kang {
15614cb4f7c1SHerbert Xu struct caam_hash_state *state = ahash_request_ctx_dma(req);
15625ec90831SRussell King const struct caam_export_state *export = in;
1563045e3678SYuan Kang
15645ec90831SRussell King memset(state, 0, sizeof(*state));
156546b49abcSAndrei Botila memcpy(state->buf, export->buf, export->buflen);
15665ec90831SRussell King memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx));
156746b49abcSAndrei Botila state->buflen = export->buflen;
15685ec90831SRussell King state->update = export->update;
15695ec90831SRussell King state->final = export->final;
15705ec90831SRussell King state->finup = export->finup;
1571434b4212SRussell King
1572045e3678SYuan Kang return 0;
1573045e3678SYuan Kang }
1574045e3678SYuan Kang
1575045e3678SYuan Kang struct caam_hash_template {
1576045e3678SYuan Kang char name[CRYPTO_MAX_ALG_NAME];
1577045e3678SYuan Kang char driver_name[CRYPTO_MAX_ALG_NAME];
1578b0e09baeSYuan Kang char hmac_name[CRYPTO_MAX_ALG_NAME];
1579b0e09baeSYuan Kang char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
1580045e3678SYuan Kang unsigned int blocksize;
1581045e3678SYuan Kang struct ahash_alg template_ahash;
1582045e3678SYuan Kang u32 alg_type;
1583045e3678SYuan Kang };
1584045e3678SYuan Kang
1585045e3678SYuan Kang /* ahash descriptors */
1586045e3678SYuan Kang static struct caam_hash_template driver_hash[] = {
1587045e3678SYuan Kang {
1588b0e09baeSYuan Kang .name = "sha1",
1589b0e09baeSYuan Kang .driver_name = "sha1-caam",
1590b0e09baeSYuan Kang .hmac_name = "hmac(sha1)",
1591b0e09baeSYuan Kang .hmac_driver_name = "hmac-sha1-caam",
1592045e3678SYuan Kang .blocksize = SHA1_BLOCK_SIZE,
1593045e3678SYuan Kang .template_ahash = {
1594045e3678SYuan Kang .init = ahash_init,
1595045e3678SYuan Kang .update = ahash_update,
1596045e3678SYuan Kang .final = ahash_final,
1597045e3678SYuan Kang .finup = ahash_finup,
1598045e3678SYuan Kang .digest = ahash_digest,
1599045e3678SYuan Kang .export = ahash_export,
1600045e3678SYuan Kang .import = ahash_import,
1601045e3678SYuan Kang .setkey = ahash_setkey,
1602045e3678SYuan Kang .halg = {
1603045e3678SYuan Kang .digestsize = SHA1_DIGEST_SIZE,
16045ec90831SRussell King .statesize = sizeof(struct caam_export_state),
1605045e3678SYuan Kang },
1606045e3678SYuan Kang },
1607045e3678SYuan Kang .alg_type = OP_ALG_ALGSEL_SHA1,
1608045e3678SYuan Kang }, {
1609b0e09baeSYuan Kang .name = "sha224",
1610b0e09baeSYuan Kang .driver_name = "sha224-caam",
1611b0e09baeSYuan Kang .hmac_name = "hmac(sha224)",
1612b0e09baeSYuan Kang .hmac_driver_name = "hmac-sha224-caam",
1613045e3678SYuan Kang .blocksize = SHA224_BLOCK_SIZE,
1614045e3678SYuan Kang .template_ahash = {
1615045e3678SYuan Kang .init = ahash_init,
1616045e3678SYuan Kang .update = ahash_update,
1617045e3678SYuan Kang .final = ahash_final,
1618045e3678SYuan Kang .finup = ahash_finup,
1619045e3678SYuan Kang .digest = ahash_digest,
1620045e3678SYuan Kang .export = ahash_export,
1621045e3678SYuan Kang .import = ahash_import,
1622045e3678SYuan Kang .setkey = ahash_setkey,
1623045e3678SYuan Kang .halg = {
1624045e3678SYuan Kang .digestsize = SHA224_DIGEST_SIZE,
16255ec90831SRussell King .statesize = sizeof(struct caam_export_state),
1626045e3678SYuan Kang },
1627045e3678SYuan Kang },
1628045e3678SYuan Kang .alg_type = OP_ALG_ALGSEL_SHA224,
1629045e3678SYuan Kang }, {
1630b0e09baeSYuan Kang .name = "sha256",
1631b0e09baeSYuan Kang .driver_name = "sha256-caam",
1632b0e09baeSYuan Kang .hmac_name = "hmac(sha256)",
1633b0e09baeSYuan Kang .hmac_driver_name = "hmac-sha256-caam",
1634045e3678SYuan Kang .blocksize = SHA256_BLOCK_SIZE,
1635045e3678SYuan Kang .template_ahash = {
1636045e3678SYuan Kang .init = ahash_init,
1637045e3678SYuan Kang .update = ahash_update,
1638045e3678SYuan Kang .final = ahash_final,
1639045e3678SYuan Kang .finup = ahash_finup,
1640045e3678SYuan Kang .digest = ahash_digest,
1641045e3678SYuan Kang .export = ahash_export,
1642045e3678SYuan Kang .import = ahash_import,
1643045e3678SYuan Kang .setkey = ahash_setkey,
1644045e3678SYuan Kang .halg = {
1645045e3678SYuan Kang .digestsize = SHA256_DIGEST_SIZE,
16465ec90831SRussell King .statesize = sizeof(struct caam_export_state),
1647045e3678SYuan Kang },
1648045e3678SYuan Kang },
1649045e3678SYuan Kang .alg_type = OP_ALG_ALGSEL_SHA256,
1650045e3678SYuan Kang }, {
1651b0e09baeSYuan Kang .name = "sha384",
1652b0e09baeSYuan Kang .driver_name = "sha384-caam",
1653b0e09baeSYuan Kang .hmac_name = "hmac(sha384)",
1654b0e09baeSYuan Kang .hmac_driver_name = "hmac-sha384-caam",
1655045e3678SYuan Kang .blocksize = SHA384_BLOCK_SIZE,
1656045e3678SYuan Kang .template_ahash = {
1657045e3678SYuan Kang .init = ahash_init,
1658045e3678SYuan Kang .update = ahash_update,
1659045e3678SYuan Kang .final = ahash_final,
1660045e3678SYuan Kang .finup = ahash_finup,
1661045e3678SYuan Kang .digest = ahash_digest,
1662045e3678SYuan Kang .export = ahash_export,
1663045e3678SYuan Kang .import = ahash_import,
1664045e3678SYuan Kang .setkey = ahash_setkey,
1665045e3678SYuan Kang .halg = {
1666045e3678SYuan Kang .digestsize = SHA384_DIGEST_SIZE,
16675ec90831SRussell King .statesize = sizeof(struct caam_export_state),
1668045e3678SYuan Kang },
1669045e3678SYuan Kang },
1670045e3678SYuan Kang .alg_type = OP_ALG_ALGSEL_SHA384,
1671045e3678SYuan Kang }, {
1672b0e09baeSYuan Kang .name = "sha512",
1673b0e09baeSYuan Kang .driver_name = "sha512-caam",
1674b0e09baeSYuan Kang .hmac_name = "hmac(sha512)",
1675b0e09baeSYuan Kang .hmac_driver_name = "hmac-sha512-caam",
1676045e3678SYuan Kang .blocksize = SHA512_BLOCK_SIZE,
1677045e3678SYuan Kang .template_ahash = {
1678045e3678SYuan Kang .init = ahash_init,
1679045e3678SYuan Kang .update = ahash_update,
1680045e3678SYuan Kang .final = ahash_final,
1681045e3678SYuan Kang .finup = ahash_finup,
1682045e3678SYuan Kang .digest = ahash_digest,
1683045e3678SYuan Kang .export = ahash_export,
1684045e3678SYuan Kang .import = ahash_import,
1685045e3678SYuan Kang .setkey = ahash_setkey,
1686045e3678SYuan Kang .halg = {
1687045e3678SYuan Kang .digestsize = SHA512_DIGEST_SIZE,
16885ec90831SRussell King .statesize = sizeof(struct caam_export_state),
1689045e3678SYuan Kang },
1690045e3678SYuan Kang },
1691045e3678SYuan Kang .alg_type = OP_ALG_ALGSEL_SHA512,
1692045e3678SYuan Kang }, {
1693b0e09baeSYuan Kang .name = "md5",
1694b0e09baeSYuan Kang .driver_name = "md5-caam",
1695b0e09baeSYuan Kang .hmac_name = "hmac(md5)",
1696b0e09baeSYuan Kang .hmac_driver_name = "hmac-md5-caam",
1697045e3678SYuan Kang .blocksize = MD5_BLOCK_WORDS * 4,
1698045e3678SYuan Kang .template_ahash = {
1699045e3678SYuan Kang .init = ahash_init,
1700045e3678SYuan Kang .update = ahash_update,
1701045e3678SYuan Kang .final = ahash_final,
1702045e3678SYuan Kang .finup = ahash_finup,
1703045e3678SYuan Kang .digest = ahash_digest,
1704045e3678SYuan Kang .export = ahash_export,
1705045e3678SYuan Kang .import = ahash_import,
1706045e3678SYuan Kang .setkey = ahash_setkey,
1707045e3678SYuan Kang .halg = {
1708045e3678SYuan Kang .digestsize = MD5_DIGEST_SIZE,
17095ec90831SRussell King .statesize = sizeof(struct caam_export_state),
1710045e3678SYuan Kang },
1711045e3678SYuan Kang },
1712045e3678SYuan Kang .alg_type = OP_ALG_ALGSEL_MD5,
171312b8567fSIuliana Prodan }, {
171412b8567fSIuliana Prodan .hmac_name = "xcbc(aes)",
171512b8567fSIuliana Prodan .hmac_driver_name = "xcbc-aes-caam",
171612b8567fSIuliana Prodan .blocksize = AES_BLOCK_SIZE,
171712b8567fSIuliana Prodan .template_ahash = {
171812b8567fSIuliana Prodan .init = ahash_init,
171912b8567fSIuliana Prodan .update = ahash_update,
172012b8567fSIuliana Prodan .final = ahash_final,
172112b8567fSIuliana Prodan .finup = ahash_finup,
172212b8567fSIuliana Prodan .digest = ahash_digest,
172312b8567fSIuliana Prodan .export = ahash_export,
172412b8567fSIuliana Prodan .import = ahash_import,
172512b8567fSIuliana Prodan .setkey = axcbc_setkey,
172612b8567fSIuliana Prodan .halg = {
172712b8567fSIuliana Prodan .digestsize = AES_BLOCK_SIZE,
172812b8567fSIuliana Prodan .statesize = sizeof(struct caam_export_state),
172912b8567fSIuliana Prodan },
173012b8567fSIuliana Prodan },
173112b8567fSIuliana Prodan .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
173287870cfbSIuliana Prodan }, {
173387870cfbSIuliana Prodan .hmac_name = "cmac(aes)",
173487870cfbSIuliana Prodan .hmac_driver_name = "cmac-aes-caam",
173587870cfbSIuliana Prodan .blocksize = AES_BLOCK_SIZE,
173687870cfbSIuliana Prodan .template_ahash = {
173787870cfbSIuliana Prodan .init = ahash_init,
173887870cfbSIuliana Prodan .update = ahash_update,
173987870cfbSIuliana Prodan .final = ahash_final,
174087870cfbSIuliana Prodan .finup = ahash_finup,
174187870cfbSIuliana Prodan .digest = ahash_digest,
174287870cfbSIuliana Prodan .export = ahash_export,
174387870cfbSIuliana Prodan .import = ahash_import,
174487870cfbSIuliana Prodan .setkey = acmac_setkey,
174587870cfbSIuliana Prodan .halg = {
174687870cfbSIuliana Prodan .digestsize = AES_BLOCK_SIZE,
174787870cfbSIuliana Prodan .statesize = sizeof(struct caam_export_state),
174887870cfbSIuliana Prodan },
174987870cfbSIuliana Prodan },
175087870cfbSIuliana Prodan .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC,
1751045e3678SYuan Kang },
1752045e3678SYuan Kang };
1753045e3678SYuan Kang
1754045e3678SYuan Kang struct caam_hash_alg {
1755045e3678SYuan Kang struct list_head entry;
1756045e3678SYuan Kang int alg_type;
1757c5a2f74dSGaurav Jain bool is_hmac;
1758623814c0SHerbert Xu struct ahash_engine_alg ahash_alg;
1759045e3678SYuan Kang };
1760045e3678SYuan Kang
caam_hash_cra_init(struct crypto_tfm * tfm)1761045e3678SYuan Kang static int caam_hash_cra_init(struct crypto_tfm *tfm)
1762045e3678SYuan Kang {
1763045e3678SYuan Kang struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
1764045e3678SYuan Kang struct crypto_alg *base = tfm->__crt_alg;
1765045e3678SYuan Kang struct hash_alg_common *halg =
1766045e3678SYuan Kang container_of(base, struct hash_alg_common, base);
1767045e3678SYuan Kang struct ahash_alg *alg =
1768045e3678SYuan Kang container_of(halg, struct ahash_alg, halg);
1769045e3678SYuan Kang struct caam_hash_alg *caam_hash =
1770623814c0SHerbert Xu container_of(alg, struct caam_hash_alg, ahash_alg.base);
17714cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
1772045e3678SYuan Kang /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
1773045e3678SYuan Kang static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
1774045e3678SYuan Kang HASH_MSG_LEN + SHA1_DIGEST_SIZE,
1775045e3678SYuan Kang HASH_MSG_LEN + 32,
1776045e3678SYuan Kang HASH_MSG_LEN + SHA256_DIGEST_SIZE,
1777045e3678SYuan Kang HASH_MSG_LEN + 64,
1778045e3678SYuan Kang HASH_MSG_LEN + SHA512_DIGEST_SIZE };
177921b014f0SIuliana Prodan const size_t sh_desc_update_offset = offsetof(struct caam_hash_ctx,
178021b014f0SIuliana Prodan sh_desc_update);
1781bbf22344SHoria Geantă dma_addr_t dma_addr;
17827e0880b9SHoria Geantă struct caam_drv_private *priv;
1783045e3678SYuan Kang
1784045e3678SYuan Kang /*
1785cfc6f11bSRuchika Gupta * Get a Job ring from Job Ring driver to ensure in-order
1786045e3678SYuan Kang * crypto request processing per tfm
1787045e3678SYuan Kang */
1788cfc6f11bSRuchika Gupta ctx->jrdev = caam_jr_alloc();
1789cfc6f11bSRuchika Gupta if (IS_ERR(ctx->jrdev)) {
1790cfc6f11bSRuchika Gupta pr_err("Job Ring Device allocation for transform failed\n");
1791cfc6f11bSRuchika Gupta return PTR_ERR(ctx->jrdev);
1792cfc6f11bSRuchika Gupta }
1793bbf22344SHoria Geantă
17947e0880b9SHoria Geantă priv = dev_get_drvdata(ctx->jrdev->parent);
179512b8567fSIuliana Prodan
179612b8567fSIuliana Prodan if (is_xcbc_aes(caam_hash->alg_type)) {
179712b8567fSIuliana Prodan ctx->dir = DMA_TO_DEVICE;
1798e9b4913aSHoria Geantă ctx->key_dir = DMA_BIDIRECTIONAL;
179912b8567fSIuliana Prodan ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
180012b8567fSIuliana Prodan ctx->ctx_len = 48;
1801e9b4913aSHoria Geantă } else if (is_cmac_aes(caam_hash->alg_type)) {
1802e9b4913aSHoria Geantă ctx->dir = DMA_TO_DEVICE;
1803e9b4913aSHoria Geantă ctx->key_dir = DMA_NONE;
1804e9b4913aSHoria Geantă ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
1805e9b4913aSHoria Geantă ctx->ctx_len = 32;
1806e9b4913aSHoria Geantă } else {
1807e9b4913aSHoria Geantă if (priv->era >= 6) {
1808e9b4913aSHoria Geantă ctx->dir = DMA_BIDIRECTIONAL;
1809c5a2f74dSGaurav Jain ctx->key_dir = caam_hash->is_hmac ? DMA_TO_DEVICE : DMA_NONE;
1810e9b4913aSHoria Geantă } else {
1811e9b4913aSHoria Geantă ctx->dir = DMA_TO_DEVICE;
1812e9b4913aSHoria Geantă ctx->key_dir = DMA_NONE;
1813e9b4913aSHoria Geantă }
1814e9b4913aSHoria Geantă ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
1815e9b4913aSHoria Geantă ctx->ctx_len = runninglen[(ctx->adata.algtype &
1816e9b4913aSHoria Geantă OP_ALG_ALGSEL_SUBMASK) >>
1817e9b4913aSHoria Geantă OP_ALG_ALGSEL_SHIFT];
1818e9b4913aSHoria Geantă }
181912b8567fSIuliana Prodan
1820e9b4913aSHoria Geantă if (ctx->key_dir != DMA_NONE) {
1821a2fb864cSHoria Geantă ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key,
182212b8567fSIuliana Prodan ARRAY_SIZE(ctx->key),
1823e9b4913aSHoria Geantă ctx->key_dir,
182412b8567fSIuliana Prodan DMA_ATTR_SKIP_CPU_SYNC);
1825a2fb864cSHoria Geantă if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) {
182612b8567fSIuliana Prodan dev_err(ctx->jrdev, "unable to map key\n");
182712b8567fSIuliana Prodan caam_jr_free(ctx->jrdev);
182812b8567fSIuliana Prodan return -ENOMEM;
182912b8567fSIuliana Prodan }
183012b8567fSIuliana Prodan }
18317e0880b9SHoria Geantă
1832bbf22344SHoria Geantă dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update,
183321b014f0SIuliana Prodan offsetof(struct caam_hash_ctx, key) -
183421b014f0SIuliana Prodan sh_desc_update_offset,
18357e0880b9SHoria Geantă ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
1836bbf22344SHoria Geantă if (dma_mapping_error(ctx->jrdev, dma_addr)) {
1837bbf22344SHoria Geantă dev_err(ctx->jrdev, "unable to map shared descriptors\n");
183812b8567fSIuliana Prodan
1839e9b4913aSHoria Geantă if (ctx->key_dir != DMA_NONE)
1840a2fb864cSHoria Geantă dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
184112b8567fSIuliana Prodan ARRAY_SIZE(ctx->key),
1842e9b4913aSHoria Geantă ctx->key_dir,
184312b8567fSIuliana Prodan DMA_ATTR_SKIP_CPU_SYNC);
184412b8567fSIuliana Prodan
1845bbf22344SHoria Geantă caam_jr_free(ctx->jrdev);
1846bbf22344SHoria Geantă return -ENOMEM;
1847bbf22344SHoria Geantă }
1848bbf22344SHoria Geantă
1849bbf22344SHoria Geantă ctx->sh_desc_update_dma = dma_addr;
1850bbf22344SHoria Geantă ctx->sh_desc_update_first_dma = dma_addr +
1851bbf22344SHoria Geantă offsetof(struct caam_hash_ctx,
185221b014f0SIuliana Prodan sh_desc_update_first) -
185321b014f0SIuliana Prodan sh_desc_update_offset;
1854bbf22344SHoria Geantă ctx->sh_desc_fin_dma = dma_addr + offsetof(struct caam_hash_ctx,
185521b014f0SIuliana Prodan sh_desc_fin) -
185621b014f0SIuliana Prodan sh_desc_update_offset;
1857bbf22344SHoria Geantă ctx->sh_desc_digest_dma = dma_addr + offsetof(struct caam_hash_ctx,
185821b014f0SIuliana Prodan sh_desc_digest) -
185921b014f0SIuliana Prodan sh_desc_update_offset;
186021b014f0SIuliana Prodan
18614cb4f7c1SHerbert Xu crypto_ahash_set_reqsize_dma(ahash, sizeof(struct caam_hash_state));
18629a2537d0SIuliana Prodan
18639a2537d0SIuliana Prodan /*
18649a2537d0SIuliana Prodan * For keyed hash algorithms shared descriptors
18659a2537d0SIuliana Prodan * will be created later in setkey() callback
18669a2537d0SIuliana Prodan */
1867c5a2f74dSGaurav Jain return caam_hash->is_hmac ? 0 : ahash_set_sh_desc(ahash);
1868045e3678SYuan Kang }
1869045e3678SYuan Kang
caam_hash_cra_exit(struct crypto_tfm * tfm)1870045e3678SYuan Kang static void caam_hash_cra_exit(struct crypto_tfm *tfm)
1871045e3678SYuan Kang {
18724cb4f7c1SHerbert Xu struct caam_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm);
1873045e3678SYuan Kang
1874bbf22344SHoria Geantă dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma,
187521b014f0SIuliana Prodan offsetof(struct caam_hash_ctx, key) -
187621b014f0SIuliana Prodan offsetof(struct caam_hash_ctx, sh_desc_update),
18777e0880b9SHoria Geantă ctx->dir, DMA_ATTR_SKIP_CPU_SYNC);
1878e9b4913aSHoria Geantă if (ctx->key_dir != DMA_NONE)
1879a2fb864cSHoria Geantă dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma,
1880e9b4913aSHoria Geantă ARRAY_SIZE(ctx->key), ctx->key_dir,
188112b8567fSIuliana Prodan DMA_ATTR_SKIP_CPU_SYNC);
1882cfc6f11bSRuchika Gupta caam_jr_free(ctx->jrdev);
1883045e3678SYuan Kang }
1884045e3678SYuan Kang
caam_algapi_hash_exit(void)18851b46c90cSHoria Geantă void caam_algapi_hash_exit(void)
1886045e3678SYuan Kang {
1887045e3678SYuan Kang struct caam_hash_alg *t_alg, *n;
1888045e3678SYuan Kang
1889cfc6f11bSRuchika Gupta if (!hash_list.next)
1890045e3678SYuan Kang return;
1891045e3678SYuan Kang
1892cfc6f11bSRuchika Gupta list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
1893623814c0SHerbert Xu crypto_engine_unregister_ahash(&t_alg->ahash_alg);
1894045e3678SYuan Kang list_del(&t_alg->entry);
1895045e3678SYuan Kang kfree(t_alg);
1896045e3678SYuan Kang }
1897045e3678SYuan Kang }
1898045e3678SYuan Kang
1899045e3678SYuan Kang static struct caam_hash_alg *
caam_hash_alloc(struct caam_hash_template * template,bool keyed)1900cfc6f11bSRuchika Gupta caam_hash_alloc(struct caam_hash_template *template,
1901b0e09baeSYuan Kang bool keyed)
1902045e3678SYuan Kang {
1903045e3678SYuan Kang struct caam_hash_alg *t_alg;
1904045e3678SYuan Kang struct ahash_alg *halg;
1905045e3678SYuan Kang struct crypto_alg *alg;
1906045e3678SYuan Kang
19079c4f9733SFabio Estevam t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
19083de0152bSChristophe JAILLET if (!t_alg)
1909045e3678SYuan Kang return ERR_PTR(-ENOMEM);
1910045e3678SYuan Kang
1911623814c0SHerbert Xu t_alg->ahash_alg.base = template->template_ahash;
1912623814c0SHerbert Xu halg = &t_alg->ahash_alg.base;
1913045e3678SYuan Kang alg = &halg->halg.base;
1914045e3678SYuan Kang
1915b0e09baeSYuan Kang if (keyed) {
1916b0e09baeSYuan Kang snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
1917b0e09baeSYuan Kang template->hmac_name);
1918b0e09baeSYuan Kang snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
1919b0e09baeSYuan Kang template->hmac_driver_name);
1920c5a2f74dSGaurav Jain t_alg->is_hmac = true;
1921b0e09baeSYuan Kang } else {
1922b0e09baeSYuan Kang snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
1923b0e09baeSYuan Kang template->name);
1924045e3678SYuan Kang snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
1925045e3678SYuan Kang template->driver_name);
1926623814c0SHerbert Xu halg->setkey = NULL;
1927c5a2f74dSGaurav Jain t_alg->is_hmac = false;
1928b0e09baeSYuan Kang }
1929045e3678SYuan Kang alg->cra_module = THIS_MODULE;
1930045e3678SYuan Kang alg->cra_init = caam_hash_cra_init;
1931045e3678SYuan Kang alg->cra_exit = caam_hash_cra_exit;
19324cb4f7c1SHerbert Xu alg->cra_ctxsize = sizeof(struct caam_hash_ctx) + crypto_dma_padding();
1933045e3678SYuan Kang alg->cra_priority = CAAM_CRA_PRIORITY;
1934045e3678SYuan Kang alg->cra_blocksize = template->blocksize;
1935045e3678SYuan Kang alg->cra_alignmask = 0;
1936b8aa7dc5SMikulas Patocka alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY;
1937045e3678SYuan Kang
1938045e3678SYuan Kang t_alg->alg_type = template->alg_type;
1939623814c0SHerbert Xu t_alg->ahash_alg.op.do_one_request = ahash_do_one_req;
1940045e3678SYuan Kang
1941045e3678SYuan Kang return t_alg;
1942045e3678SYuan Kang }
1943045e3678SYuan Kang
caam_algapi_hash_init(struct device * ctrldev)19441b46c90cSHoria Geantă int caam_algapi_hash_init(struct device *ctrldev)
1945045e3678SYuan Kang {
1946045e3678SYuan Kang int i = 0, err = 0;
19471b46c90cSHoria Geantă struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
1948bf83490eSVictoria Milhoan unsigned int md_limit = SHA512_DIGEST_SIZE;
1949d239b10dSHoria Geantă u32 md_inst, md_vid;
1950045e3678SYuan Kang
1951bf83490eSVictoria Milhoan /*
1952bf83490eSVictoria Milhoan * Register crypto algorithms the device supports. First, identify
1953bf83490eSVictoria Milhoan * presence and attributes of MD block.
1954bf83490eSVictoria Milhoan */
1955d239b10dSHoria Geantă if (priv->era < 10) {
1956ae1dd17dSHoria GeantA struct caam_perfmon __iomem *perfmon = &priv->jr[0]->perfmon;
1957ae1dd17dSHoria GeantA
1958ae1dd17dSHoria GeantA md_vid = (rd_reg32(&perfmon->cha_id_ls) &
1959d239b10dSHoria Geantă CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
1960ae1dd17dSHoria GeantA md_inst = (rd_reg32(&perfmon->cha_num_ls) &
1961d239b10dSHoria Geantă CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
1962d239b10dSHoria Geantă } else {
1963ae1dd17dSHoria GeantA u32 mdha = rd_reg32(&priv->jr[0]->vreg.mdha);
1964d239b10dSHoria Geantă
1965d239b10dSHoria Geantă md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT;
1966d239b10dSHoria Geantă md_inst = mdha & CHA_VER_NUM_MASK;
1967d239b10dSHoria Geantă }
1968bf83490eSVictoria Milhoan
1969bf83490eSVictoria Milhoan /*
1970bf83490eSVictoria Milhoan * Skip registration of any hashing algorithms if MD block
1971bf83490eSVictoria Milhoan * is not present.
1972bf83490eSVictoria Milhoan */
19731b46c90cSHoria Geantă if (!md_inst)
19740435d47eSIuliana Prodan return 0;
1975bf83490eSVictoria Milhoan
1976bf83490eSVictoria Milhoan /* Limit digest size based on LP256 */
1977d239b10dSHoria Geantă if (md_vid == CHA_VER_VID_MD_LP256)
1978bf83490eSVictoria Milhoan md_limit = SHA256_DIGEST_SIZE;
1979bf83490eSVictoria Milhoan
1980cfc6f11bSRuchika Gupta INIT_LIST_HEAD(&hash_list);
1981045e3678SYuan Kang
1982045e3678SYuan Kang /* register crypto algorithms the device supports */
1983045e3678SYuan Kang for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
1984045e3678SYuan Kang struct caam_hash_alg *t_alg;
1985bf83490eSVictoria Milhoan struct caam_hash_template *alg = driver_hash + i;
1986bf83490eSVictoria Milhoan
1987bf83490eSVictoria Milhoan /* If MD size is not supported by device, skip registration */
198812b8567fSIuliana Prodan if (is_mdha(alg->alg_type) &&
198912b8567fSIuliana Prodan alg->template_ahash.halg.digestsize > md_limit)
1990bf83490eSVictoria Milhoan continue;
1991045e3678SYuan Kang
1992b0e09baeSYuan Kang /* register hmac version */
1993bf83490eSVictoria Milhoan t_alg = caam_hash_alloc(alg, true);
1994b0e09baeSYuan Kang if (IS_ERR(t_alg)) {
1995b0e09baeSYuan Kang err = PTR_ERR(t_alg);
19960f103b37SIuliana Prodan pr_warn("%s alg allocation failed\n",
19970f103b37SIuliana Prodan alg->hmac_driver_name);
1998b0e09baeSYuan Kang continue;
1999b0e09baeSYuan Kang }
2000b0e09baeSYuan Kang
2001623814c0SHerbert Xu err = crypto_engine_register_ahash(&t_alg->ahash_alg);
2002b0e09baeSYuan Kang if (err) {
20036ea30f0aSRussell King pr_warn("%s alg registration failed: %d\n",
2004623814c0SHerbert Xu t_alg->ahash_alg.base.halg.base.cra_driver_name,
20056ea30f0aSRussell King err);
2006b0e09baeSYuan Kang kfree(t_alg);
2007b0e09baeSYuan Kang } else
2008cfc6f11bSRuchika Gupta list_add_tail(&t_alg->entry, &hash_list);
2009b0e09baeSYuan Kang
201012b8567fSIuliana Prodan if ((alg->alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES)
201112b8567fSIuliana Prodan continue;
201212b8567fSIuliana Prodan
2013b0e09baeSYuan Kang /* register unkeyed version */
2014bf83490eSVictoria Milhoan t_alg = caam_hash_alloc(alg, false);
2015045e3678SYuan Kang if (IS_ERR(t_alg)) {
2016045e3678SYuan Kang err = PTR_ERR(t_alg);
2017bf83490eSVictoria Milhoan pr_warn("%s alg allocation failed\n", alg->driver_name);
2018045e3678SYuan Kang continue;
2019045e3678SYuan Kang }
2020045e3678SYuan Kang
2021623814c0SHerbert Xu err = crypto_engine_register_ahash(&t_alg->ahash_alg);
2022045e3678SYuan Kang if (err) {
20236ea30f0aSRussell King pr_warn("%s alg registration failed: %d\n",
2024623814c0SHerbert Xu t_alg->ahash_alg.base.halg.base.cra_driver_name,
20256ea30f0aSRussell King err);
2026045e3678SYuan Kang kfree(t_alg);
2027045e3678SYuan Kang } else
2028cfc6f11bSRuchika Gupta list_add_tail(&t_alg->entry, &hash_list);
2029045e3678SYuan Kang }
2030045e3678SYuan Kang
2031045e3678SYuan Kang return err;
2032045e3678SYuan Kang }
2033