xref: /dpdk/drivers/crypto/ionic/ionic_crypto_ops.c (revision 80518852e2f52bbe27b5763fb05031caf8da4788)
1dddfb0d9SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
2dddfb0d9SAndrew Boyer  * Copyright 2021-2024 Advanced Micro Devices, Inc.
3dddfb0d9SAndrew Boyer  */
4dddfb0d9SAndrew Boyer 
5dddfb0d9SAndrew Boyer #include <rte_cryptodev.h>
6dddfb0d9SAndrew Boyer #include <cryptodev_pmd.h>
7dddfb0d9SAndrew Boyer #include <rte_errno.h>
8dddfb0d9SAndrew Boyer #include <rte_malloc.h>
9dddfb0d9SAndrew Boyer #include <rte_mempool.h>
10dddfb0d9SAndrew Boyer 
11dddfb0d9SAndrew Boyer #include "ionic_crypto.h"
12dddfb0d9SAndrew Boyer 
13dddfb0d9SAndrew Boyer static int
14dddfb0d9SAndrew Boyer iocpt_op_config(struct rte_cryptodev *cdev,
15dddfb0d9SAndrew Boyer 		struct rte_cryptodev_config *config __rte_unused)
16dddfb0d9SAndrew Boyer {
17dddfb0d9SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
18dddfb0d9SAndrew Boyer 
19dddfb0d9SAndrew Boyer 	iocpt_configure(dev);
20dddfb0d9SAndrew Boyer 
21dddfb0d9SAndrew Boyer 	return 0;
22dddfb0d9SAndrew Boyer }
23dddfb0d9SAndrew Boyer 
24dddfb0d9SAndrew Boyer static int
25*80518852SAndrew Boyer iocpt_op_start(struct rte_cryptodev *cdev)
26*80518852SAndrew Boyer {
27*80518852SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
28*80518852SAndrew Boyer 
29*80518852SAndrew Boyer 	return iocpt_start(dev);
30*80518852SAndrew Boyer }
31*80518852SAndrew Boyer 
32*80518852SAndrew Boyer static void
33*80518852SAndrew Boyer iocpt_op_stop(struct rte_cryptodev *cdev)
34*80518852SAndrew Boyer {
35*80518852SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
36*80518852SAndrew Boyer 
37*80518852SAndrew Boyer 	return iocpt_stop(dev);
38*80518852SAndrew Boyer }
39*80518852SAndrew Boyer 
40*80518852SAndrew Boyer static int
41dddfb0d9SAndrew Boyer iocpt_op_close(struct rte_cryptodev *cdev)
42dddfb0d9SAndrew Boyer {
43dddfb0d9SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
44dddfb0d9SAndrew Boyer 
45dddfb0d9SAndrew Boyer 	iocpt_deinit(dev);
46dddfb0d9SAndrew Boyer 
47dddfb0d9SAndrew Boyer 	return 0;
48dddfb0d9SAndrew Boyer }
49dddfb0d9SAndrew Boyer 
50dddfb0d9SAndrew Boyer static void
51dddfb0d9SAndrew Boyer iocpt_op_info_get(struct rte_cryptodev *cdev, struct rte_cryptodev_info *info)
52dddfb0d9SAndrew Boyer {
53dddfb0d9SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
54dddfb0d9SAndrew Boyer 
55dddfb0d9SAndrew Boyer 	if (info == NULL)
56dddfb0d9SAndrew Boyer 		return;
57dddfb0d9SAndrew Boyer 
58dddfb0d9SAndrew Boyer 	info->max_nb_queue_pairs = dev->max_qps;
59dddfb0d9SAndrew Boyer 	info->feature_flags = dev->features;
60dddfb0d9SAndrew Boyer 	info->capabilities = iocpt_get_caps(info->feature_flags);
61dddfb0d9SAndrew Boyer 	info->sym.max_nb_sessions = dev->max_sessions;
62dddfb0d9SAndrew Boyer 	info->driver_id = dev->driver_id;
63dddfb0d9SAndrew Boyer 	info->min_mbuf_headroom_req = 0;
64dddfb0d9SAndrew Boyer 	info->min_mbuf_tailroom_req = 0;
65dddfb0d9SAndrew Boyer }
66dddfb0d9SAndrew Boyer 
67*80518852SAndrew Boyer static int
68*80518852SAndrew Boyer iocpt_op_queue_release(struct rte_cryptodev *cdev, uint16_t queue_id)
69*80518852SAndrew Boyer {
70*80518852SAndrew Boyer 	struct iocpt_crypto_q *cptq = cdev->data->queue_pairs[queue_id];
71*80518852SAndrew Boyer 
72*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "queue_id %u", queue_id);
73*80518852SAndrew Boyer 
74*80518852SAndrew Boyer 	assert(!(cptq->flags & IOCPT_Q_F_INITED));
75*80518852SAndrew Boyer 
76*80518852SAndrew Boyer 	iocpt_cryptoq_free(cptq);
77*80518852SAndrew Boyer 
78*80518852SAndrew Boyer 	cdev->data->queue_pairs[queue_id] = NULL;
79*80518852SAndrew Boyer 
80*80518852SAndrew Boyer 	return 0;
81*80518852SAndrew Boyer }
82*80518852SAndrew Boyer 
83*80518852SAndrew Boyer static int
84*80518852SAndrew Boyer iocpt_op_queue_setup(struct rte_cryptodev *cdev, uint16_t queue_id,
85*80518852SAndrew Boyer 		const struct rte_cryptodev_qp_conf *qp_conf,
86*80518852SAndrew Boyer 		int socket_id)
87*80518852SAndrew Boyer {
88*80518852SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
89*80518852SAndrew Boyer 	int err;
90*80518852SAndrew Boyer 
91*80518852SAndrew Boyer 	if (cdev->data->queue_pairs[queue_id] != NULL)
92*80518852SAndrew Boyer 		iocpt_op_queue_release(cdev, queue_id);
93*80518852SAndrew Boyer 
94*80518852SAndrew Boyer 	if (qp_conf->nb_descriptors < (1 << IOCPT_QSIZE_MIN_LG2) ||
95*80518852SAndrew Boyer 	    qp_conf->nb_descriptors > (1 << IOCPT_QSIZE_MAX_LG2)) {
96*80518852SAndrew Boyer 		IOCPT_PRINT(ERR, "invalid nb_descriptors %u, use range %u..%u",
97*80518852SAndrew Boyer 			qp_conf->nb_descriptors,
98*80518852SAndrew Boyer 			1 << IOCPT_QSIZE_MIN_LG2, 1 << IOCPT_QSIZE_MAX_LG2);
99*80518852SAndrew Boyer 		return -ERANGE;
100*80518852SAndrew Boyer 	}
101*80518852SAndrew Boyer 
102*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "queue_id %u", queue_id);
103*80518852SAndrew Boyer 
104*80518852SAndrew Boyer 	err = iocpt_cryptoq_alloc(dev, socket_id, queue_id,
105*80518852SAndrew Boyer 				qp_conf->nb_descriptors);
106*80518852SAndrew Boyer 	if (err != 0)
107*80518852SAndrew Boyer 		return err;
108*80518852SAndrew Boyer 
109*80518852SAndrew Boyer 	cdev->data->queue_pairs[queue_id] = dev->cryptoqs[queue_id];
110*80518852SAndrew Boyer 
111*80518852SAndrew Boyer 	return 0;
112*80518852SAndrew Boyer }
113*80518852SAndrew Boyer 
1146bc7f2cfSAndrew Boyer static unsigned int
1156bc7f2cfSAndrew Boyer iocpt_op_get_session_size(struct rte_cryptodev *cdev __rte_unused)
1166bc7f2cfSAndrew Boyer {
1176bc7f2cfSAndrew Boyer 	return iocpt_session_size();
1186bc7f2cfSAndrew Boyer }
1196bc7f2cfSAndrew Boyer 
1206bc7f2cfSAndrew Boyer static inline int
1216bc7f2cfSAndrew Boyer iocpt_is_algo_supported(struct rte_crypto_sym_xform *xform)
1226bc7f2cfSAndrew Boyer {
1236bc7f2cfSAndrew Boyer 	if (xform->next != NULL) {
1246bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "chaining not supported");
1256bc7f2cfSAndrew Boyer 		return -ENOTSUP;
1266bc7f2cfSAndrew Boyer 	}
1276bc7f2cfSAndrew Boyer 
1286bc7f2cfSAndrew Boyer 	if (xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) {
1296bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "xform->type %d not supported", xform->type);
1306bc7f2cfSAndrew Boyer 		return -ENOTSUP;
1316bc7f2cfSAndrew Boyer 	}
1326bc7f2cfSAndrew Boyer 
1336bc7f2cfSAndrew Boyer 	return 0;
1346bc7f2cfSAndrew Boyer }
1356bc7f2cfSAndrew Boyer 
1366bc7f2cfSAndrew Boyer static __rte_always_inline int
1376bc7f2cfSAndrew Boyer iocpt_fill_sess_aead(struct rte_crypto_sym_xform *xform,
1386bc7f2cfSAndrew Boyer 		struct iocpt_session_priv *priv)
1396bc7f2cfSAndrew Boyer {
1406bc7f2cfSAndrew Boyer 	struct rte_crypto_aead_xform *aead_form = &xform->aead;
1416bc7f2cfSAndrew Boyer 
1426bc7f2cfSAndrew Boyer 	if (aead_form->algo != RTE_CRYPTO_AEAD_AES_GCM) {
1436bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Unknown algo");
1446bc7f2cfSAndrew Boyer 		return -EINVAL;
1456bc7f2cfSAndrew Boyer 	}
1466bc7f2cfSAndrew Boyer 	if (aead_form->op == RTE_CRYPTO_AEAD_OP_ENCRYPT) {
1476bc7f2cfSAndrew Boyer 		priv->op = IOCPT_DESC_OPCODE_GCM_AEAD_ENCRYPT;
1486bc7f2cfSAndrew Boyer 	} else if (aead_form->op == RTE_CRYPTO_AEAD_OP_DECRYPT) {
1496bc7f2cfSAndrew Boyer 		priv->op = IOCPT_DESC_OPCODE_GCM_AEAD_DECRYPT;
1506bc7f2cfSAndrew Boyer 	} else {
1516bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Unknown cipher operations");
1526bc7f2cfSAndrew Boyer 		return -1;
1536bc7f2cfSAndrew Boyer 	}
1546bc7f2cfSAndrew Boyer 
1556bc7f2cfSAndrew Boyer 	if (aead_form->key.length < IOCPT_SESS_KEY_LEN_MIN ||
1566bc7f2cfSAndrew Boyer 	    aead_form->key.length > IOCPT_SESS_KEY_LEN_MAX_SYMM) {
1576bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Invalid cipher keylen %u",
1586bc7f2cfSAndrew Boyer 			aead_form->key.length);
1596bc7f2cfSAndrew Boyer 		return -1;
1606bc7f2cfSAndrew Boyer 	}
1616bc7f2cfSAndrew Boyer 	priv->key_len = aead_form->key.length;
1626bc7f2cfSAndrew Boyer 	memcpy(priv->key, aead_form->key.data, priv->key_len);
1636bc7f2cfSAndrew Boyer 
1646bc7f2cfSAndrew Boyer 	priv->type = IOCPT_SESS_AEAD_AES_GCM;
1656bc7f2cfSAndrew Boyer 	priv->iv_offset = aead_form->iv.offset;
1666bc7f2cfSAndrew Boyer 	priv->iv_length = aead_form->iv.length;
1676bc7f2cfSAndrew Boyer 	priv->digest_length = aead_form->digest_length;
1686bc7f2cfSAndrew Boyer 	priv->aad_length = aead_form->aad_length;
1696bc7f2cfSAndrew Boyer 
1706bc7f2cfSAndrew Boyer 	return 0;
1716bc7f2cfSAndrew Boyer }
1726bc7f2cfSAndrew Boyer 
1736bc7f2cfSAndrew Boyer static int
1746bc7f2cfSAndrew Boyer iocpt_session_cfg(struct iocpt_dev *dev,
1756bc7f2cfSAndrew Boyer 		struct rte_crypto_sym_xform *xform,
1766bc7f2cfSAndrew Boyer 		struct rte_cryptodev_sym_session *sess)
1776bc7f2cfSAndrew Boyer {
1786bc7f2cfSAndrew Boyer 	struct rte_crypto_sym_xform *chain;
1796bc7f2cfSAndrew Boyer 	struct iocpt_session_priv *priv = NULL;
1806bc7f2cfSAndrew Boyer 
1816bc7f2cfSAndrew Boyer 	if (iocpt_is_algo_supported(xform) < 0)
1826bc7f2cfSAndrew Boyer 		return -ENOTSUP;
1836bc7f2cfSAndrew Boyer 
1846bc7f2cfSAndrew Boyer 	if (unlikely(sess == NULL)) {
1856bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "invalid session");
1866bc7f2cfSAndrew Boyer 		return -EINVAL;
1876bc7f2cfSAndrew Boyer 	}
1886bc7f2cfSAndrew Boyer 
1896bc7f2cfSAndrew Boyer 	priv = CRYPTODEV_GET_SYM_SESS_PRIV(sess);
1906bc7f2cfSAndrew Boyer 	priv->dev = dev;
1916bc7f2cfSAndrew Boyer 
1926bc7f2cfSAndrew Boyer 	chain = xform;
1936bc7f2cfSAndrew Boyer 	while (chain) {
1946bc7f2cfSAndrew Boyer 		switch (chain->type) {
1956bc7f2cfSAndrew Boyer 		case RTE_CRYPTO_SYM_XFORM_AEAD:
1966bc7f2cfSAndrew Boyer 			if (iocpt_fill_sess_aead(chain, priv))
1976bc7f2cfSAndrew Boyer 				return -EIO;
1986bc7f2cfSAndrew Boyer 			break;
1996bc7f2cfSAndrew Boyer 		default:
2006bc7f2cfSAndrew Boyer 			IOCPT_PRINT(ERR, "invalid crypto xform type %d",
2016bc7f2cfSAndrew Boyer 				chain->type);
2026bc7f2cfSAndrew Boyer 			return -ENOTSUP;
2036bc7f2cfSAndrew Boyer 		}
2046bc7f2cfSAndrew Boyer 		chain = chain->next;
2056bc7f2cfSAndrew Boyer 	}
2066bc7f2cfSAndrew Boyer 
2076bc7f2cfSAndrew Boyer 	return iocpt_session_init(priv);
2086bc7f2cfSAndrew Boyer }
2096bc7f2cfSAndrew Boyer 
2106bc7f2cfSAndrew Boyer static int
2116bc7f2cfSAndrew Boyer iocpt_op_session_cfg(struct rte_cryptodev *cdev,
2126bc7f2cfSAndrew Boyer 		struct rte_crypto_sym_xform *xform,
2136bc7f2cfSAndrew Boyer 		struct rte_cryptodev_sym_session *sess)
2146bc7f2cfSAndrew Boyer {
2156bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
2166bc7f2cfSAndrew Boyer 
2176bc7f2cfSAndrew Boyer 	return iocpt_session_cfg(dev, xform, sess);
2186bc7f2cfSAndrew Boyer }
2196bc7f2cfSAndrew Boyer 
2206bc7f2cfSAndrew Boyer static void
2216bc7f2cfSAndrew Boyer iocpt_session_clear(struct rte_cryptodev_sym_session *sess)
2226bc7f2cfSAndrew Boyer {
2236bc7f2cfSAndrew Boyer 	iocpt_session_deinit(CRYPTODEV_GET_SYM_SESS_PRIV(sess));
2246bc7f2cfSAndrew Boyer }
2256bc7f2cfSAndrew Boyer 
2266bc7f2cfSAndrew Boyer static void
2276bc7f2cfSAndrew Boyer iocpt_op_session_clear(struct rte_cryptodev *cdev __rte_unused,
2286bc7f2cfSAndrew Boyer 		struct rte_cryptodev_sym_session *sess)
2296bc7f2cfSAndrew Boyer {
2306bc7f2cfSAndrew Boyer 	iocpt_session_clear(sess);
2316bc7f2cfSAndrew Boyer }
2326bc7f2cfSAndrew Boyer 
233*80518852SAndrew Boyer static inline void
234*80518852SAndrew Boyer iocpt_fill_sge(struct iocpt_crypto_sg_elem *arr, uint8_t idx,
235*80518852SAndrew Boyer 		uint64_t addr, uint16_t len)
236*80518852SAndrew Boyer {
237*80518852SAndrew Boyer 	arr[idx].addr = rte_cpu_to_le_64(addr);
238*80518852SAndrew Boyer 	arr[idx].len = rte_cpu_to_le_16(len);
239*80518852SAndrew Boyer }
240*80518852SAndrew Boyer 
241*80518852SAndrew Boyer static __rte_always_inline int
242*80518852SAndrew Boyer iocpt_enq_one_aead(struct iocpt_crypto_q *cptq,
243*80518852SAndrew Boyer 		struct iocpt_session_priv *priv, struct rte_crypto_op *op)
244*80518852SAndrew Boyer {
245*80518852SAndrew Boyer 	struct rte_crypto_sym_op *sym_op = op->sym;
246*80518852SAndrew Boyer 	struct iocpt_queue *q = &cptq->q;
247*80518852SAndrew Boyer 	struct iocpt_crypto_desc *desc, *desc_base = q->base;
248*80518852SAndrew Boyer 	struct iocpt_crypto_sg_desc *sg_desc, *sg_desc_base = q->sg_base;
249*80518852SAndrew Boyer 	struct iocpt_crypto_sg_elem *src, *dst;
250*80518852SAndrew Boyer 	rte_iova_t aad_addr, digest_addr, iv_addr, seg_addr;
251*80518852SAndrew Boyer 	uint32_t data_len, data_offset, seg_len;
252*80518852SAndrew Boyer 	uint8_t nsge_src = 0, nsge_dst = 0, flags = 0;
253*80518852SAndrew Boyer 	struct rte_mbuf *m;
254*80518852SAndrew Boyer 
255*80518852SAndrew Boyer 	desc = &desc_base[q->head_idx];
256*80518852SAndrew Boyer 	sg_desc = &sg_desc_base[q->head_idx];
257*80518852SAndrew Boyer 	src = sg_desc->src_elems;
258*80518852SAndrew Boyer 	dst = sg_desc->dst_elems;
259*80518852SAndrew Boyer 
260*80518852SAndrew Boyer 	/* Fill the first SGE with the IV / Nonce */
261*80518852SAndrew Boyer 	iv_addr = rte_crypto_op_ctophys_offset(op, priv->iv_offset);
262*80518852SAndrew Boyer 	iocpt_fill_sge(src, nsge_src++, iv_addr, priv->iv_length);
263*80518852SAndrew Boyer 
264*80518852SAndrew Boyer 	/* Fill the second SGE with the AAD, if applicable */
265*80518852SAndrew Boyer 	if (priv->aad_length > 0) {
266*80518852SAndrew Boyer 		aad_addr = sym_op->aead.aad.phys_addr;
267*80518852SAndrew Boyer 		iocpt_fill_sge(src, nsge_src++, aad_addr, priv->aad_length);
268*80518852SAndrew Boyer 		flags |= IOCPT_DESC_F_AAD_VALID;
269*80518852SAndrew Boyer 	}
270*80518852SAndrew Boyer 
271*80518852SAndrew Boyer 	m = sym_op->m_src;
272*80518852SAndrew Boyer 	data_len = sym_op->aead.data.length;
273*80518852SAndrew Boyer 
274*80518852SAndrew Boyer 	/* Fast-forward through mbuf chain to account for data offset */
275*80518852SAndrew Boyer 	data_offset = sym_op->aead.data.offset;
276*80518852SAndrew Boyer 	while (m != NULL && data_offset >= m->data_len) {
277*80518852SAndrew Boyer 		data_offset -= m->data_len;
278*80518852SAndrew Boyer 		m = m->next;
279*80518852SAndrew Boyer 	}
280*80518852SAndrew Boyer 
281*80518852SAndrew Boyer 	/* Fill the next SGEs with the payload segments */
282*80518852SAndrew Boyer 	while (m != NULL && data_len > 0) {
283*80518852SAndrew Boyer 		seg_addr = rte_mbuf_data_iova(m) + data_offset;
284*80518852SAndrew Boyer 		seg_len = RTE_MIN(m->data_len - data_offset, data_len);
285*80518852SAndrew Boyer 		data_offset = 0;
286*80518852SAndrew Boyer 		data_len -= seg_len;
287*80518852SAndrew Boyer 
288*80518852SAndrew Boyer 		/* Use -1 to save room for digest */
289*80518852SAndrew Boyer 		if (nsge_src >= IOCPT_CRYPTO_MAX_SG_ELEMS - 1)
290*80518852SAndrew Boyer 			return -ERANGE;
291*80518852SAndrew Boyer 
292*80518852SAndrew Boyer 		iocpt_fill_sge(src, nsge_src++, seg_addr, seg_len);
293*80518852SAndrew Boyer 
294*80518852SAndrew Boyer 		m = m->next;
295*80518852SAndrew Boyer 	}
296*80518852SAndrew Boyer 
297*80518852SAndrew Boyer 	/* AEAD AES-GCM: digest == authentication tag */
298*80518852SAndrew Boyer 	digest_addr = sym_op->aead.digest.phys_addr;
299*80518852SAndrew Boyer 	iocpt_fill_sge(src, nsge_src++, digest_addr, priv->digest_length);
300*80518852SAndrew Boyer 
301*80518852SAndrew Boyer 	/* Process Out-Of-Place destination SGL */
302*80518852SAndrew Boyer 	if (sym_op->m_dst != NULL) {
303*80518852SAndrew Boyer 		/* Put the AAD here, too */
304*80518852SAndrew Boyer 		if (priv->aad_length > 0)
305*80518852SAndrew Boyer 			iocpt_fill_sge(dst, nsge_dst++,
306*80518852SAndrew Boyer 				sym_op->aead.aad.phys_addr, priv->aad_length);
307*80518852SAndrew Boyer 
308*80518852SAndrew Boyer 		m = sym_op->m_dst;
309*80518852SAndrew Boyer 		data_len = sym_op->aead.data.length;
310*80518852SAndrew Boyer 
311*80518852SAndrew Boyer 		/* Fast-forward through chain to account for data offset */
312*80518852SAndrew Boyer 		data_offset = sym_op->aead.data.offset;
313*80518852SAndrew Boyer 		while (m != NULL && data_offset >= m->data_len) {
314*80518852SAndrew Boyer 			data_offset -= m->data_len;
315*80518852SAndrew Boyer 			m = m->next;
316*80518852SAndrew Boyer 		}
317*80518852SAndrew Boyer 
318*80518852SAndrew Boyer 		/* Fill in the SGEs with the payload segments */
319*80518852SAndrew Boyer 		while (m != NULL && data_len > 0) {
320*80518852SAndrew Boyer 			seg_addr = rte_mbuf_data_iova(m) + data_offset;
321*80518852SAndrew Boyer 			seg_len = RTE_MIN(m->data_len - data_offset, data_len);
322*80518852SAndrew Boyer 			data_offset = 0;
323*80518852SAndrew Boyer 			data_len -= seg_len;
324*80518852SAndrew Boyer 
325*80518852SAndrew Boyer 			if (nsge_dst >= IOCPT_CRYPTO_MAX_SG_ELEMS)
326*80518852SAndrew Boyer 				return -ERANGE;
327*80518852SAndrew Boyer 
328*80518852SAndrew Boyer 			iocpt_fill_sge(dst, nsge_dst++, seg_addr, seg_len);
329*80518852SAndrew Boyer 
330*80518852SAndrew Boyer 			m = m->next;
331*80518852SAndrew Boyer 		}
332*80518852SAndrew Boyer 	}
333*80518852SAndrew Boyer 
334*80518852SAndrew Boyer 	desc->opcode = priv->op;
335*80518852SAndrew Boyer 	desc->flags = flags;
336*80518852SAndrew Boyer 	desc->num_src_dst_sgs = iocpt_encode_nsge_src_dst(nsge_src, nsge_dst);
337*80518852SAndrew Boyer 	desc->session_tag = rte_cpu_to_le_32(priv->index);
338*80518852SAndrew Boyer 
339*80518852SAndrew Boyer 	op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
340*80518852SAndrew Boyer 	q->info[q->head_idx] = op;
341*80518852SAndrew Boyer 	q->head_idx = Q_NEXT_TO_POST(q, 1);
342*80518852SAndrew Boyer 
343*80518852SAndrew Boyer 	return 0;
344*80518852SAndrew Boyer }
345*80518852SAndrew Boyer 
346*80518852SAndrew Boyer static uint16_t
347*80518852SAndrew Boyer iocpt_enqueue_sym(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops)
348*80518852SAndrew Boyer {
349*80518852SAndrew Boyer 	struct iocpt_crypto_q *cptq = qp;
350*80518852SAndrew Boyer 	struct rte_crypto_op *op;
351*80518852SAndrew Boyer 	struct iocpt_session_priv *priv;
352*80518852SAndrew Boyer 	uint16_t avail, count;
353*80518852SAndrew Boyer 	int err;
354*80518852SAndrew Boyer 
355*80518852SAndrew Boyer 	avail = iocpt_q_space_avail(&cptq->q);
356*80518852SAndrew Boyer 	if (unlikely(nb_ops > avail))
357*80518852SAndrew Boyer 		nb_ops = avail;
358*80518852SAndrew Boyer 
359*80518852SAndrew Boyer 	count = 0;
360*80518852SAndrew Boyer 	while (likely(count < nb_ops)) {
361*80518852SAndrew Boyer 		op = ops[count];
362*80518852SAndrew Boyer 
363*80518852SAndrew Boyer 		if (unlikely(op->sess_type != RTE_CRYPTO_OP_WITH_SESSION)) {
364*80518852SAndrew Boyer 			op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
365*80518852SAndrew Boyer 			break;
366*80518852SAndrew Boyer 		}
367*80518852SAndrew Boyer 
368*80518852SAndrew Boyer 		priv = CRYPTODEV_GET_SYM_SESS_PRIV(op->sym->session);
369*80518852SAndrew Boyer 		if (unlikely(priv == NULL)) {
370*80518852SAndrew Boyer 			op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
371*80518852SAndrew Boyer 			break;
372*80518852SAndrew Boyer 		}
373*80518852SAndrew Boyer 
374*80518852SAndrew Boyer 		err = iocpt_enq_one_aead(cptq, priv, op);
375*80518852SAndrew Boyer 		if (unlikely(err != 0)) {
376*80518852SAndrew Boyer 			op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
377*80518852SAndrew Boyer 			break;
378*80518852SAndrew Boyer 		}
379*80518852SAndrew Boyer 
380*80518852SAndrew Boyer 		count++;
381*80518852SAndrew Boyer 	}
382*80518852SAndrew Boyer 
383*80518852SAndrew Boyer 	if (likely(count > 0))
384*80518852SAndrew Boyer 		iocpt_q_flush(&cptq->q);
385*80518852SAndrew Boyer 
386*80518852SAndrew Boyer 	return count;
387*80518852SAndrew Boyer }
388*80518852SAndrew Boyer 
389*80518852SAndrew Boyer static uint16_t
390*80518852SAndrew Boyer iocpt_dequeue_sym(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops)
391*80518852SAndrew Boyer {
392*80518852SAndrew Boyer 	struct iocpt_crypto_q *cptq = qp;
393*80518852SAndrew Boyer 	struct iocpt_queue *q = &cptq->q;
394*80518852SAndrew Boyer 	struct iocpt_cq *cq = &cptq->cq;
395*80518852SAndrew Boyer 	struct rte_crypto_op *op;
396*80518852SAndrew Boyer 	struct iocpt_crypto_comp *cq_desc_base = cq->base;
397*80518852SAndrew Boyer 	volatile struct iocpt_crypto_comp *cq_desc;
398*80518852SAndrew Boyer 	uint16_t count = 0;
399*80518852SAndrew Boyer 
400*80518852SAndrew Boyer 	cq_desc = &cq_desc_base[cq->tail_idx];
401*80518852SAndrew Boyer 
402*80518852SAndrew Boyer 	/* First walk the CQ to update any completed op's status
403*80518852SAndrew Boyer 	 * NB: These can arrive out of order!
404*80518852SAndrew Boyer 	 */
405*80518852SAndrew Boyer 	while ((cq_desc->color & 0x1) == cq->done_color) {
406*80518852SAndrew Boyer 		cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
407*80518852SAndrew Boyer 		if (unlikely(cq->tail_idx == 0))
408*80518852SAndrew Boyer 			cq->done_color = !cq->done_color;
409*80518852SAndrew Boyer 
410*80518852SAndrew Boyer 		op = q->info[rte_le_to_cpu_16(cq_desc->comp_index)];
411*80518852SAndrew Boyer 
412*80518852SAndrew Boyer 		/* Process returned CQ descriptor status */
413*80518852SAndrew Boyer 		if (unlikely(cq_desc->status)) {
414*80518852SAndrew Boyer 			switch (cq_desc->status) {
415*80518852SAndrew Boyer 			case IOCPT_COMP_SYMM_AUTH_VERIFY_ERROR:
416*80518852SAndrew Boyer 				op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
417*80518852SAndrew Boyer 				break;
418*80518852SAndrew Boyer 			case IOCPT_COMP_INVAL_OPCODE_ERROR:
419*80518852SAndrew Boyer 			case IOCPT_COMP_UNSUPP_OPCODE_ERROR:
420*80518852SAndrew Boyer 			case IOCPT_COMP_SYMM_SRC_SG_ERROR:
421*80518852SAndrew Boyer 			case IOCPT_COMP_SYMM_DST_SG_ERROR:
422*80518852SAndrew Boyer 			case IOCPT_COMP_SYMM_SRC_DST_LEN_MISMATCH:
423*80518852SAndrew Boyer 			case IOCPT_COMP_SYMM_KEY_IDX_ERROR:
424*80518852SAndrew Boyer 				op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
425*80518852SAndrew Boyer 				break;
426*80518852SAndrew Boyer 			default:
427*80518852SAndrew Boyer 				op->status = RTE_CRYPTO_OP_STATUS_ERROR;
428*80518852SAndrew Boyer 				break;
429*80518852SAndrew Boyer 			}
430*80518852SAndrew Boyer 		} else
431*80518852SAndrew Boyer 			op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
432*80518852SAndrew Boyer 
433*80518852SAndrew Boyer 		cq_desc = &cq_desc_base[cq->tail_idx];
434*80518852SAndrew Boyer 	}
435*80518852SAndrew Boyer 
436*80518852SAndrew Boyer 	/* Next walk the SQ to pop off completed ops in-order */
437*80518852SAndrew Boyer 	while (count < nb_ops) {
438*80518852SAndrew Boyer 		op = q->info[q->tail_idx];
439*80518852SAndrew Boyer 
440*80518852SAndrew Boyer 		/* No more completions */
441*80518852SAndrew Boyer 		if (op == NULL ||
442*80518852SAndrew Boyer 		    op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
443*80518852SAndrew Boyer 			break;
444*80518852SAndrew Boyer 
445*80518852SAndrew Boyer 		ops[count] = op;
446*80518852SAndrew Boyer 		q->info[q->tail_idx] = NULL;
447*80518852SAndrew Boyer 
448*80518852SAndrew Boyer 		q->tail_idx = Q_NEXT_TO_SRVC(q, 1);
449*80518852SAndrew Boyer 		count++;
450*80518852SAndrew Boyer 	}
451*80518852SAndrew Boyer 
452*80518852SAndrew Boyer 	return count;
453*80518852SAndrew Boyer }
454*80518852SAndrew Boyer 
455dddfb0d9SAndrew Boyer static struct rte_cryptodev_ops iocpt_ops = {
456dddfb0d9SAndrew Boyer 	.dev_configure = iocpt_op_config,
457*80518852SAndrew Boyer 	.dev_start = iocpt_op_start,
458*80518852SAndrew Boyer 	.dev_stop = iocpt_op_stop,
459dddfb0d9SAndrew Boyer 	.dev_close = iocpt_op_close,
460dddfb0d9SAndrew Boyer 	.dev_infos_get = iocpt_op_info_get,
4616bc7f2cfSAndrew Boyer 
462*80518852SAndrew Boyer 	.queue_pair_setup = iocpt_op_queue_setup,
463*80518852SAndrew Boyer 	.queue_pair_release = iocpt_op_queue_release,
464*80518852SAndrew Boyer 
4656bc7f2cfSAndrew Boyer 	.sym_session_get_size = iocpt_op_get_session_size,
4666bc7f2cfSAndrew Boyer 	.sym_session_configure = iocpt_op_session_cfg,
4676bc7f2cfSAndrew Boyer 	.sym_session_clear = iocpt_op_session_clear,
468dddfb0d9SAndrew Boyer };
469dddfb0d9SAndrew Boyer 
470dddfb0d9SAndrew Boyer int
471dddfb0d9SAndrew Boyer iocpt_assign_ops(struct rte_cryptodev *cdev)
472dddfb0d9SAndrew Boyer {
473dddfb0d9SAndrew Boyer 	struct iocpt_dev *dev = cdev->data->dev_private;
474dddfb0d9SAndrew Boyer 
475dddfb0d9SAndrew Boyer 	cdev->dev_ops = &iocpt_ops;
476dddfb0d9SAndrew Boyer 	cdev->feature_flags = dev->features;
477dddfb0d9SAndrew Boyer 
478*80518852SAndrew Boyer 	if (dev->features & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) {
479*80518852SAndrew Boyer 		cdev->enqueue_burst = iocpt_enqueue_sym;
480*80518852SAndrew Boyer 		cdev->dequeue_burst = iocpt_dequeue_sym;
481*80518852SAndrew Boyer 	}
482*80518852SAndrew Boyer 
483dddfb0d9SAndrew Boyer 	return 0;
484dddfb0d9SAndrew Boyer }
485