xref: /linux/drivers/crypto/hisilicon/sec2/sec_crypto.c (revision a181647c06c21828c012df221d4adc1fd4125f16)
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 */
43*a181647cSZaibo Xu static inline int sec_alloc_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 
53*a181647cSZaibo Xu static inline void sec_free_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 
123cb1eeb75SArnd Bergmann 	atomic64_inc(&req->ctx->sec->debug.dfx.recv_cnt);
1241e9bc276SZaibo 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);
138cb1eeb75SArnd Bergmann 	atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
139416d8220SZaibo Xu 
140416d8220SZaibo Xu 	if (ret == -EBUSY)
141416d8220SZaibo Xu 		return -ENOBUFS;
142416d8220SZaibo Xu 
143416d8220SZaibo Xu 	if (!ret) {
144ca0d158dSZaibo 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);
1828a6b8f4dSDan Carpenter 	if (IS_ERR(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);
1898a6b8f4dSDan Carpenter 	if (IS_ERR(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) {
248a718cfceSZaibo Xu 		pr_err("Can not find proper 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;
254a718cfceSZaibo Xu 	ctx->hlf_q_num = sec->ctx_q_num >> 1;
255416d8220SZaibo Xu 
256416d8220SZaibo Xu 	/* Half of queue depth is taken as fake requests limit in the queue. */
257a718cfceSZaibo Xu 	ctx->fake_req_limit = QM_Q_DEPTH >> 1;
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 
293*a181647cSZaibo Xu static void sec_skcipher_uninit(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;
427*a181647cSZaibo Xu 	struct sec_alg_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);
441*a181647cSZaibo Xu 	struct sec_alg_res *res;
442416d8220SZaibo Xu 	int i;
443416d8220SZaibo Xu 
444*a181647cSZaibo Xu 	res = kcalloc(QM_Q_DEPTH, sizeof(*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 {
467*a181647cSZaibo Xu 	struct sec_alg_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 
477*a181647cSZaibo Xu static int sec_cipher_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 
512*a181647cSZaibo Xu static void sec_cipher_unmap(struct device *dev, struct sec_cipher_req *req,
513*a181647cSZaibo Xu 			     struct scatterlist *src, struct scatterlist *dst)
514*a181647cSZaibo Xu {
515*a181647cSZaibo Xu 	if (dst != src)
516*a181647cSZaibo Xu 		hisi_acc_sg_buf_unmap(dev, src, req->c_in);
517*a181647cSZaibo Xu 
518*a181647cSZaibo Xu 	hisi_acc_sg_buf_unmap(dev, dst, req->c_out);
519*a181647cSZaibo Xu }
520*a181647cSZaibo Xu 
521416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
522416d8220SZaibo Xu {
523*a181647cSZaibo Xu 	struct skcipher_request *sq = req->c_req.sk_req;
524416d8220SZaibo Xu 
525*a181647cSZaibo Xu 	return sec_cipher_map(SEC_CTX_DEV(ctx), req, sq->src, sq->dst);
526416d8220SZaibo Xu }
527416d8220SZaibo Xu 
528416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
529416d8220SZaibo Xu {
530416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
531416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
532416d8220SZaibo Xu 	struct skcipher_request *sk_req = c_req->sk_req;
533416d8220SZaibo Xu 
534*a181647cSZaibo Xu 	sec_cipher_unmap(dev, c_req, sk_req->src, sk_req->dst);
535416d8220SZaibo Xu }
536416d8220SZaibo Xu 
537416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
538416d8220SZaibo Xu {
539416d8220SZaibo Xu 	int ret;
540416d8220SZaibo Xu 
541416d8220SZaibo Xu 	ret = ctx->req_op->buf_map(ctx, req);
542416d8220SZaibo Xu 	if (ret)
543416d8220SZaibo Xu 		return ret;
544416d8220SZaibo Xu 
545416d8220SZaibo Xu 	ctx->req_op->do_transfer(ctx, req);
546416d8220SZaibo Xu 
547416d8220SZaibo Xu 	ret = ctx->req_op->bd_fill(ctx, req);
548416d8220SZaibo Xu 	if (ret)
549416d8220SZaibo Xu 		goto unmap_req_buf;
550416d8220SZaibo Xu 
551416d8220SZaibo Xu 	return ret;
552416d8220SZaibo Xu 
553416d8220SZaibo Xu unmap_req_buf:
554416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
555416d8220SZaibo Xu 
556416d8220SZaibo Xu 	return ret;
557416d8220SZaibo Xu }
558416d8220SZaibo Xu 
559416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
560416d8220SZaibo Xu {
561416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
562416d8220SZaibo Xu }
563416d8220SZaibo Xu 
564416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
565416d8220SZaibo Xu {
566416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
567416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
568416d8220SZaibo Xu 
569416d8220SZaibo Xu 	c_req->c_len = sk_req->cryptlen;
570416d8220SZaibo Xu 	memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
571416d8220SZaibo Xu }
572416d8220SZaibo Xu 
573416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
574416d8220SZaibo Xu {
575416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
576416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
577416d8220SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
578416d8220SZaibo Xu 	u8 de = 0;
579416d8220SZaibo Xu 	u8 scene, sa_type, da_type;
580416d8220SZaibo Xu 	u8 bd_type, cipher;
581416d8220SZaibo Xu 
582416d8220SZaibo Xu 	memset(sec_sqe, 0, sizeof(struct sec_sqe));
583416d8220SZaibo Xu 
584416d8220SZaibo Xu 	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
585416d8220SZaibo Xu 	sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma);
586416d8220SZaibo Xu 	sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma);
587416d8220SZaibo Xu 	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
588416d8220SZaibo Xu 
589416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
590416d8220SZaibo Xu 						SEC_CMODE_OFFSET);
591416d8220SZaibo Xu 	sec_sqe->type2.c_alg = c_ctx->c_alg;
592416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
593416d8220SZaibo Xu 						SEC_CKEY_OFFSET);
594416d8220SZaibo Xu 
595416d8220SZaibo Xu 	bd_type = SEC_BD_TYPE2;
596416d8220SZaibo Xu 	if (c_req->encrypt)
597416d8220SZaibo Xu 		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
598416d8220SZaibo Xu 	else
599416d8220SZaibo Xu 		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
600416d8220SZaibo Xu 	sec_sqe->type_cipher_auth = bd_type | cipher;
601416d8220SZaibo Xu 
602416d8220SZaibo Xu 	sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
603416d8220SZaibo Xu 	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
604416d8220SZaibo Xu 	if (c_req->c_in_dma != c_req->c_out_dma)
605416d8220SZaibo Xu 		de = 0x1 << SEC_DE_OFFSET;
606416d8220SZaibo Xu 
607416d8220SZaibo Xu 	sec_sqe->sds_sa_type = (de | scene | sa_type);
608416d8220SZaibo Xu 
609416d8220SZaibo Xu 	/* Just set DST address type */
610416d8220SZaibo Xu 	da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
611416d8220SZaibo Xu 	sec_sqe->sdm_addr_type |= da_type;
612416d8220SZaibo Xu 
613416d8220SZaibo Xu 	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
614416d8220SZaibo Xu 	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
615416d8220SZaibo Xu 
616416d8220SZaibo Xu 	return 0;
617416d8220SZaibo Xu }
618416d8220SZaibo Xu 
619416d8220SZaibo Xu static void sec_update_iv(struct sec_req *req)
620416d8220SZaibo Xu {
621416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
622416d8220SZaibo Xu 	u32 iv_size = req->ctx->c_ctx.ivsize;
623416d8220SZaibo Xu 	struct scatterlist *sgl;
624416d8220SZaibo Xu 	size_t sz;
625416d8220SZaibo Xu 
626416d8220SZaibo Xu 	if (req->c_req.encrypt)
627416d8220SZaibo Xu 		sgl = sk_req->dst;
628416d8220SZaibo Xu 	else
629416d8220SZaibo Xu 		sgl = sk_req->src;
630416d8220SZaibo Xu 
631416d8220SZaibo Xu 	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), sk_req->iv,
632416d8220SZaibo Xu 				iv_size, sk_req->cryptlen - iv_size);
633416d8220SZaibo Xu 	if (sz != iv_size)
634416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n");
635416d8220SZaibo Xu }
636416d8220SZaibo Xu 
637416d8220SZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req)
638416d8220SZaibo Xu {
639416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
640416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
641416d8220SZaibo Xu 
642416d8220SZaibo Xu 	atomic_dec(&qp_ctx->pending_reqs);
643416d8220SZaibo Xu 	sec_free_req_id(req);
644416d8220SZaibo Xu 
645416d8220SZaibo Xu 	/* IV output at encrypto of CBC mode */
646416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
647416d8220SZaibo Xu 		sec_update_iv(req);
648416d8220SZaibo Xu 
649ca0d158dSZaibo Xu 	if (req->fake_busy)
650416d8220SZaibo Xu 		sk_req->base.complete(&sk_req->base, -EINPROGRESS);
651416d8220SZaibo Xu 
652416d8220SZaibo Xu 	sk_req->base.complete(&sk_req->base, req->err_type);
653416d8220SZaibo Xu }
654416d8220SZaibo Xu 
655416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
656416d8220SZaibo Xu {
657416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
658416d8220SZaibo Xu 
659416d8220SZaibo Xu 	atomic_dec(&qp_ctx->pending_reqs);
660416d8220SZaibo Xu 	sec_free_req_id(req);
661*a181647cSZaibo Xu 	sec_free_queue_id(ctx, req);
662416d8220SZaibo Xu }
663416d8220SZaibo Xu 
664416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
665416d8220SZaibo Xu {
666416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
667*a181647cSZaibo Xu 	int queue_id, ret;
668416d8220SZaibo Xu 
669416d8220SZaibo Xu 	/* To load balance */
670*a181647cSZaibo Xu 	queue_id = sec_alloc_queue_id(ctx, req);
671*a181647cSZaibo Xu 	qp_ctx = &ctx->qp_ctx[queue_id];
672416d8220SZaibo Xu 
673416d8220SZaibo Xu 	req->req_id = sec_alloc_req_id(req, qp_ctx);
674416d8220SZaibo Xu 	if (req->req_id < 0) {
675*a181647cSZaibo Xu 		sec_free_queue_id(ctx, req);
676416d8220SZaibo Xu 		return req->req_id;
677416d8220SZaibo Xu 	}
678416d8220SZaibo Xu 
679416d8220SZaibo Xu 	if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs))
680ca0d158dSZaibo Xu 		req->fake_busy = true;
681416d8220SZaibo Xu 	else
682ca0d158dSZaibo Xu 		req->fake_busy = false;
683416d8220SZaibo Xu 
684416d8220SZaibo Xu 	ret = ctx->req_op->get_res(ctx, req);
685416d8220SZaibo Xu 	if (ret) {
686416d8220SZaibo Xu 		atomic_dec(&qp_ctx->pending_reqs);
687416d8220SZaibo Xu 		sec_request_uninit(ctx, req);
688416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "get resources failed!\n");
689416d8220SZaibo Xu 	}
690416d8220SZaibo Xu 
691416d8220SZaibo Xu 	return ret;
692416d8220SZaibo Xu }
693416d8220SZaibo Xu 
694416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
695416d8220SZaibo Xu {
696416d8220SZaibo Xu 	int ret;
697416d8220SZaibo Xu 
698416d8220SZaibo Xu 	ret = sec_request_init(ctx, req);
699416d8220SZaibo Xu 	if (ret)
700416d8220SZaibo Xu 		return ret;
701416d8220SZaibo Xu 
702416d8220SZaibo Xu 	ret = sec_request_transfer(ctx, req);
703416d8220SZaibo Xu 	if (ret)
704416d8220SZaibo Xu 		goto err_uninit_req;
705416d8220SZaibo Xu 
706416d8220SZaibo Xu 	/* Output IV as decrypto */
707416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
708416d8220SZaibo Xu 		sec_update_iv(req);
709416d8220SZaibo Xu 
710416d8220SZaibo Xu 	ret = ctx->req_op->bd_send(ctx, req);
711416d8220SZaibo Xu 	if (ret != -EBUSY && ret != -EINPROGRESS) {
712a718cfceSZaibo Xu 		dev_err_ratelimited(SEC_CTX_DEV(ctx), "send sec request failed!\n");
713416d8220SZaibo Xu 		goto err_send_req;
714416d8220SZaibo Xu 	}
715416d8220SZaibo Xu 
716416d8220SZaibo Xu 	return ret;
717416d8220SZaibo Xu 
718416d8220SZaibo Xu err_send_req:
719416d8220SZaibo Xu 	/* As failing, restore the IV from user */
720416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
721416d8220SZaibo Xu 		memcpy(req->c_req.sk_req->iv, req->c_req.c_ivin,
722416d8220SZaibo Xu 		       ctx->c_ctx.ivsize);
723416d8220SZaibo Xu 
724416d8220SZaibo Xu 	sec_request_untransfer(ctx, req);
725416d8220SZaibo Xu err_uninit_req:
726416d8220SZaibo Xu 	sec_request_uninit(ctx, req);
727416d8220SZaibo Xu 
728416d8220SZaibo Xu 	return ret;
729416d8220SZaibo Xu }
730416d8220SZaibo Xu 
731*a181647cSZaibo Xu static const struct sec_req_op sec_skcipher_req_ops = {
732416d8220SZaibo Xu 	.get_res	= sec_skcipher_get_res,
733416d8220SZaibo Xu 	.resource_alloc	= sec_skcipher_resource_alloc,
734416d8220SZaibo Xu 	.resource_free	= sec_skcipher_resource_free,
735416d8220SZaibo Xu 	.buf_map	= sec_skcipher_sgl_map,
736416d8220SZaibo Xu 	.buf_unmap	= sec_skcipher_sgl_unmap,
737416d8220SZaibo Xu 	.do_transfer	= sec_skcipher_copy_iv,
738416d8220SZaibo Xu 	.bd_fill	= sec_skcipher_bd_fill,
739416d8220SZaibo Xu 	.bd_send	= sec_bd_send,
740416d8220SZaibo Xu 	.callback	= sec_skcipher_callback,
741416d8220SZaibo Xu 	.process	= sec_process,
742416d8220SZaibo Xu };
743416d8220SZaibo Xu 
744416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
745416d8220SZaibo Xu {
746416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
747416d8220SZaibo Xu 
748*a181647cSZaibo Xu 	ctx->req_op = &sec_skcipher_req_ops;
749416d8220SZaibo Xu 
750416d8220SZaibo Xu 	return sec_skcipher_init(tfm);
751416d8220SZaibo Xu }
752416d8220SZaibo Xu 
753416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
754416d8220SZaibo Xu {
755*a181647cSZaibo Xu 	sec_skcipher_uninit(tfm);
756416d8220SZaibo Xu }
757416d8220SZaibo Xu 
758416d8220SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx,
759416d8220SZaibo Xu 				    struct skcipher_request *sk_req)
760416d8220SZaibo Xu {
761416d8220SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
762416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
763416d8220SZaibo Xu 
764416d8220SZaibo Xu 	if (!sk_req->src || !sk_req->dst) {
765416d8220SZaibo Xu 		dev_err(dev, "skcipher input param error!\n");
766416d8220SZaibo Xu 		return -EINVAL;
767416d8220SZaibo Xu 	}
768416d8220SZaibo Xu 
769416d8220SZaibo Xu 	if (c_alg == SEC_CALG_3DES) {
770416d8220SZaibo Xu 		if (sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1)) {
771416d8220SZaibo Xu 			dev_err(dev, "skcipher 3des input length error!\n");
772416d8220SZaibo Xu 			return -EINVAL;
773416d8220SZaibo Xu 		}
774416d8220SZaibo Xu 		return 0;
775416d8220SZaibo Xu 	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
776416d8220SZaibo Xu 		if (sk_req->cryptlen & (AES_BLOCK_SIZE - 1)) {
777416d8220SZaibo Xu 			dev_err(dev, "skcipher aes input length error!\n");
778416d8220SZaibo Xu 			return -EINVAL;
779416d8220SZaibo Xu 		}
780416d8220SZaibo Xu 		return 0;
781416d8220SZaibo Xu 	}
782416d8220SZaibo Xu 
783416d8220SZaibo Xu 	dev_err(dev, "skcipher algorithm error!\n");
784416d8220SZaibo Xu 	return -EINVAL;
785416d8220SZaibo Xu }
786416d8220SZaibo Xu 
787416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
788416d8220SZaibo Xu {
789416d8220SZaibo Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
790416d8220SZaibo Xu 	struct sec_req *req = skcipher_request_ctx(sk_req);
791416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
792416d8220SZaibo Xu 	int ret;
793416d8220SZaibo Xu 
794416d8220SZaibo Xu 	if (!sk_req->cryptlen)
795416d8220SZaibo Xu 		return 0;
796416d8220SZaibo Xu 
797416d8220SZaibo Xu 	ret = sec_skcipher_param_check(ctx, sk_req);
798416d8220SZaibo Xu 	if (ret)
799416d8220SZaibo Xu 		return ret;
800416d8220SZaibo Xu 
801416d8220SZaibo Xu 	req->c_req.sk_req = sk_req;
802416d8220SZaibo Xu 	req->c_req.encrypt = encrypt;
803416d8220SZaibo Xu 	req->ctx = ctx;
804416d8220SZaibo Xu 
805416d8220SZaibo Xu 	return ctx->req_op->process(ctx, req);
806416d8220SZaibo Xu }
807416d8220SZaibo Xu 
808416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
809416d8220SZaibo Xu {
810416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, true);
811416d8220SZaibo Xu }
812416d8220SZaibo Xu 
813416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
814416d8220SZaibo Xu {
815416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, false);
816416d8220SZaibo Xu }
817416d8220SZaibo Xu 
818416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
819416d8220SZaibo Xu 	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
820416d8220SZaibo Xu {\
821416d8220SZaibo Xu 	.base = {\
822416d8220SZaibo Xu 		.cra_name = sec_cra_name,\
823416d8220SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
824416d8220SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
825416d8220SZaibo Xu 		.cra_flags = CRYPTO_ALG_ASYNC,\
826416d8220SZaibo Xu 		.cra_blocksize = blk_size,\
827416d8220SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
828416d8220SZaibo Xu 		.cra_module = THIS_MODULE,\
829416d8220SZaibo Xu 	},\
830416d8220SZaibo Xu 	.init = ctx_init,\
831416d8220SZaibo Xu 	.exit = ctx_exit,\
832416d8220SZaibo Xu 	.setkey = sec_set_key,\
833416d8220SZaibo Xu 	.decrypt = sec_skcipher_decrypt,\
834416d8220SZaibo Xu 	.encrypt = sec_skcipher_encrypt,\
835416d8220SZaibo Xu 	.min_keysize = sec_min_key_size,\
836416d8220SZaibo Xu 	.max_keysize = sec_max_key_size,\
837416d8220SZaibo Xu 	.ivsize = iv_size,\
838416d8220SZaibo Xu },
839416d8220SZaibo Xu 
840416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
841416d8220SZaibo Xu 	max_key_size, blk_size, iv_size) \
842416d8220SZaibo Xu 	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
843416d8220SZaibo Xu 	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
844416d8220SZaibo Xu 
845*a181647cSZaibo Xu static struct skcipher_alg sec_skciphers[] = {
846416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
847416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
848416d8220SZaibo Xu 			 AES_BLOCK_SIZE, 0)
849416d8220SZaibo Xu 
850416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
851416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
852416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
853416d8220SZaibo Xu 
854416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
855416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
856416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
857416d8220SZaibo Xu 
858416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
859416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
860416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, 0)
861416d8220SZaibo Xu 
862416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
863416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
864416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
865416d8220SZaibo Xu 
866416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
867416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
868416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
869416d8220SZaibo Xu 
870416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
871416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
872416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
873416d8220SZaibo Xu };
874416d8220SZaibo Xu 
875416d8220SZaibo Xu int sec_register_to_crypto(void)
876416d8220SZaibo Xu {
877416d8220SZaibo Xu 	int ret = 0;
878416d8220SZaibo Xu 
879416d8220SZaibo Xu 	/* To avoid repeat register */
880416d8220SZaibo Xu 	mutex_lock(&sec_algs_lock);
881416d8220SZaibo Xu 	if (++sec_active_devs == 1)
882*a181647cSZaibo Xu 		ret = crypto_register_skciphers(sec_skciphers,
883*a181647cSZaibo Xu 						ARRAY_SIZE(sec_skciphers));
884416d8220SZaibo Xu 	mutex_unlock(&sec_algs_lock);
885416d8220SZaibo Xu 
886416d8220SZaibo Xu 	return ret;
887416d8220SZaibo Xu }
888416d8220SZaibo Xu 
889416d8220SZaibo Xu void sec_unregister_from_crypto(void)
890416d8220SZaibo Xu {
891416d8220SZaibo Xu 	mutex_lock(&sec_algs_lock);
892416d8220SZaibo Xu 	if (--sec_active_devs == 0)
893*a181647cSZaibo Xu 		crypto_unregister_skciphers(sec_skciphers,
894*a181647cSZaibo Xu 					    ARRAY_SIZE(sec_skciphers));
895416d8220SZaibo Xu 	mutex_unlock(&sec_algs_lock);
896416d8220SZaibo Xu }
897