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)
38d6de2a59SZaibo Xu #define SEC_SQE_CFLAG		2
39d6de2a59SZaibo Xu #define SEC_SQE_DONE		0x1
40416d8220SZaibo Xu 
41416d8220SZaibo Xu static DEFINE_MUTEX(sec_algs_lock);
42416d8220SZaibo Xu static unsigned int sec_active_devs;
43416d8220SZaibo Xu 
44416d8220SZaibo Xu /* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
45a181647cSZaibo Xu static inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req)
46416d8220SZaibo Xu {
47416d8220SZaibo Xu 	if (req->c_req.encrypt)
48416d8220SZaibo Xu 		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
49416d8220SZaibo Xu 				 ctx->hlf_q_num;
50416d8220SZaibo Xu 
51416d8220SZaibo Xu 	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
52416d8220SZaibo Xu 				 ctx->hlf_q_num;
53416d8220SZaibo Xu }
54416d8220SZaibo Xu 
55a181647cSZaibo Xu static inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req)
56416d8220SZaibo Xu {
57416d8220SZaibo Xu 	if (req->c_req.encrypt)
58416d8220SZaibo Xu 		atomic_dec(&ctx->enc_qcyclic);
59416d8220SZaibo Xu 	else
60416d8220SZaibo Xu 		atomic_dec(&ctx->dec_qcyclic);
61416d8220SZaibo Xu }
62416d8220SZaibo Xu 
63416d8220SZaibo Xu static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
64416d8220SZaibo Xu {
65416d8220SZaibo Xu 	int req_id;
66416d8220SZaibo Xu 
67416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
68416d8220SZaibo Xu 
69416d8220SZaibo Xu 	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL,
70416d8220SZaibo Xu 				  0, QM_Q_DEPTH, GFP_ATOMIC);
71416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
72416d8220SZaibo Xu 	if (req_id < 0) {
73416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "alloc req id fail!\n");
74416d8220SZaibo Xu 		return req_id;
75416d8220SZaibo Xu 	}
76416d8220SZaibo Xu 
77416d8220SZaibo Xu 	req->qp_ctx = qp_ctx;
78416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = req;
79416d8220SZaibo Xu 	return req_id;
80416d8220SZaibo Xu }
81416d8220SZaibo Xu 
82416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req)
83416d8220SZaibo Xu {
84416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
85416d8220SZaibo Xu 	int req_id = req->req_id;
86416d8220SZaibo Xu 
87416d8220SZaibo Xu 	if (req_id < 0 || req_id >= QM_Q_DEPTH) {
88416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "free request id invalid!\n");
89416d8220SZaibo Xu 		return;
90416d8220SZaibo Xu 	}
91416d8220SZaibo Xu 
92416d8220SZaibo Xu 	qp_ctx->req_list[req_id] = NULL;
93416d8220SZaibo Xu 	req->qp_ctx = NULL;
94416d8220SZaibo Xu 
95416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
96416d8220SZaibo Xu 	idr_remove(&qp_ctx->req_idr, req_id);
97416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
98416d8220SZaibo Xu }
99416d8220SZaibo Xu 
100416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp)
101416d8220SZaibo Xu {
102416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
103416d8220SZaibo Xu 	struct sec_sqe *bd = resp;
104d6de2a59SZaibo Xu 	struct sec_ctx *ctx;
105d6de2a59SZaibo Xu 	struct sec_req *req;
106416d8220SZaibo Xu 	u16 done, flag;
107*310ea0acSZaibo Xu 	int err = 0;
108416d8220SZaibo Xu 	u8 type;
109416d8220SZaibo Xu 
110416d8220SZaibo Xu 	type = bd->type_cipher_auth & SEC_TYPE_MASK;
111d6de2a59SZaibo Xu 	if (type != SEC_BD_TYPE2) {
112416d8220SZaibo Xu 		pr_err("err bd type [%d]\n", type);
113416d8220SZaibo Xu 		return;
114416d8220SZaibo Xu 	}
115416d8220SZaibo Xu 
116d6de2a59SZaibo Xu 	req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)];
117d6de2a59SZaibo Xu 	req->err_type = bd->type2.error_type;
118d6de2a59SZaibo Xu 	ctx = req->ctx;
119d6de2a59SZaibo Xu 	done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
120d6de2a59SZaibo Xu 	flag = (le16_to_cpu(bd->type2.done_flag) &
121d6de2a59SZaibo Xu 		SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
122d6de2a59SZaibo Xu 	if (req->err_type || done != SEC_SQE_DONE ||
123*310ea0acSZaibo Xu 	    flag != SEC_SQE_CFLAG) {
124d6de2a59SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx),
125d6de2a59SZaibo Xu 			"err_type[%d],done[%d],flag[%d]\n",
126d6de2a59SZaibo Xu 			req->err_type, done, flag);
127*310ea0acSZaibo Xu 		err = -EIO;
128*310ea0acSZaibo Xu 	}
1291e9bc276SZaibo Xu 
130d6de2a59SZaibo Xu 	atomic64_inc(&ctx->sec->debug.dfx.recv_cnt);
131416d8220SZaibo Xu 
132d6de2a59SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
133d6de2a59SZaibo Xu 
134*310ea0acSZaibo Xu 	ctx->req_op->callback(ctx, req, err);
135416d8220SZaibo Xu }
136416d8220SZaibo Xu 
137416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
138416d8220SZaibo Xu {
139416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
140416d8220SZaibo Xu 	int ret;
141416d8220SZaibo Xu 
142416d8220SZaibo Xu 	mutex_lock(&qp_ctx->req_lock);
143416d8220SZaibo Xu 	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
144416d8220SZaibo Xu 	mutex_unlock(&qp_ctx->req_lock);
145cb1eeb75SArnd Bergmann 	atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
146416d8220SZaibo Xu 
147416d8220SZaibo Xu 	if (ret == -EBUSY)
148416d8220SZaibo Xu 		return -ENOBUFS;
149416d8220SZaibo Xu 
150416d8220SZaibo Xu 	if (!ret) {
151ca0d158dSZaibo Xu 		if (req->fake_busy)
152416d8220SZaibo Xu 			ret = -EBUSY;
153416d8220SZaibo Xu 		else
154416d8220SZaibo Xu 			ret = -EINPROGRESS;
155416d8220SZaibo Xu 	}
156416d8220SZaibo Xu 
157416d8220SZaibo Xu 	return ret;
158416d8220SZaibo Xu }
159416d8220SZaibo Xu 
1607c7d902aSZaibo Xu /* Get DMA memory resources */
1617c7d902aSZaibo Xu static int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
1627c7d902aSZaibo Xu {
1637c7d902aSZaibo Xu 	int i;
1647c7d902aSZaibo Xu 
1657c7d902aSZaibo Xu 	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
1667c7d902aSZaibo Xu 					 &res->c_ivin_dma, GFP_KERNEL);
1677c7d902aSZaibo Xu 	if (!res->c_ivin)
1687c7d902aSZaibo Xu 		return -ENOMEM;
1697c7d902aSZaibo Xu 
1707c7d902aSZaibo Xu 	for (i = 1; i < QM_Q_DEPTH; i++) {
1717c7d902aSZaibo Xu 		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
1727c7d902aSZaibo Xu 		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
1737c7d902aSZaibo Xu 	}
1747c7d902aSZaibo Xu 
1757c7d902aSZaibo Xu 	return 0;
1767c7d902aSZaibo Xu }
1777c7d902aSZaibo Xu 
1787c7d902aSZaibo Xu static void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
1797c7d902aSZaibo Xu {
1807c7d902aSZaibo Xu 	if (res->c_ivin)
1817c7d902aSZaibo Xu 		dma_free_coherent(dev, SEC_TOTAL_IV_SZ,
1827c7d902aSZaibo Xu 				  res->c_ivin, res->c_ivin_dma);
1837c7d902aSZaibo Xu }
1847c7d902aSZaibo Xu 
1857c7d902aSZaibo Xu static int sec_alg_resource_alloc(struct sec_ctx *ctx,
1867c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
1877c7d902aSZaibo Xu {
1887c7d902aSZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
1897c7d902aSZaibo Xu 
1907c7d902aSZaibo Xu 	return sec_alloc_civ_resource(dev, qp_ctx->res);
1917c7d902aSZaibo Xu }
1927c7d902aSZaibo Xu 
1937c7d902aSZaibo Xu static void sec_alg_resource_free(struct sec_ctx *ctx,
1947c7d902aSZaibo Xu 				  struct sec_qp_ctx *qp_ctx)
1957c7d902aSZaibo Xu {
1967c7d902aSZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
1977c7d902aSZaibo Xu 
1987c7d902aSZaibo Xu 	sec_free_civ_resource(dev, qp_ctx->res);
1997c7d902aSZaibo Xu }
2007c7d902aSZaibo Xu 
201416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
202416d8220SZaibo Xu 			     int qp_ctx_id, int alg_type)
203416d8220SZaibo Xu {
204416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
205416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
206416d8220SZaibo Xu 	struct hisi_qp *qp;
207416d8220SZaibo Xu 	int ret = -ENOMEM;
208416d8220SZaibo Xu 
209416d8220SZaibo Xu 	qp = hisi_qm_create_qp(qm, alg_type);
210416d8220SZaibo Xu 	if (IS_ERR(qp))
211416d8220SZaibo Xu 		return PTR_ERR(qp);
212416d8220SZaibo Xu 
213416d8220SZaibo Xu 	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
214416d8220SZaibo Xu 	qp->req_type = 0;
215416d8220SZaibo Xu 	qp->qp_ctx = qp_ctx;
216416d8220SZaibo Xu 	qp->req_cb = sec_req_cb;
217416d8220SZaibo Xu 	qp_ctx->qp = qp;
218416d8220SZaibo Xu 	qp_ctx->ctx = ctx;
219416d8220SZaibo Xu 
220416d8220SZaibo Xu 	mutex_init(&qp_ctx->req_lock);
221416d8220SZaibo Xu 	atomic_set(&qp_ctx->pending_reqs, 0);
222416d8220SZaibo Xu 	idr_init(&qp_ctx->req_idr);
223416d8220SZaibo Xu 
224416d8220SZaibo Xu 	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
225416d8220SZaibo Xu 						     SEC_SGL_SGE_NR);
2268a6b8f4dSDan Carpenter 	if (IS_ERR(qp_ctx->c_in_pool)) {
227416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for input!\n");
2287c7d902aSZaibo Xu 		goto err_destroy_idr;
229416d8220SZaibo Xu 	}
230416d8220SZaibo Xu 
231416d8220SZaibo Xu 	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
232416d8220SZaibo Xu 						      SEC_SGL_SGE_NR);
2338a6b8f4dSDan Carpenter 	if (IS_ERR(qp_ctx->c_out_pool)) {
234416d8220SZaibo Xu 		dev_err(dev, "fail to create sgl pool for output!\n");
235416d8220SZaibo Xu 		goto err_free_c_in_pool;
236416d8220SZaibo Xu 	}
237416d8220SZaibo Xu 
2387c7d902aSZaibo Xu 	ret = sec_alg_resource_alloc(ctx, qp_ctx);
239416d8220SZaibo Xu 	if (ret)
240416d8220SZaibo Xu 		goto err_free_c_out_pool;
241416d8220SZaibo Xu 
242416d8220SZaibo Xu 	ret = hisi_qm_start_qp(qp, 0);
243416d8220SZaibo Xu 	if (ret < 0)
244416d8220SZaibo Xu 		goto err_queue_free;
245416d8220SZaibo Xu 
246416d8220SZaibo Xu 	return 0;
247416d8220SZaibo Xu 
248416d8220SZaibo Xu err_queue_free:
2497c7d902aSZaibo Xu 	sec_alg_resource_free(ctx, qp_ctx);
250416d8220SZaibo Xu err_free_c_out_pool:
251416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
252416d8220SZaibo Xu err_free_c_in_pool:
253416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
254416d8220SZaibo Xu err_destroy_idr:
255416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
256416d8220SZaibo Xu 	hisi_qm_release_qp(qp);
257416d8220SZaibo Xu 
258416d8220SZaibo Xu 	return ret;
259416d8220SZaibo Xu }
260416d8220SZaibo Xu 
261416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx,
262416d8220SZaibo Xu 			       struct sec_qp_ctx *qp_ctx)
263416d8220SZaibo Xu {
264416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
265416d8220SZaibo Xu 
266416d8220SZaibo Xu 	hisi_qm_stop_qp(qp_ctx->qp);
2677c7d902aSZaibo Xu 	sec_alg_resource_free(ctx, qp_ctx);
268416d8220SZaibo Xu 
269416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
270416d8220SZaibo Xu 	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
271416d8220SZaibo Xu 
272416d8220SZaibo Xu 	idr_destroy(&qp_ctx->req_idr);
273416d8220SZaibo Xu 	hisi_qm_release_qp(qp_ctx->qp);
274416d8220SZaibo Xu }
275416d8220SZaibo Xu 
276416d8220SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm)
277416d8220SZaibo Xu {
278416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
279416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx;
280416d8220SZaibo Xu 	struct sec_dev *sec;
281416d8220SZaibo Xu 	struct device *dev;
282416d8220SZaibo Xu 	struct hisi_qm *qm;
283416d8220SZaibo Xu 	int i, ret;
284416d8220SZaibo Xu 
285416d8220SZaibo Xu 	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
286416d8220SZaibo Xu 
287416d8220SZaibo Xu 	sec = sec_find_device(cpu_to_node(smp_processor_id()));
288416d8220SZaibo Xu 	if (!sec) {
289a718cfceSZaibo Xu 		pr_err("Can not find proper Hisilicon SEC device!\n");
290416d8220SZaibo Xu 		return -ENODEV;
291416d8220SZaibo Xu 	}
292416d8220SZaibo Xu 	ctx->sec = sec;
293416d8220SZaibo Xu 	qm = &sec->qm;
294416d8220SZaibo Xu 	dev = &qm->pdev->dev;
295a718cfceSZaibo Xu 	ctx->hlf_q_num = sec->ctx_q_num >> 1;
296416d8220SZaibo Xu 
297416d8220SZaibo Xu 	/* Half of queue depth is taken as fake requests limit in the queue. */
298a718cfceSZaibo Xu 	ctx->fake_req_limit = QM_Q_DEPTH >> 1;
299416d8220SZaibo Xu 	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
300416d8220SZaibo Xu 			      GFP_KERNEL);
301416d8220SZaibo Xu 	if (!ctx->qp_ctx)
302416d8220SZaibo Xu 		return -ENOMEM;
303416d8220SZaibo Xu 
304416d8220SZaibo Xu 	for (i = 0; i < sec->ctx_q_num; i++) {
305416d8220SZaibo Xu 		ret = sec_create_qp_ctx(qm, ctx, i, 0);
306416d8220SZaibo Xu 		if (ret)
307416d8220SZaibo Xu 			goto err_sec_release_qp_ctx;
308416d8220SZaibo Xu 	}
309416d8220SZaibo Xu 
310416d8220SZaibo Xu 	c_ctx = &ctx->c_ctx;
311416d8220SZaibo Xu 	c_ctx->ivsize = crypto_skcipher_ivsize(tfm);
312416d8220SZaibo Xu 	if (c_ctx->ivsize > SEC_IV_SIZE) {
313416d8220SZaibo Xu 		dev_err(dev, "get error iv size!\n");
314416d8220SZaibo Xu 		ret = -EINVAL;
315416d8220SZaibo Xu 		goto err_sec_release_qp_ctx;
316416d8220SZaibo Xu 	}
317416d8220SZaibo Xu 	c_ctx->c_key = dma_alloc_coherent(dev, SEC_MAX_KEY_SIZE,
318416d8220SZaibo Xu 					  &c_ctx->c_key_dma, GFP_KERNEL);
319416d8220SZaibo Xu 	if (!c_ctx->c_key) {
320416d8220SZaibo Xu 		ret = -ENOMEM;
321416d8220SZaibo Xu 		goto err_sec_release_qp_ctx;
322416d8220SZaibo Xu 	}
323416d8220SZaibo Xu 
324416d8220SZaibo Xu 	return 0;
325416d8220SZaibo Xu 
326416d8220SZaibo Xu err_sec_release_qp_ctx:
327416d8220SZaibo Xu 	for (i = i - 1; i >= 0; i--)
328416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
329416d8220SZaibo Xu 
330416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
331416d8220SZaibo Xu 	return ret;
332416d8220SZaibo Xu }
333416d8220SZaibo Xu 
334a181647cSZaibo Xu static void sec_skcipher_uninit(struct crypto_skcipher *tfm)
335416d8220SZaibo Xu {
336416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
337416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
338416d8220SZaibo Xu 	int i = 0;
339416d8220SZaibo Xu 
340416d8220SZaibo Xu 	if (c_ctx->c_key) {
341416d8220SZaibo Xu 		dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
342416d8220SZaibo Xu 				  c_ctx->c_key, c_ctx->c_key_dma);
343416d8220SZaibo Xu 		c_ctx->c_key = NULL;
344416d8220SZaibo Xu 	}
345416d8220SZaibo Xu 
346416d8220SZaibo Xu 	for (i = 0; i < ctx->sec->ctx_q_num; i++)
347416d8220SZaibo Xu 		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
348416d8220SZaibo Xu 
349416d8220SZaibo Xu 	kfree(ctx->qp_ctx);
350416d8220SZaibo Xu }
351416d8220SZaibo Xu 
352416d8220SZaibo Xu static int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx,
353416d8220SZaibo Xu 				    const u32 keylen,
354416d8220SZaibo Xu 				    const enum sec_cmode c_mode)
355416d8220SZaibo Xu {
356416d8220SZaibo Xu 	switch (keylen) {
357416d8220SZaibo Xu 	case SEC_DES3_2KEY_SIZE:
358416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
359416d8220SZaibo Xu 		break;
360416d8220SZaibo Xu 	case SEC_DES3_3KEY_SIZE:
361416d8220SZaibo Xu 		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
362416d8220SZaibo Xu 		break;
363416d8220SZaibo Xu 	default:
364416d8220SZaibo Xu 		return -EINVAL;
365416d8220SZaibo Xu 	}
366416d8220SZaibo Xu 
367416d8220SZaibo Xu 	return 0;
368416d8220SZaibo Xu }
369416d8220SZaibo Xu 
370416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
371416d8220SZaibo Xu 				       const u32 keylen,
372416d8220SZaibo Xu 				       const enum sec_cmode c_mode)
373416d8220SZaibo Xu {
374416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
375416d8220SZaibo Xu 		switch (keylen) {
376416d8220SZaibo Xu 		case SEC_XTS_MIN_KEY_SIZE:
377416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
378416d8220SZaibo Xu 			break;
379416d8220SZaibo Xu 		case SEC_XTS_MAX_KEY_SIZE:
380416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
381416d8220SZaibo Xu 			break;
382416d8220SZaibo Xu 		default:
383416d8220SZaibo Xu 			pr_err("hisi_sec2: xts mode key error!\n");
384416d8220SZaibo Xu 			return -EINVAL;
385416d8220SZaibo Xu 		}
386416d8220SZaibo Xu 	} else {
387416d8220SZaibo Xu 		switch (keylen) {
388416d8220SZaibo Xu 		case AES_KEYSIZE_128:
389416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_128BIT;
390416d8220SZaibo Xu 			break;
391416d8220SZaibo Xu 		case AES_KEYSIZE_192:
392416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_192BIT;
393416d8220SZaibo Xu 			break;
394416d8220SZaibo Xu 		case AES_KEYSIZE_256:
395416d8220SZaibo Xu 			c_ctx->c_key_len = SEC_CKEY_256BIT;
396416d8220SZaibo Xu 			break;
397416d8220SZaibo Xu 		default:
398416d8220SZaibo Xu 			pr_err("hisi_sec2: aes key error!\n");
399416d8220SZaibo Xu 			return -EINVAL;
400416d8220SZaibo Xu 		}
401416d8220SZaibo Xu 	}
402416d8220SZaibo Xu 
403416d8220SZaibo Xu 	return 0;
404416d8220SZaibo Xu }
405416d8220SZaibo Xu 
406416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
407416d8220SZaibo Xu 			       const u32 keylen, const enum sec_calg c_alg,
408416d8220SZaibo Xu 			       const enum sec_cmode c_mode)
409416d8220SZaibo Xu {
410416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
411416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
412416d8220SZaibo Xu 	int ret;
413416d8220SZaibo Xu 
414416d8220SZaibo Xu 	if (c_mode == SEC_CMODE_XTS) {
415416d8220SZaibo Xu 		ret = xts_verify_key(tfm, key, keylen);
416416d8220SZaibo Xu 		if (ret) {
417416d8220SZaibo Xu 			dev_err(SEC_CTX_DEV(ctx), "xts mode key err!\n");
418416d8220SZaibo Xu 			return ret;
419416d8220SZaibo Xu 		}
420416d8220SZaibo Xu 	}
421416d8220SZaibo Xu 
422416d8220SZaibo Xu 	c_ctx->c_alg  = c_alg;
423416d8220SZaibo Xu 	c_ctx->c_mode = c_mode;
424416d8220SZaibo Xu 
425416d8220SZaibo Xu 	switch (c_alg) {
426416d8220SZaibo Xu 	case SEC_CALG_3DES:
427416d8220SZaibo Xu 		ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode);
428416d8220SZaibo Xu 		break;
429416d8220SZaibo Xu 	case SEC_CALG_AES:
430416d8220SZaibo Xu 	case SEC_CALG_SM4:
431416d8220SZaibo Xu 		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
432416d8220SZaibo Xu 		break;
433416d8220SZaibo Xu 	default:
434416d8220SZaibo Xu 		return -EINVAL;
435416d8220SZaibo Xu 	}
436416d8220SZaibo Xu 
437416d8220SZaibo Xu 	if (ret) {
438416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(ctx), "set sec key err!\n");
439416d8220SZaibo Xu 		return ret;
440416d8220SZaibo Xu 	}
441416d8220SZaibo Xu 
442416d8220SZaibo Xu 	memcpy(c_ctx->c_key, key, keylen);
443416d8220SZaibo Xu 
444416d8220SZaibo Xu 	return 0;
445416d8220SZaibo Xu }
446416d8220SZaibo Xu 
447416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
448416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
449416d8220SZaibo Xu 	u32 keylen)							\
450416d8220SZaibo Xu {									\
451416d8220SZaibo Xu 	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
452416d8220SZaibo Xu }
453416d8220SZaibo Xu 
454416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
455416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
456416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
457416d8220SZaibo Xu 
458416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
459416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
460416d8220SZaibo Xu 
461416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
462416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
463416d8220SZaibo Xu 
464a181647cSZaibo Xu static int sec_cipher_map(struct device *dev, struct sec_req *req,
465416d8220SZaibo Xu 			  struct scatterlist *src, struct scatterlist *dst)
466416d8220SZaibo Xu {
467416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
468416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
469416d8220SZaibo Xu 
470416d8220SZaibo Xu 	c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
471416d8220SZaibo Xu 						    qp_ctx->c_in_pool,
472416d8220SZaibo Xu 						    req->req_id,
473416d8220SZaibo Xu 						    &c_req->c_in_dma);
474416d8220SZaibo Xu 
475416d8220SZaibo Xu 	if (IS_ERR(c_req->c_in)) {
476416d8220SZaibo Xu 		dev_err(dev, "fail to dma map input sgl buffers!\n");
477416d8220SZaibo Xu 		return PTR_ERR(c_req->c_in);
478416d8220SZaibo Xu 	}
479416d8220SZaibo Xu 
480416d8220SZaibo Xu 	if (dst == src) {
481416d8220SZaibo Xu 		c_req->c_out = c_req->c_in;
482416d8220SZaibo Xu 		c_req->c_out_dma = c_req->c_in_dma;
483416d8220SZaibo Xu 	} else {
484416d8220SZaibo Xu 		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
485416d8220SZaibo Xu 							     qp_ctx->c_out_pool,
486416d8220SZaibo Xu 							     req->req_id,
487416d8220SZaibo Xu 							     &c_req->c_out_dma);
488416d8220SZaibo Xu 
489416d8220SZaibo Xu 		if (IS_ERR(c_req->c_out)) {
490416d8220SZaibo Xu 			dev_err(dev, "fail to dma map output sgl buffers!\n");
491416d8220SZaibo Xu 			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
492416d8220SZaibo Xu 			return PTR_ERR(c_req->c_out);
493416d8220SZaibo Xu 		}
494416d8220SZaibo Xu 	}
495416d8220SZaibo Xu 
496416d8220SZaibo Xu 	return 0;
497416d8220SZaibo Xu }
498416d8220SZaibo Xu 
499a181647cSZaibo Xu static void sec_cipher_unmap(struct device *dev, struct sec_cipher_req *req,
500a181647cSZaibo Xu 			     struct scatterlist *src, struct scatterlist *dst)
501a181647cSZaibo Xu {
502a181647cSZaibo Xu 	if (dst != src)
503a181647cSZaibo Xu 		hisi_acc_sg_buf_unmap(dev, src, req->c_in);
504a181647cSZaibo Xu 
505a181647cSZaibo Xu 	hisi_acc_sg_buf_unmap(dev, dst, req->c_out);
506a181647cSZaibo Xu }
507a181647cSZaibo Xu 
508416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
509416d8220SZaibo Xu {
510a181647cSZaibo Xu 	struct skcipher_request *sq = req->c_req.sk_req;
511416d8220SZaibo Xu 
512a181647cSZaibo Xu 	return sec_cipher_map(SEC_CTX_DEV(ctx), req, sq->src, sq->dst);
513416d8220SZaibo Xu }
514416d8220SZaibo Xu 
515416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
516416d8220SZaibo Xu {
517416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
518416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
519416d8220SZaibo Xu 	struct skcipher_request *sk_req = c_req->sk_req;
520416d8220SZaibo Xu 
521a181647cSZaibo Xu 	sec_cipher_unmap(dev, c_req, sk_req->src, sk_req->dst);
522416d8220SZaibo Xu }
523416d8220SZaibo Xu 
524416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
525416d8220SZaibo Xu {
526416d8220SZaibo Xu 	int ret;
527416d8220SZaibo Xu 
528416d8220SZaibo Xu 	ret = ctx->req_op->buf_map(ctx, req);
529416d8220SZaibo Xu 	if (ret)
530416d8220SZaibo Xu 		return ret;
531416d8220SZaibo Xu 
532416d8220SZaibo Xu 	ctx->req_op->do_transfer(ctx, req);
533416d8220SZaibo Xu 
534416d8220SZaibo Xu 	ret = ctx->req_op->bd_fill(ctx, req);
535416d8220SZaibo Xu 	if (ret)
536416d8220SZaibo Xu 		goto unmap_req_buf;
537416d8220SZaibo Xu 
538416d8220SZaibo Xu 	return ret;
539416d8220SZaibo Xu 
540416d8220SZaibo Xu unmap_req_buf:
541416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
542416d8220SZaibo Xu 
543416d8220SZaibo Xu 	return ret;
544416d8220SZaibo Xu }
545416d8220SZaibo Xu 
546416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
547416d8220SZaibo Xu {
548416d8220SZaibo Xu 	ctx->req_op->buf_unmap(ctx, req);
549416d8220SZaibo Xu }
550416d8220SZaibo Xu 
551416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
552416d8220SZaibo Xu {
553416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
5547c7d902aSZaibo Xu 	u8 *c_ivin = req->qp_ctx->res[req->req_id].c_ivin;
555416d8220SZaibo Xu 
5567c7d902aSZaibo Xu 	memcpy(c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
557416d8220SZaibo Xu }
558416d8220SZaibo Xu 
559416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
560416d8220SZaibo Xu {
561416d8220SZaibo Xu 	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
562416d8220SZaibo Xu 	struct sec_cipher_req *c_req = &req->c_req;
563416d8220SZaibo Xu 	struct sec_sqe *sec_sqe = &req->sec_sqe;
564416d8220SZaibo Xu 	u8 scene, sa_type, da_type;
565416d8220SZaibo Xu 	u8 bd_type, cipher;
5667c7d902aSZaibo Xu 	u8 de = 0;
567416d8220SZaibo Xu 
568416d8220SZaibo Xu 	memset(sec_sqe, 0, sizeof(struct sec_sqe));
569416d8220SZaibo Xu 
570416d8220SZaibo Xu 	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
5717c7d902aSZaibo Xu 	sec_sqe->type2.c_ivin_addr =
5727c7d902aSZaibo Xu 		cpu_to_le64(req->qp_ctx->res[req->req_id].c_ivin_dma);
573416d8220SZaibo Xu 	sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma);
574416d8220SZaibo Xu 	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
575416d8220SZaibo Xu 
576416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
577416d8220SZaibo Xu 						SEC_CMODE_OFFSET);
578416d8220SZaibo Xu 	sec_sqe->type2.c_alg = c_ctx->c_alg;
579416d8220SZaibo Xu 	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
580416d8220SZaibo Xu 						SEC_CKEY_OFFSET);
581416d8220SZaibo Xu 
582416d8220SZaibo Xu 	bd_type = SEC_BD_TYPE2;
583416d8220SZaibo Xu 	if (c_req->encrypt)
584416d8220SZaibo Xu 		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
585416d8220SZaibo Xu 	else
586416d8220SZaibo Xu 		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
587416d8220SZaibo Xu 	sec_sqe->type_cipher_auth = bd_type | cipher;
588416d8220SZaibo Xu 
589416d8220SZaibo Xu 	sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
590416d8220SZaibo Xu 	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
591416d8220SZaibo Xu 	if (c_req->c_in_dma != c_req->c_out_dma)
592416d8220SZaibo Xu 		de = 0x1 << SEC_DE_OFFSET;
593416d8220SZaibo Xu 
594416d8220SZaibo Xu 	sec_sqe->sds_sa_type = (de | scene | sa_type);
595416d8220SZaibo Xu 
596416d8220SZaibo Xu 	/* Just set DST address type */
597416d8220SZaibo Xu 	da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
598416d8220SZaibo Xu 	sec_sqe->sdm_addr_type |= da_type;
599416d8220SZaibo Xu 
600416d8220SZaibo Xu 	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
601416d8220SZaibo Xu 	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
602416d8220SZaibo Xu 
603416d8220SZaibo Xu 	return 0;
604416d8220SZaibo Xu }
605416d8220SZaibo Xu 
606416d8220SZaibo Xu static void sec_update_iv(struct sec_req *req)
607416d8220SZaibo Xu {
608416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
609416d8220SZaibo Xu 	u32 iv_size = req->ctx->c_ctx.ivsize;
610416d8220SZaibo Xu 	struct scatterlist *sgl;
611416d8220SZaibo Xu 	size_t sz;
612416d8220SZaibo Xu 
613416d8220SZaibo Xu 	if (req->c_req.encrypt)
614416d8220SZaibo Xu 		sgl = sk_req->dst;
615416d8220SZaibo Xu 	else
616416d8220SZaibo Xu 		sgl = sk_req->src;
617416d8220SZaibo Xu 
618416d8220SZaibo Xu 	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), sk_req->iv,
619416d8220SZaibo Xu 				iv_size, sk_req->cryptlen - iv_size);
620416d8220SZaibo Xu 	if (sz != iv_size)
621416d8220SZaibo Xu 		dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n");
622416d8220SZaibo Xu }
623416d8220SZaibo Xu 
624*310ea0acSZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
625*310ea0acSZaibo Xu 				  int err)
626416d8220SZaibo Xu {
627416d8220SZaibo Xu 	struct skcipher_request *sk_req = req->c_req.sk_req;
628416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
629416d8220SZaibo Xu 
630416d8220SZaibo Xu 	atomic_dec(&qp_ctx->pending_reqs);
631416d8220SZaibo Xu 	sec_free_req_id(req);
632416d8220SZaibo Xu 
633416d8220SZaibo Xu 	/* IV output at encrypto of CBC mode */
634*310ea0acSZaibo Xu 	if (!err && ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
635416d8220SZaibo Xu 		sec_update_iv(req);
636416d8220SZaibo Xu 
637ca0d158dSZaibo Xu 	if (req->fake_busy)
638416d8220SZaibo Xu 		sk_req->base.complete(&sk_req->base, -EINPROGRESS);
639416d8220SZaibo Xu 
640*310ea0acSZaibo Xu 	sk_req->base.complete(&sk_req->base, err);
641416d8220SZaibo Xu }
642416d8220SZaibo Xu 
643416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
644416d8220SZaibo Xu {
645416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
646416d8220SZaibo Xu 
647416d8220SZaibo Xu 	atomic_dec(&qp_ctx->pending_reqs);
648416d8220SZaibo Xu 	sec_free_req_id(req);
649a181647cSZaibo Xu 	sec_free_queue_id(ctx, req);
650416d8220SZaibo Xu }
651416d8220SZaibo Xu 
652416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
653416d8220SZaibo Xu {
654416d8220SZaibo Xu 	struct sec_qp_ctx *qp_ctx;
6557c7d902aSZaibo Xu 	int queue_id;
656416d8220SZaibo Xu 
657416d8220SZaibo Xu 	/* To load balance */
658a181647cSZaibo Xu 	queue_id = sec_alloc_queue_id(ctx, req);
659a181647cSZaibo Xu 	qp_ctx = &ctx->qp_ctx[queue_id];
660416d8220SZaibo Xu 
661416d8220SZaibo Xu 	req->req_id = sec_alloc_req_id(req, qp_ctx);
662416d8220SZaibo Xu 	if (req->req_id < 0) {
663a181647cSZaibo Xu 		sec_free_queue_id(ctx, req);
664416d8220SZaibo Xu 		return req->req_id;
665416d8220SZaibo Xu 	}
666416d8220SZaibo Xu 
667416d8220SZaibo Xu 	if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs))
668ca0d158dSZaibo Xu 		req->fake_busy = true;
669416d8220SZaibo Xu 	else
670ca0d158dSZaibo Xu 		req->fake_busy = false;
671416d8220SZaibo Xu 
6727c7d902aSZaibo Xu 	return 0;
673416d8220SZaibo Xu }
674416d8220SZaibo Xu 
675416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
676416d8220SZaibo Xu {
677416d8220SZaibo Xu 	int ret;
678416d8220SZaibo Xu 
679416d8220SZaibo Xu 	ret = sec_request_init(ctx, req);
680416d8220SZaibo Xu 	if (ret)
681416d8220SZaibo Xu 		return ret;
682416d8220SZaibo Xu 
683416d8220SZaibo Xu 	ret = sec_request_transfer(ctx, req);
684416d8220SZaibo Xu 	if (ret)
685416d8220SZaibo Xu 		goto err_uninit_req;
686416d8220SZaibo Xu 
687416d8220SZaibo Xu 	/* Output IV as decrypto */
688416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
689416d8220SZaibo Xu 		sec_update_iv(req);
690416d8220SZaibo Xu 
691416d8220SZaibo Xu 	ret = ctx->req_op->bd_send(ctx, req);
692416d8220SZaibo Xu 	if (ret != -EBUSY && ret != -EINPROGRESS) {
693a718cfceSZaibo Xu 		dev_err_ratelimited(SEC_CTX_DEV(ctx), "send sec request failed!\n");
694416d8220SZaibo Xu 		goto err_send_req;
695416d8220SZaibo Xu 	}
696416d8220SZaibo Xu 
697416d8220SZaibo Xu 	return ret;
698416d8220SZaibo Xu 
699416d8220SZaibo Xu err_send_req:
700416d8220SZaibo Xu 	/* As failing, restore the IV from user */
701416d8220SZaibo Xu 	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
7027c7d902aSZaibo Xu 		memcpy(req->c_req.sk_req->iv,
7037c7d902aSZaibo Xu 		       req->qp_ctx->res[req->req_id].c_ivin,
704416d8220SZaibo Xu 		       ctx->c_ctx.ivsize);
705416d8220SZaibo Xu 
706416d8220SZaibo Xu 	sec_request_untransfer(ctx, req);
707416d8220SZaibo Xu err_uninit_req:
708416d8220SZaibo Xu 	sec_request_uninit(ctx, req);
709416d8220SZaibo Xu 
710416d8220SZaibo Xu 	return ret;
711416d8220SZaibo Xu }
712416d8220SZaibo Xu 
713a181647cSZaibo Xu static const struct sec_req_op sec_skcipher_req_ops = {
714416d8220SZaibo Xu 	.buf_map	= sec_skcipher_sgl_map,
715416d8220SZaibo Xu 	.buf_unmap	= sec_skcipher_sgl_unmap,
716416d8220SZaibo Xu 	.do_transfer	= sec_skcipher_copy_iv,
717416d8220SZaibo Xu 	.bd_fill	= sec_skcipher_bd_fill,
718416d8220SZaibo Xu 	.bd_send	= sec_bd_send,
719416d8220SZaibo Xu 	.callback	= sec_skcipher_callback,
720416d8220SZaibo Xu 	.process	= sec_process,
721416d8220SZaibo Xu };
722416d8220SZaibo Xu 
723416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
724416d8220SZaibo Xu {
725416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
726416d8220SZaibo Xu 
727a181647cSZaibo Xu 	ctx->req_op = &sec_skcipher_req_ops;
728416d8220SZaibo Xu 
729416d8220SZaibo Xu 	return sec_skcipher_init(tfm);
730416d8220SZaibo Xu }
731416d8220SZaibo Xu 
732416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
733416d8220SZaibo Xu {
734a181647cSZaibo Xu 	sec_skcipher_uninit(tfm);
735416d8220SZaibo Xu }
736416d8220SZaibo Xu 
737d6de2a59SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
738416d8220SZaibo Xu {
739d6de2a59SZaibo Xu 	struct skcipher_request *sk_req = sreq->c_req.sk_req;
740416d8220SZaibo Xu 	struct device *dev = SEC_CTX_DEV(ctx);
741d6de2a59SZaibo Xu 	u8 c_alg = ctx->c_ctx.c_alg;
742416d8220SZaibo Xu 
743416d8220SZaibo Xu 	if (!sk_req->src || !sk_req->dst) {
744416d8220SZaibo Xu 		dev_err(dev, "skcipher input param error!\n");
745416d8220SZaibo Xu 		return -EINVAL;
746416d8220SZaibo Xu 	}
747d6de2a59SZaibo Xu 	sreq->c_req.c_len = sk_req->cryptlen;
748416d8220SZaibo Xu 	if (c_alg == SEC_CALG_3DES) {
749416d8220SZaibo Xu 		if (sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1)) {
750416d8220SZaibo Xu 			dev_err(dev, "skcipher 3des input length error!\n");
751416d8220SZaibo Xu 			return -EINVAL;
752416d8220SZaibo Xu 		}
753416d8220SZaibo Xu 		return 0;
754416d8220SZaibo Xu 	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
755416d8220SZaibo Xu 		if (sk_req->cryptlen & (AES_BLOCK_SIZE - 1)) {
756416d8220SZaibo Xu 			dev_err(dev, "skcipher aes input length error!\n");
757416d8220SZaibo Xu 			return -EINVAL;
758416d8220SZaibo Xu 		}
759416d8220SZaibo Xu 		return 0;
760416d8220SZaibo Xu 	}
761416d8220SZaibo Xu 
762416d8220SZaibo Xu 	dev_err(dev, "skcipher algorithm error!\n");
763416d8220SZaibo Xu 	return -EINVAL;
764416d8220SZaibo Xu }
765416d8220SZaibo Xu 
766416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
767416d8220SZaibo Xu {
768416d8220SZaibo Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
769416d8220SZaibo Xu 	struct sec_req *req = skcipher_request_ctx(sk_req);
770416d8220SZaibo Xu 	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
771416d8220SZaibo Xu 	int ret;
772416d8220SZaibo Xu 
773416d8220SZaibo Xu 	if (!sk_req->cryptlen)
774416d8220SZaibo Xu 		return 0;
775416d8220SZaibo Xu 
776416d8220SZaibo Xu 	req->c_req.sk_req = sk_req;
777416d8220SZaibo Xu 	req->c_req.encrypt = encrypt;
778416d8220SZaibo Xu 	req->ctx = ctx;
779416d8220SZaibo Xu 
780d6de2a59SZaibo Xu 	ret = sec_skcipher_param_check(ctx, req);
781d6de2a59SZaibo Xu 	if (unlikely(ret))
782d6de2a59SZaibo Xu 		return -EINVAL;
783d6de2a59SZaibo Xu 
784416d8220SZaibo Xu 	return ctx->req_op->process(ctx, req);
785416d8220SZaibo Xu }
786416d8220SZaibo Xu 
787416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
788416d8220SZaibo Xu {
789416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, true);
790416d8220SZaibo Xu }
791416d8220SZaibo Xu 
792416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
793416d8220SZaibo Xu {
794416d8220SZaibo Xu 	return sec_skcipher_crypto(sk_req, false);
795416d8220SZaibo Xu }
796416d8220SZaibo Xu 
797416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
798416d8220SZaibo Xu 	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
799416d8220SZaibo Xu {\
800416d8220SZaibo Xu 	.base = {\
801416d8220SZaibo Xu 		.cra_name = sec_cra_name,\
802416d8220SZaibo Xu 		.cra_driver_name = "hisi_sec_"sec_cra_name,\
803416d8220SZaibo Xu 		.cra_priority = SEC_PRIORITY,\
804416d8220SZaibo Xu 		.cra_flags = CRYPTO_ALG_ASYNC,\
805416d8220SZaibo Xu 		.cra_blocksize = blk_size,\
806416d8220SZaibo Xu 		.cra_ctxsize = sizeof(struct sec_ctx),\
807416d8220SZaibo Xu 		.cra_module = THIS_MODULE,\
808416d8220SZaibo Xu 	},\
809416d8220SZaibo Xu 	.init = ctx_init,\
810416d8220SZaibo Xu 	.exit = ctx_exit,\
811416d8220SZaibo Xu 	.setkey = sec_set_key,\
812416d8220SZaibo Xu 	.decrypt = sec_skcipher_decrypt,\
813416d8220SZaibo Xu 	.encrypt = sec_skcipher_encrypt,\
814416d8220SZaibo Xu 	.min_keysize = sec_min_key_size,\
815416d8220SZaibo Xu 	.max_keysize = sec_max_key_size,\
816416d8220SZaibo Xu 	.ivsize = iv_size,\
817416d8220SZaibo Xu },
818416d8220SZaibo Xu 
819416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
820416d8220SZaibo Xu 	max_key_size, blk_size, iv_size) \
821416d8220SZaibo Xu 	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
822416d8220SZaibo Xu 	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
823416d8220SZaibo Xu 
824a181647cSZaibo Xu static struct skcipher_alg sec_skciphers[] = {
825416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
826416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
827416d8220SZaibo Xu 			 AES_BLOCK_SIZE, 0)
828416d8220SZaibo Xu 
829416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
830416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
831416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
832416d8220SZaibo Xu 
833416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
834416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
835416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
836416d8220SZaibo Xu 
837416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
838416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
839416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, 0)
840416d8220SZaibo Xu 
841416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
842416d8220SZaibo Xu 			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
843416d8220SZaibo Xu 			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
844416d8220SZaibo Xu 
845416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
846416d8220SZaibo Xu 			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
847416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
848416d8220SZaibo Xu 
849416d8220SZaibo Xu 	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
850416d8220SZaibo Xu 			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
851416d8220SZaibo Xu 			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
852416d8220SZaibo Xu };
853416d8220SZaibo Xu 
854416d8220SZaibo Xu int sec_register_to_crypto(void)
855416d8220SZaibo Xu {
856416d8220SZaibo Xu 	int ret = 0;
857416d8220SZaibo Xu 
858416d8220SZaibo Xu 	/* To avoid repeat register */
859416d8220SZaibo Xu 	mutex_lock(&sec_algs_lock);
860416d8220SZaibo Xu 	if (++sec_active_devs == 1)
861a181647cSZaibo Xu 		ret = crypto_register_skciphers(sec_skciphers,
862a181647cSZaibo Xu 						ARRAY_SIZE(sec_skciphers));
863416d8220SZaibo Xu 	mutex_unlock(&sec_algs_lock);
864416d8220SZaibo Xu 
865416d8220SZaibo Xu 	return ret;
866416d8220SZaibo Xu }
867416d8220SZaibo Xu 
868416d8220SZaibo Xu void sec_unregister_from_crypto(void)
869416d8220SZaibo Xu {
870416d8220SZaibo Xu 	mutex_lock(&sec_algs_lock);
871416d8220SZaibo Xu 	if (--sec_active_devs == 0)
872a181647cSZaibo Xu 		crypto_unregister_skciphers(sec_skciphers,
873a181647cSZaibo Xu 					    ARRAY_SIZE(sec_skciphers));
874416d8220SZaibo Xu 	mutex_unlock(&sec_algs_lock);
875416d8220SZaibo Xu }
876