xref: /linux/drivers/crypto/hisilicon/sec2/sec_crypto.c (revision 1e9bc276f8f19ea65b617d7c9458ead14da4ef60)
1416d8220SZaibo Xu // SPDX-License-Identifier: GPL-2.0
2416d8220SZaibo Xu /* Copyright (c) 2019 HiSilicon Limited. */
3416d8220SZaibo Xu 
4416d8220SZaibo Xu #include <crypto/aes.h>
5416d8220SZaibo Xu #include <crypto/algapi.h>
6416d8220SZaibo Xu #include <crypto/des.h>
7416d8220SZaibo Xu #include <crypto/skcipher.h>
8416d8220SZaibo Xu #include <crypto/xts.h>
9416d8220SZaibo Xu #include <linux/crypto.h>
10416d8220SZaibo Xu #include <linux/dma-mapping.h>
11416d8220SZaibo Xu #include <linux/idr.h>
12416d8220SZaibo Xu 
13416d8220SZaibo Xu #include "sec.h"
14416d8220SZaibo Xu #include "sec_crypto.h"
15416d8220SZaibo Xu 
16416d8220SZaibo Xu #define SEC_PRIORITY		4001
17416d8220SZaibo Xu #define SEC_XTS_MIN_KEY_SIZE	(2 * AES_MIN_KEY_SIZE)
18416d8220SZaibo Xu #define SEC_XTS_MAX_KEY_SIZE	(2 * AES_MAX_KEY_SIZE)
19416d8220SZaibo Xu #define SEC_DES3_2KEY_SIZE	(2 * DES_KEY_SIZE)
20416d8220SZaibo Xu #define SEC_DES3_3KEY_SIZE	(3 * DES_KEY_SIZE)
21416d8220SZaibo Xu 
22416d8220SZaibo Xu /* SEC sqe(bd) bit operational relative MACRO */
23416d8220SZaibo Xu #define SEC_DE_OFFSET		1
24416d8220SZaibo Xu #define SEC_CIPHER_OFFSET	4
25416d8220SZaibo Xu #define SEC_SCENE_OFFSET	3
26416d8220SZaibo Xu #define SEC_DST_SGL_OFFSET	2
27416d8220SZaibo Xu #define SEC_SRC_SGL_OFFSET	7
28416d8220SZaibo Xu #define SEC_CKEY_OFFSET		9
29416d8220SZaibo Xu #define SEC_CMODE_OFFSET	12
30416d8220SZaibo Xu #define SEC_FLAG_OFFSET		7
31416d8220SZaibo Xu #define SEC_FLAG_MASK		0x0780
32416d8220SZaibo Xu #define SEC_TYPE_MASK		0x0F
33416d8220SZaibo Xu #define SEC_DONE_MASK		0x0001
34416d8220SZaibo Xu 
35416d8220SZaibo Xu #define SEC_TOTAL_IV_SZ		(SEC_IV_SIZE * QM_Q_DEPTH)
36416d8220SZaibo Xu #define SEC_SGL_SGE_NR		128
37416d8220SZaibo Xu #define SEC_CTX_DEV(ctx)	(&(ctx)->sec->qm.pdev->dev)
38416d8220SZaibo Xu 
39416d8220SZaibo Xu static DEFINE_MUTEX(sec_algs_lock);
40416d8220SZaibo Xu static unsigned int sec_active_devs;
41416d8220SZaibo Xu 
42416d8220SZaibo Xu /* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
43416d8220SZaibo Xu static inline int sec_get_queue_id(struct sec_ctx *ctx, struct sec_req *req)
44416d8220SZaibo Xu {
45416d8220SZaibo Xu 	if (req->c_req.encrypt)
46416d8220SZaibo Xu 		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
47416d8220SZaibo Xu 				 ctx->hlf_q_num;
48416d8220SZaibo Xu 
49416d8220SZaibo Xu 	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
50416d8220SZaibo Xu 				 ctx->hlf_q_num;
51416d8220SZaibo Xu }
52416d8220SZaibo Xu 
53416d8220SZaibo Xu static inline void sec_put_queue_id(struct sec_ctx *ctx, struct sec_req *req)
54416d8220SZaibo Xu {
55416d8220SZaibo Xu 	if (req->c_req.encrypt)
56416d8220SZaibo Xu 		atomic_dec(&ctx->enc_qcyclic);
57416d8220SZaibo Xu 	else
58416d8220SZaibo Xu 		atomic_dec(&ctx->dec_qcyclic);
59416d8220SZaibo Xu }
60416d8220SZaibo Xu 
61416d8220SZaibo Xu static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
62416d8220SZaibo Xu {
63416d8220SZaibo Xu 	int req_id;
64416d8220SZaibo Xu 
65416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
66416d8220SZaibo Xu 
67416d8220SZaibo Xu 	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL,
68416d8220SZaibo Xu 				  0, QM_Q_DEPTH, GFP_ATOMIC);
69416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
70416d8220SZaibo Xu 	if (req_id < 0) {
71416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "alloc req id fail!\n");
72416d8220SZaibo Xu 		return req_id;
73416d8220SZaibo Xu 	}
74416d8220SZaibo Xu 
75416d8220SZaibo Xu 	req->qp_ctx = qp_ctx;
76416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = req;
77416d8220SZaibo Xu 	return req_id;
78416d8220SZaibo Xu }
79416d8220SZaibo Xu 
80416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req)
81416d8220SZaibo Xu {
82416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
83416d8220SZaibo Xu 	int req_id = req->req_id;
84416d8220SZaibo Xu 
85416d8220SZaibo Xu 	if (req_id < 0 || req_id >= QM_Q_DEPTH) {
86416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "free request id invalid!\n");
87416d8220SZaibo Xu 		return;
88416d8220SZaibo Xu 	}
89416d8220SZaibo Xu 
90416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = NULL;
91416d8220SZaibo Xu 	req->qp_ctx = NULL;
92416d8220SZaibo Xu 
93416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
94416d8220SZaibo Xu 	idr_remove(&qp_ctx->req_idr, req_id);
95416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
96416d8220SZaibo Xu }
97416d8220SZaibo Xu 
98416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp)
99416d8220SZaibo Xu {
100416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
101416d8220SZaibo Xu 	struct sec_sqe *bd = resp;
102416d8220SZaibo Xu 	u16 done, flag;
103416d8220SZaibo Xu 	u8 type;
104416d8220SZaibo Xu 	struct sec_req *req;
105416d8220SZaibo Xu 
106416d8220SZaibo Xu 	type = bd->type_cipher_auth & SEC_TYPE_MASK;
107416d8220SZaibo Xu 	if (type == SEC_BD_TYPE2) {
108416d8220SZaibo Xu 		req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)];
109416d8220SZaibo Xu 		req->err_type = bd->type2.error_type;
110416d8220SZaibo Xu 
111416d8220SZaibo Xu 		done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
112416d8220SZaibo Xu 		flag = (le16_to_cpu(bd->type2.done_flag) &
113416d8220SZaibo Xu 				   SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
114416d8220SZaibo Xu 		if (req->err_type || done != 0x1 || flag != 0x2)
115416d8220SZaibo Xu 			dev_err(SEC_CTX_DEV(req->ctx),
116416d8220SZaibo Xu 				"err_type[%d],done[%d],flag[%d]\n",
117416d8220SZaibo Xu 				req->err_type, done, flag);
118416d8220SZaibo Xu 	} else {
119416d8220SZaibo Xu 		pr_err("err bd type [%d]\n", type);
120416d8220SZaibo Xu 		return;
121416d8220SZaibo Xu 	}
122416d8220SZaibo Xu 
123*1e9bc276SZaibo Xu 	__sync_add_and_fetch(&req->ctx->sec->debug.dfx.recv_cnt, 1);
124*1e9bc276SZaibo Xu 
125416d8220SZaibo Xu 	req->ctx->req_op->buf_unmap(req->ctx, req);
126416d8220SZaibo Xu 
127416d8220SZaibo Xu 	req->ctx->req_op->callback(req->ctx, req);
128416d8220SZaibo Xu }
129416d8220SZaibo Xu 
130416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
131416d8220SZaibo Xu {
132416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
133416d8220SZaibo Xu 	int ret;
134416d8220SZaibo Xu 
135416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
136416d8220SZaibo Xu 	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
137416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
138*1e9bc276SZaibo Xu 	__sync_add_and_fetch(&ctx->sec->debug.dfx.send_cnt, 1);
139416d8220SZaibo Xu 
140416d8220SZaibo Xu 	if (ret == -EBUSY)
141416d8220SZaibo Xu 		return -ENOBUFS;
142416d8220SZaibo Xu 
143416d8220SZaibo Xu 	if (!ret) {
144416d8220SZaibo Xu 		if (req->fake_busy)
145416d8220SZaibo Xu 			ret = -EBUSY;
146416d8220SZaibo Xu 		else
147416d8220SZaibo Xu 			ret = -EINPROGRESS;
148416d8220SZaibo Xu 	}
149416d8220SZaibo Xu 
150416d8220SZaibo Xu 	return ret;
151416d8220SZaibo Xu }
152416d8220SZaibo Xu 
153416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
154416d8220SZaibo Xu 			     int qp_ctx_id, int alg_type)
155416d8220SZaibo Xu {
156416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
157416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
158416d8220SZaibo Xu 	struct hisi_qp *qp;
159416d8220SZaibo Xu 	int ret = -ENOMEM;
160416d8220SZaibo Xu 
161416d8220SZaibo Xu 	qp = hisi_qm_create_qp(qm, alg_type);
162416d8220SZaibo Xu 	if (IS_ERR(qp))
163416d8220SZaibo Xu 		return PTR_ERR(qp);
164416d8220SZaibo Xu 
165416d8220SZaibo Xu 	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
166416d8220SZaibo Xu 	qp->req_type = 0;
167416d8220SZaibo Xu 	qp->qp_ctx = qp_ctx;
168416d8220SZaibo Xu 	qp->req_cb = sec_req_cb;
169416d8220SZaibo Xu 	qp_ctx->qp = qp;
170416d8220SZaibo Xu 	qp_ctx->ctx = ctx;
171416d8220SZaibo Xu 
172416d8220SZaibo Xu 	mutex_init(&qp_ctx->req_lock);
173416d8220SZaibo Xu 	atomic_set(&qp_ctx->pending_reqs, 0);
174416d8220SZaibo Xu 	idr_init(&qp_ctx->req_idr);
175416d8220SZaibo Xu 
176416d8220SZaibo Xu 	qp_ctx->req_list = kcalloc(QM_Q_DEPTH, sizeof(void *), GFP_ATOMIC);
177416d8220SZaibo Xu 	if (!qp_ctx->req_list)
178416d8220SZaibo Xu 		goto err_destroy_idr;
179416d8220SZaibo Xu 
180416d8220SZaibo Xu 	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
181416d8220SZaibo Xu 						     SEC_SGL_SGE_NR);
182416d8220SZaibo Xu 	if (!qp_ctx->c_in_pool) {
183416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for input!\n");
184416d8220SZaibo Xu 		goto err_free_req_list;
185416d8220SZaibo Xu 	}
186416d8220SZaibo Xu 
187416d8220SZaibo Xu 	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
188416d8220SZaibo Xu 						      SEC_SGL_SGE_NR);
189416d8220SZaibo Xu 	if (!qp_ctx->c_out_pool) {
190416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for output!\n");
191416d8220SZaibo Xu 		goto err_free_c_in_pool;
192416d8220SZaibo Xu 	}
193416d8220SZaibo Xu 
194416d8220SZaibo Xu 	ret = ctx->req_op->resource_alloc(ctx, qp_ctx);
195416d8220SZaibo Xu 	if (ret)
196416d8220SZaibo Xu 		goto err_free_c_out_pool;
197416d8220SZaibo Xu 
198416d8220SZaibo Xu 	ret = hisi_qm_start_qp(qp, 0);
199416d8220SZaibo Xu 	if (ret < 0)
200416d8220SZaibo Xu 		goto err_queue_free;
201416d8220SZaibo Xu 
202416d8220SZaibo Xu 	return 0;
203416d8220SZaibo Xu 
204416d8220SZaibo Xu err_queue_free:
205416d8220SZaibo Xu 	ctx->req_op->resource_free(ctx, qp_ctx);
206416d8220SZaibo Xu err_free_c_out_pool:
207416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
208416d8220SZaibo Xu err_free_c_in_pool:
209416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
210416d8220SZaibo Xu err_free_req_list:
211416d8220SZaibo Xu 	kfree(qp_ctx->req_list);
212416d8220SZaibo Xu err_destroy_idr:
213416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
214416d8220SZaibo Xu 	hisi_qm_release_qp(qp);
215416d8220SZaibo Xu 
216416d8220SZaibo Xu 	return ret;
217416d8220SZaibo Xu }
218416d8220SZaibo Xu 
219416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx,
220416d8220SZaibo Xu 			       struct sec_qp_ctx *qp_ctx)
221416d8220SZaibo Xu {
222416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
223416d8220SZaibo Xu 
224416d8220SZaibo Xu 	hisi_qm_stop_qp(qp_ctx->qp);
225416d8220SZaibo Xu 	ctx->req_op->resource_free(ctx, qp_ctx);
226416d8220SZaibo Xu 
227416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
228416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
229416d8220SZaibo Xu 
230416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
231416d8220SZaibo Xu 	kfree(qp_ctx->req_list);
232416d8220SZaibo Xu 	hisi_qm_release_qp(qp_ctx->qp);
233416d8220SZaibo Xu }
234416d8220SZaibo Xu 
235416d8220SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm)
236416d8220SZaibo Xu {
237416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
238416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx;
239416d8220SZaibo Xu 	struct sec_dev *sec;
240416d8220SZaibo Xu 	struct device *dev;
241416d8220SZaibo Xu 	struct hisi_qm *qm;
242416d8220SZaibo Xu 	int i, ret;
243416d8220SZaibo Xu 
244416d8220SZaibo Xu 	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
245416d8220SZaibo Xu 
246416d8220SZaibo Xu 	sec = sec_find_device(cpu_to_node(smp_processor_id()));
247416d8220SZaibo Xu 	if (!sec) {
248416d8220SZaibo Xu 		pr_err("find no Hisilicon SEC device!\n");
249416d8220SZaibo Xu 		return -ENODEV;
250416d8220SZaibo Xu 	}
251416d8220SZaibo Xu 	ctx->sec = sec;
252416d8220SZaibo Xu 	qm = &sec->qm;
253416d8220SZaibo Xu 	dev = &qm->pdev->dev;
254416d8220SZaibo Xu 	ctx->hlf_q_num = sec->ctx_q_num >> 0x1;
255416d8220SZaibo Xu 
256416d8220SZaibo Xu 	/* Half of queue depth is taken as fake requests limit in the queue. */
257416d8220SZaibo Xu 	ctx->fake_req_limit = QM_Q_DEPTH >> 0x1;
258416d8220SZaibo Xu 	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
259416d8220SZaibo Xu 			      GFP_KERNEL);
260416d8220SZaibo Xu 	if (!ctx->qp_ctx)
261416d8220SZaibo Xu 		return -ENOMEM;
262416d8220SZaibo Xu 
263416d8220SZaibo Xu 	for (i = 0; i < sec->ctx_q_num; i++) {
264416d8220SZaibo Xu 		ret = sec_create_qp_ctx(qm, ctx, i, 0);
265416d8220SZaibo Xu 		if (ret)
266416d8220SZaibo Xu 			goto err_sec_release_qp_ctx;
267416d8220SZaibo Xu 	}
268416d8220SZaibo Xu 
269416d8220SZaibo Xu 	c_ctx = &ctx->c_ctx;
270416d8220SZaibo Xu 	c_ctx->ivsize = crypto_skcipher_ivsize(tfm);
271416d8220SZaibo Xu 	if (c_ctx->ivsize > SEC_IV_SIZE) {
272416d8220SZaibo Xu 		dev_err(dev, "get error iv size!\n");
273416d8220SZaibo Xu 		ret = -EINVAL;
274416d8220SZaibo Xu 		goto err_sec_release_qp_ctx;
275416d8220SZaibo Xu 	}
276416d8220SZaibo Xu 	c_ctx->c_key = dma_alloc_coherent(dev, SEC_MAX_KEY_SIZE,
277416d8220SZaibo Xu 					  &c_ctx->c_key_dma, GFP_KERNEL);
278416d8220SZaibo Xu 	if (!c_ctx->c_key) {
279416d8220SZaibo Xu 		ret = -ENOMEM;
280416d8220SZaibo Xu 		goto err_sec_release_qp_ctx;
281416d8220SZaibo Xu 	}
282416d8220SZaibo Xu 
283416d8220SZaibo Xu 	return 0;
284416d8220SZaibo Xu 
285416d8220SZaibo Xu err_sec_release_qp_ctx:
286416d8220SZaibo Xu 	for (i = i - 1; i >= 0; i--)
287416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
288416d8220SZaibo Xu 
289416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
290416d8220SZaibo Xu 	return ret;
291416d8220SZaibo Xu }
292416d8220SZaibo Xu 
293416d8220SZaibo Xu static void sec_skcipher_exit(struct crypto_skcipher *tfm)
294416d8220SZaibo Xu {
295416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
296416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
297416d8220SZaibo Xu 	int i = 0;
298416d8220SZaibo Xu 
299416d8220SZaibo Xu 	if (c_ctx->c_key) {
300416d8220SZaibo Xu 		dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
301416d8220SZaibo Xu 				  c_ctx->c_key, c_ctx->c_key_dma);
302416d8220SZaibo Xu 		c_ctx->c_key = NULL;
303416d8220SZaibo Xu 	}
304416d8220SZaibo Xu 
305416d8220SZaibo Xu 	for (i = 0; i < ctx->sec->ctx_q_num; i++)
306416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
307416d8220SZaibo Xu 
308416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
309416d8220SZaibo Xu }
310416d8220SZaibo Xu 
311416d8220SZaibo Xu static int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx,
312416d8220SZaibo Xu 				    const u32 keylen,
313416d8220SZaibo Xu 				    const enum sec_cmode c_mode)
314416d8220SZaibo Xu {
315416d8220SZaibo Xu 	switch (keylen) {
316416d8220SZaibo Xu 	case SEC_DES3_2KEY_SIZE:
317416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
318416d8220SZaibo Xu 		break;
319416d8220SZaibo Xu 	case SEC_DES3_3KEY_SIZE:
320416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
321416d8220SZaibo Xu 		break;
322416d8220SZaibo Xu 	default:
323416d8220SZaibo Xu 		return -EINVAL;
324416d8220SZaibo Xu 	}
325416d8220SZaibo Xu 
326416d8220SZaibo Xu 	return 0;
327416d8220SZaibo Xu }
328416d8220SZaibo Xu 
329416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
330416d8220SZaibo Xu 				       const u32 keylen,
331416d8220SZaibo Xu 				       const enum sec_cmode c_mode)
332416d8220SZaibo Xu {
333416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
334416d8220SZaibo Xu 		switch (keylen) {
335416d8220SZaibo Xu 		case SEC_XTS_MIN_KEY_SIZE:
336416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
337416d8220SZaibo Xu 			break;
338416d8220SZaibo Xu 		case SEC_XTS_MAX_KEY_SIZE:
339416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
340416d8220SZaibo Xu 			break;
341416d8220SZaibo Xu 		default:
342416d8220SZaibo Xu 			pr_err("hisi_sec2: xts mode key error!\n");
343416d8220SZaibo Xu 			return -EINVAL;
344416d8220SZaibo Xu 		}
345416d8220SZaibo Xu 	} else {
346416d8220SZaibo Xu 		switch (keylen) {
347416d8220SZaibo Xu 		case AES_KEYSIZE_128:
348416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
349416d8220SZaibo Xu 			break;
350416d8220SZaibo Xu 		case AES_KEYSIZE_192:
351416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_192BIT;
352416d8220SZaibo Xu 			break;
353416d8220SZaibo Xu 		case AES_KEYSIZE_256:
354416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
355416d8220SZaibo Xu 			break;
356416d8220SZaibo Xu 		default:
357416d8220SZaibo Xu 			pr_err("hisi_sec2: aes key error!\n");
358416d8220SZaibo Xu 			return -EINVAL;
359416d8220SZaibo Xu 		}
360416d8220SZaibo Xu 	}
361416d8220SZaibo Xu 
362416d8220SZaibo Xu 	return 0;
363416d8220SZaibo Xu }
364416d8220SZaibo Xu 
365416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
366416d8220SZaibo Xu 			       const u32 keylen, const enum sec_calg c_alg,
367416d8220SZaibo Xu 			       const enum sec_cmode c_mode)
368416d8220SZaibo Xu {
369416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
370416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
371416d8220SZaibo Xu 	int ret;
372416d8220SZaibo Xu 
373416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
374416d8220SZaibo Xu 		ret = xts_verify_key(tfm, key, keylen);
375416d8220SZaibo Xu 		if (ret) {
376416d8220SZaibo Xu 			dev_err(SEC_CTX_DEV(ctx), "xts mode key err!\n");
377416d8220SZaibo Xu 			return ret;
378416d8220SZaibo Xu 		}
379416d8220SZaibo Xu 	}
380416d8220SZaibo Xu 
381416d8220SZaibo Xu 	c_ctx->c_alg  = c_alg;
382416d8220SZaibo Xu 	c_ctx->c_mode = c_mode;
383416d8220SZaibo Xu 
384416d8220SZaibo Xu 	switch (c_alg) {
385416d8220SZaibo Xu 	case SEC_CALG_3DES:
386416d8220SZaibo Xu 		ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode);
387416d8220SZaibo Xu 		break;
388416d8220SZaibo Xu 	case SEC_CALG_AES:
389416d8220SZaibo Xu 	case SEC_CALG_SM4:
390416d8220SZaibo Xu 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
391416d8220SZaibo Xu 		break;
392416d8220SZaibo Xu 	default:
393416d8220SZaibo Xu 		return -EINVAL;
394416d8220SZaibo Xu 	}
395416d8220SZaibo Xu 
396416d8220SZaibo Xu 	if (ret) {
397416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "set sec key err!\n");
398416d8220SZaibo Xu 		return ret;
399416d8220SZaibo Xu 	}
400416d8220SZaibo Xu 
401416d8220SZaibo Xu 	memcpy(c_ctx->c_key, key, keylen);
402416d8220SZaibo Xu 
403416d8220SZaibo Xu 	return 0;
404416d8220SZaibo Xu }
405416d8220SZaibo Xu 
406416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
407416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
408416d8220SZaibo Xu 	u32 keylen)							\
409416d8220SZaibo Xu {									\
410416d8220SZaibo Xu 	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
411416d8220SZaibo Xu }
412416d8220SZaibo Xu 
413416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
414416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
415416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
416416d8220SZaibo Xu 
417416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
418416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
419416d8220SZaibo Xu 
420416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
421416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
422416d8220SZaibo Xu 
423416d8220SZaibo Xu static int sec_skcipher_get_res(struct sec_ctx *ctx,
424416d8220SZaibo Xu 				struct sec_req *req)
425416d8220SZaibo Xu {
426416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
427416d8220SZaibo Xu 	struct sec_cipher_res *c_res = qp_ctx->alg_meta_data;
428416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
429416d8220SZaibo Xu 	int req_id = req->req_id;
430416d8220SZaibo Xu 
431416d8220SZaibo Xu 	c_req->c_ivin = c_res[req_id].c_ivin;
432416d8220SZaibo Xu 	c_req->c_ivin_dma = c_res[req_id].c_ivin_dma;
433416d8220SZaibo Xu 
434416d8220SZaibo Xu 	return 0;
435416d8220SZaibo Xu }
436416d8220SZaibo Xu 
437416d8220SZaibo Xu static int sec_skcipher_resource_alloc(struct sec_ctx *ctx,
438416d8220SZaibo Xu 				       struct sec_qp_ctx *qp_ctx)
439416d8220SZaibo Xu {
440416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
441416d8220SZaibo Xu 	struct sec_cipher_res *res;
442416d8220SZaibo Xu 	int i;
443416d8220SZaibo Xu 
444416d8220SZaibo Xu 	res = kcalloc(QM_Q_DEPTH, sizeof(struct sec_cipher_res), GFP_KERNEL);
445416d8220SZaibo Xu 	if (!res)
446416d8220SZaibo Xu 		return -ENOMEM;
447416d8220SZaibo Xu 
448416d8220SZaibo Xu 	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
449416d8220SZaibo Xu 					   &res->c_ivin_dma, GFP_KERNEL);
450416d8220SZaibo Xu 	if (!res->c_ivin) {
451416d8220SZaibo Xu 		kfree(res);
452416d8220SZaibo Xu 		return -ENOMEM;
453416d8220SZaibo Xu 	}
454416d8220SZaibo Xu 
455416d8220SZaibo Xu 	for (i = 1; i < QM_Q_DEPTH; i++) {
456416d8220SZaibo Xu 		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
457416d8220SZaibo Xu 		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
458416d8220SZaibo Xu 	}
459416d8220SZaibo Xu 	qp_ctx->alg_meta_data = res;
460416d8220SZaibo Xu 
461416d8220SZaibo Xu 	return 0;
462416d8220SZaibo Xu }
463416d8220SZaibo Xu 
464416d8220SZaibo Xu static void sec_skcipher_resource_free(struct sec_ctx *ctx,
465416d8220SZaibo Xu 				      struct sec_qp_ctx *qp_ctx)
466416d8220SZaibo Xu {
467416d8220SZaibo Xu 	struct sec_cipher_res *res = qp_ctx->alg_meta_data;
468416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
469416d8220SZaibo Xu 
470416d8220SZaibo Xu 	if (!res)
471416d8220SZaibo Xu 		return;
472416d8220SZaibo Xu 
473416d8220SZaibo Xu 	dma_free_coherent(dev, SEC_TOTAL_IV_SZ, res->c_ivin, res->c_ivin_dma);
474416d8220SZaibo Xu 	kfree(res);
475416d8220SZaibo Xu }
476416d8220SZaibo Xu 
477416d8220SZaibo Xu static int sec_skcipher_map(struct device *dev, struct sec_req *req,
478416d8220SZaibo Xu 			    struct scatterlist *src, struct scatterlist *dst)
479416d8220SZaibo Xu {
480416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
481416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
482416d8220SZaibo Xu 
483416d8220SZaibo Xu 	c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
484416d8220SZaibo Xu 						    qp_ctx->c_in_pool,
485416d8220SZaibo Xu 						    req->req_id,
486416d8220SZaibo Xu 						    &c_req->c_in_dma);
487416d8220SZaibo Xu 
488416d8220SZaibo Xu 	if (IS_ERR(c_req->c_in)) {
489416d8220SZaibo Xu 		dev_err(dev, "fail to dma map input sgl buffers!\n");
490416d8220SZaibo Xu 		return PTR_ERR(c_req->c_in);
491416d8220SZaibo Xu 	}
492416d8220SZaibo Xu 
493416d8220SZaibo Xu 	if (dst == src) {
494416d8220SZaibo Xu 		c_req->c_out = c_req->c_in;
495416d8220SZaibo Xu 		c_req->c_out_dma = c_req->c_in_dma;
496416d8220SZaibo Xu 	} else {
497416d8220SZaibo Xu 		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
498416d8220SZaibo Xu 							     qp_ctx->c_out_pool,
499416d8220SZaibo Xu 							     req->req_id,
500416d8220SZaibo Xu 							     &c_req->c_out_dma);
501416d8220SZaibo Xu 
502416d8220SZaibo Xu 		if (IS_ERR(c_req->c_out)) {
503416d8220SZaibo Xu 			dev_err(dev, "fail to dma map output sgl buffers!\n");
504416d8220SZaibo Xu 			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
505416d8220SZaibo Xu 			return PTR_ERR(c_req->c_out);
506416d8220SZaibo Xu 		}
507416d8220SZaibo Xu 	}
508416d8220SZaibo Xu 
509416d8220SZaibo Xu 	return 0;
510416d8220SZaibo Xu }
511416d8220SZaibo Xu 
512416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
513416d8220SZaibo Xu {
514416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
515416d8220SZaibo Xu 
516416d8220SZaibo Xu 	return sec_skcipher_map(SEC_CTX_DEV(ctx), req,
517416d8220SZaibo Xu 				c_req->sk_req->src, c_req->sk_req->dst);
518416d8220SZaibo Xu }
519416d8220SZaibo Xu 
520416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
521416d8220SZaibo Xu {
522416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
523416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
524416d8220SZaibo Xu 	struct skcipher_request *sk_req = c_req->sk_req;
525416d8220SZaibo Xu 
526416d8220SZaibo Xu 	if (sk_req->dst != sk_req->src)
527416d8220SZaibo Xu 		hisi_acc_sg_buf_unmap(dev, sk_req->src, c_req->c_in);
528416d8220SZaibo Xu 
529416d8220SZaibo Xu 	hisi_acc_sg_buf_unmap(dev, sk_req->dst, c_req->c_out);
530416d8220SZaibo Xu }
531416d8220SZaibo Xu 
532416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
533416d8220SZaibo Xu {
534416d8220SZaibo Xu 	int ret;
535416d8220SZaibo Xu 
536416d8220SZaibo Xu 	ret = ctx->req_op->buf_map(ctx, req);
537416d8220SZaibo Xu 	if (ret)
538416d8220SZaibo Xu 		return ret;
539416d8220SZaibo Xu 
540416d8220SZaibo Xu 	ctx->req_op->do_transfer(ctx, req);
541416d8220SZaibo Xu 
542416d8220SZaibo Xu 	ret = ctx->req_op->bd_fill(ctx, req);
543416d8220SZaibo Xu 	if (ret)
544416d8220SZaibo Xu 		goto unmap_req_buf;
545416d8220SZaibo Xu 
546416d8220SZaibo Xu 	return ret;
547416d8220SZaibo Xu 
548416d8220SZaibo Xu unmap_req_buf:
549416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
550416d8220SZaibo Xu 
551416d8220SZaibo Xu 	return ret;
552416d8220SZaibo Xu }
553416d8220SZaibo Xu 
554416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
555416d8220SZaibo Xu {
556416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
557416d8220SZaibo Xu }
558416d8220SZaibo Xu 
559416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
560416d8220SZaibo Xu {
561416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
562416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
563416d8220SZaibo Xu 
564416d8220SZaibo Xu 	c_req->c_len = sk_req->cryptlen;
565416d8220SZaibo Xu 	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
566416d8220SZaibo Xu }
567416d8220SZaibo Xu 
568416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
569416d8220SZaibo Xu {
570416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
571416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
572416d8220SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
573416d8220SZaibo Xu 	u8 de = 0;
574416d8220SZaibo Xu 	u8 scene, sa_type, da_type;
575416d8220SZaibo Xu 	u8 bd_type, cipher;
576416d8220SZaibo Xu 
577416d8220SZaibo Xu 	memset(sec_sqe, 0, sizeof(struct sec_sqe));
578416d8220SZaibo Xu 
579416d8220SZaibo Xu 	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
580416d8220SZaibo Xu 	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
581416d8220SZaibo Xu 	sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma);
582416d8220SZaibo Xu 	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
583416d8220SZaibo Xu 
584416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
585416d8220SZaibo Xu 						SEC_CMODE_OFFSET);
586416d8220SZaibo Xu 	sec_sqe->type2.c_alg = c_ctx->c_alg;
587416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
588416d8220SZaibo Xu 						SEC_CKEY_OFFSET);
589416d8220SZaibo Xu 
590416d8220SZaibo Xu 	bd_type = SEC_BD_TYPE2;
591416d8220SZaibo Xu 	if (c_req->encrypt)
592416d8220SZaibo Xu 		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
593416d8220SZaibo Xu 	else
594416d8220SZaibo Xu 		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
595416d8220SZaibo Xu 	sec_sqe->type_cipher_auth = bd_type | cipher;
596416d8220SZaibo Xu 
597416d8220SZaibo Xu 	sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
598416d8220SZaibo Xu 	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
599416d8220SZaibo Xu 	if (c_req->c_in_dma != c_req->c_out_dma)
600416d8220SZaibo Xu 		de = 0x1 << SEC_DE_OFFSET;
601416d8220SZaibo Xu 
602416d8220SZaibo Xu 	sec_sqe->sds_sa_type = (de | scene | sa_type);
603416d8220SZaibo Xu 
604416d8220SZaibo Xu 	/* Just set DST address type */
605416d8220SZaibo Xu 	da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
606416d8220SZaibo Xu 	sec_sqe->sdm_addr_type |= da_type;
607416d8220SZaibo Xu 
608416d8220SZaibo Xu 	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
609416d8220SZaibo Xu 	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
610416d8220SZaibo Xu 
611416d8220SZaibo Xu 	return 0;
612416d8220SZaibo Xu }
613416d8220SZaibo Xu 
614416d8220SZaibo Xu static void sec_update_iv(struct sec_req *req)
615416d8220SZaibo Xu {
616416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
617416d8220SZaibo Xu 	u32 iv_size = req->ctx->c_ctx.ivsize;
618416d8220SZaibo Xu 	struct scatterlist *sgl;
619416d8220SZaibo Xu 	size_t sz;
620416d8220SZaibo Xu 
621416d8220SZaibo Xu 	if (req->c_req.encrypt)
622416d8220SZaibo Xu 		sgl = sk_req->dst;
623416d8220SZaibo Xu 	else
624416d8220SZaibo Xu 		sgl = sk_req->src;
625416d8220SZaibo Xu 
626416d8220SZaibo Xu 	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), sk_req->iv,
627416d8220SZaibo Xu 				iv_size, sk_req->cryptlen - iv_size);
628416d8220SZaibo Xu 	if (sz != iv_size)
629416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n");
630416d8220SZaibo Xu }
631416d8220SZaibo Xu 
632416d8220SZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req)
633416d8220SZaibo Xu {
634416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
635416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
636416d8220SZaibo Xu 
637416d8220SZaibo Xu 	atomic_dec(&qp_ctx->pending_reqs);
638416d8220SZaibo Xu 	sec_free_req_id(req);
639416d8220SZaibo Xu 
640416d8220SZaibo Xu 	/* IV output at encrypto of CBC mode */
641416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
642416d8220SZaibo Xu 		sec_update_iv(req);
643416d8220SZaibo Xu 
644416d8220SZaibo Xu 	if (__sync_bool_compare_and_swap(&req->fake_busy, 1, 0))
645416d8220SZaibo Xu 		sk_req->base.complete(&sk_req->base, -EINPROGRESS);
646416d8220SZaibo Xu 
647416d8220SZaibo Xu 	sk_req->base.complete(&sk_req->base, req->err_type);
648416d8220SZaibo Xu }
649416d8220SZaibo Xu 
650416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
651416d8220SZaibo Xu {
652416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
653416d8220SZaibo Xu 
654416d8220SZaibo Xu 	atomic_dec(&qp_ctx->pending_reqs);
655416d8220SZaibo Xu 	sec_free_req_id(req);
656416d8220SZaibo Xu 	sec_put_queue_id(ctx, req);
657416d8220SZaibo Xu }
658416d8220SZaibo Xu 
659416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
660416d8220SZaibo Xu {
661416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
662416d8220SZaibo Xu 	int issue_id, ret;
663416d8220SZaibo Xu 
664416d8220SZaibo Xu 	/* To load balance */
665416d8220SZaibo Xu 	issue_id = sec_get_queue_id(ctx, req);
666416d8220SZaibo Xu 	qp_ctx = &ctx->qp_ctx[issue_id];
667416d8220SZaibo Xu 
668416d8220SZaibo Xu 	req->req_id = sec_alloc_req_id(req, qp_ctx);
669416d8220SZaibo Xu 	if (req->req_id < 0) {
670416d8220SZaibo Xu 		sec_put_queue_id(ctx, req);
671416d8220SZaibo Xu 		return req->req_id;
672416d8220SZaibo Xu 	}
673416d8220SZaibo Xu 
674416d8220SZaibo Xu 	if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs))
675416d8220SZaibo Xu 		req->fake_busy = 1;
676416d8220SZaibo Xu 	else
677416d8220SZaibo Xu 		req->fake_busy = 0;
678416d8220SZaibo Xu 
679416d8220SZaibo Xu 	ret = ctx->req_op->get_res(ctx, req);
680416d8220SZaibo Xu 	if (ret) {
681416d8220SZaibo Xu 		atomic_dec(&qp_ctx->pending_reqs);
682416d8220SZaibo Xu 		sec_request_uninit(ctx, req);
683416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "get resources failed!\n");
684416d8220SZaibo Xu 	}
685416d8220SZaibo Xu 
686416d8220SZaibo Xu 	return ret;
687416d8220SZaibo Xu }
688416d8220SZaibo Xu 
689416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
690416d8220SZaibo Xu {
691416d8220SZaibo Xu 	int ret;
692416d8220SZaibo Xu 
693416d8220SZaibo Xu 	ret = sec_request_init(ctx, req);
694416d8220SZaibo Xu 	if (ret)
695416d8220SZaibo Xu 		return ret;
696416d8220SZaibo Xu 
697416d8220SZaibo Xu 	ret = sec_request_transfer(ctx, req);
698416d8220SZaibo Xu 	if (ret)
699416d8220SZaibo Xu 		goto err_uninit_req;
700416d8220SZaibo Xu 
701416d8220SZaibo Xu 	/* Output IV as decrypto */
702416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
703416d8220SZaibo Xu 		sec_update_iv(req);
704416d8220SZaibo Xu 
705416d8220SZaibo Xu 	ret = ctx->req_op->bd_send(ctx, req);
706416d8220SZaibo Xu 	if (ret != -EBUSY && ret != -EINPROGRESS) {
707416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "send sec request failed!\n");
708416d8220SZaibo Xu 		goto err_send_req;
709416d8220SZaibo Xu 	}
710416d8220SZaibo Xu 
711416d8220SZaibo Xu 	return ret;
712416d8220SZaibo Xu 
713416d8220SZaibo Xu err_send_req:
714416d8220SZaibo Xu 	/* As failing, restore the IV from user */
715416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
716416d8220SZaibo Xu 		memcpy(req->c_req.sk_req->iv, req->c_req.c_ivin,
717416d8220SZaibo Xu 		       ctx->c_ctx.ivsize);
718416d8220SZaibo Xu 
719416d8220SZaibo Xu 	sec_request_untransfer(ctx, req);
720416d8220SZaibo Xu err_uninit_req:
721416d8220SZaibo Xu 	sec_request_uninit(ctx, req);
722416d8220SZaibo Xu 
723416d8220SZaibo Xu 	return ret;
724416d8220SZaibo Xu }
725416d8220SZaibo Xu 
726416d8220SZaibo Xu static struct sec_req_op sec_req_ops_tbl = {
727416d8220SZaibo Xu 	.get_res	= sec_skcipher_get_res,
728416d8220SZaibo Xu 	.resource_alloc	= sec_skcipher_resource_alloc,
729416d8220SZaibo Xu 	.resource_free	= sec_skcipher_resource_free,
730416d8220SZaibo Xu 	.buf_map	= sec_skcipher_sgl_map,
731416d8220SZaibo Xu 	.buf_unmap	= sec_skcipher_sgl_unmap,
732416d8220SZaibo Xu 	.do_transfer	= sec_skcipher_copy_iv,
733416d8220SZaibo Xu 	.bd_fill	= sec_skcipher_bd_fill,
734416d8220SZaibo Xu 	.bd_send	= sec_bd_send,
735416d8220SZaibo Xu 	.callback	= sec_skcipher_callback,
736416d8220SZaibo Xu 	.process	= sec_process,
737416d8220SZaibo Xu };
738416d8220SZaibo Xu 
739416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
740416d8220SZaibo Xu {
741416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
742416d8220SZaibo Xu 
743416d8220SZaibo Xu 	ctx->req_op = &sec_req_ops_tbl;
744416d8220SZaibo Xu 
745416d8220SZaibo Xu 	return sec_skcipher_init(tfm);
746416d8220SZaibo Xu }
747416d8220SZaibo Xu 
748416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
749416d8220SZaibo Xu {
750416d8220SZaibo Xu 	sec_skcipher_exit(tfm);
751416d8220SZaibo Xu }
752416d8220SZaibo Xu 
753416d8220SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx,
754416d8220SZaibo Xu 				    struct skcipher_request *sk_req)
755416d8220SZaibo Xu {
756416d8220SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
757416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
758416d8220SZaibo Xu 
759416d8220SZaibo Xu 	if (!sk_req->src || !sk_req->dst) {
760416d8220SZaibo Xu 		dev_err(dev, "skcipher input param error!\n");
761416d8220SZaibo Xu 		return -EINVAL;
762416d8220SZaibo Xu 	}
763416d8220SZaibo Xu 
764416d8220SZaibo Xu 	if (c_alg == SEC_CALG_3DES) {
765416d8220SZaibo Xu 		if (sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1)) {
766416d8220SZaibo Xu 			dev_err(dev, "skcipher 3des input length error!\n");
767416d8220SZaibo Xu 			return -EINVAL;
768416d8220SZaibo Xu 		}
769416d8220SZaibo Xu 		return 0;
770416d8220SZaibo Xu 	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
771416d8220SZaibo Xu 		if (sk_req->cryptlen & (AES_BLOCK_SIZE - 1)) {
772416d8220SZaibo Xu 			dev_err(dev, "skcipher aes input length error!\n");
773416d8220SZaibo Xu 			return -EINVAL;
774416d8220SZaibo Xu 		}
775416d8220SZaibo Xu 		return 0;
776416d8220SZaibo Xu 	}
777416d8220SZaibo Xu 
778416d8220SZaibo Xu 	dev_err(dev, "skcipher algorithm error!\n");
779416d8220SZaibo Xu 	return -EINVAL;
780416d8220SZaibo Xu }
781416d8220SZaibo Xu 
782416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
783416d8220SZaibo Xu {
784416d8220SZaibo Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
785416d8220SZaibo Xu 	struct sec_req *req = skcipher_request_ctx(sk_req);
786416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
787416d8220SZaibo Xu 	int ret;
788416d8220SZaibo Xu 
789416d8220SZaibo Xu 	if (!sk_req->cryptlen)
790416d8220SZaibo Xu 		return 0;
791416d8220SZaibo Xu 
792416d8220SZaibo Xu 	ret = sec_skcipher_param_check(ctx, sk_req);
793416d8220SZaibo Xu 	if (ret)
794416d8220SZaibo Xu 		return ret;
795416d8220SZaibo Xu 
796416d8220SZaibo Xu 	req->c_req.sk_req = sk_req;
797416d8220SZaibo Xu 	req->c_req.encrypt = encrypt;
798416d8220SZaibo Xu 	req->ctx = ctx;
799416d8220SZaibo Xu 
800416d8220SZaibo Xu 	return ctx->req_op->process(ctx, req);
801416d8220SZaibo Xu }
802416d8220SZaibo Xu 
803416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
804416d8220SZaibo Xu {
805416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, true);
806416d8220SZaibo Xu }
807416d8220SZaibo Xu 
808416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
809416d8220SZaibo Xu {
810416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, false);
811416d8220SZaibo Xu }
812416d8220SZaibo Xu 
813416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
814416d8220SZaibo Xu 	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
815416d8220SZaibo Xu {\
816416d8220SZaibo Xu 	.base = {\
817416d8220SZaibo Xu 		.cra_name = sec_cra_name,\
818416d8220SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
819416d8220SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
820416d8220SZaibo Xu 		.cra_flags = CRYPTO_ALG_ASYNC,\
821416d8220SZaibo Xu 		.cra_blocksize = blk_size,\
822416d8220SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
823416d8220SZaibo Xu 		.cra_module = THIS_MODULE,\
824416d8220SZaibo Xu 	},\
825416d8220SZaibo Xu 	.init = ctx_init,\
826416d8220SZaibo Xu 	.exit = ctx_exit,\
827416d8220SZaibo Xu 	.setkey = sec_set_key,\
828416d8220SZaibo Xu 	.decrypt = sec_skcipher_decrypt,\
829416d8220SZaibo Xu 	.encrypt = sec_skcipher_encrypt,\
830416d8220SZaibo Xu 	.min_keysize = sec_min_key_size,\
831416d8220SZaibo Xu 	.max_keysize = sec_max_key_size,\
832416d8220SZaibo Xu 	.ivsize = iv_size,\
833416d8220SZaibo Xu },
834416d8220SZaibo Xu 
835416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
836416d8220SZaibo Xu 	max_key_size, blk_size, iv_size) \
837416d8220SZaibo Xu 	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
838416d8220SZaibo Xu 	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
839416d8220SZaibo Xu 
840416d8220SZaibo Xu static struct skcipher_alg sec_algs[] = {
841416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
842416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
843416d8220SZaibo Xu 			 AES_BLOCK_SIZE, 0)
844416d8220SZaibo Xu 
845416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
846416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
847416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
848416d8220SZaibo Xu 
849416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
850416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
851416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
852416d8220SZaibo Xu 
853416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
854416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
855416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, 0)
856416d8220SZaibo Xu 
857416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
858416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
859416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
860416d8220SZaibo Xu 
861416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
862416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
863416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
864416d8220SZaibo Xu 
865416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
866416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
867416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
868416d8220SZaibo Xu };
869416d8220SZaibo Xu 
870416d8220SZaibo Xu int sec_register_to_crypto(void)
871416d8220SZaibo Xu {
872416d8220SZaibo Xu 	int ret = 0;
873416d8220SZaibo Xu 
874416d8220SZaibo Xu 	/* To avoid repeat register */
875416d8220SZaibo Xu 	mutex_lock(&sec_algs_lock);
876416d8220SZaibo Xu 	if (++sec_active_devs == 1)
877416d8220SZaibo Xu 		ret = crypto_register_skciphers(sec_algs, ARRAY_SIZE(sec_algs));
878416d8220SZaibo Xu 	mutex_unlock(&sec_algs_lock);
879416d8220SZaibo Xu 
880416d8220SZaibo Xu 	return ret;
881416d8220SZaibo Xu }
882416d8220SZaibo Xu 
883416d8220SZaibo Xu void sec_unregister_from_crypto(void)
884416d8220SZaibo Xu {
885416d8220SZaibo Xu 	mutex_lock(&sec_algs_lock);
886416d8220SZaibo Xu 	if (--sec_active_devs == 0)
887416d8220SZaibo Xu 		crypto_unregister_skciphers(sec_algs, ARRAY_SIZE(sec_algs));
888416d8220SZaibo Xu 	mutex_unlock(&sec_algs_lock);
889416d8220SZaibo Xu }
890