xref: /dpdk/drivers/crypto/ionic/ionic_crypto_main.c (revision 80518852e2f52bbe27b5763fb05031caf8da4788)
14610ac93SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
24610ac93SAndrew Boyer  * Copyright 2021-2024 Advanced Micro Devices, Inc.
34610ac93SAndrew Boyer  */
44610ac93SAndrew Boyer 
54610ac93SAndrew Boyer #include <inttypes.h>
64610ac93SAndrew Boyer 
74610ac93SAndrew Boyer #include <rte_common.h>
84610ac93SAndrew Boyer #include <rte_malloc.h>
94610ac93SAndrew Boyer #include <rte_bitops.h>
104610ac93SAndrew Boyer 
114610ac93SAndrew Boyer #include "ionic_crypto.h"
124610ac93SAndrew Boyer 
132c1662bbSAndrew Boyer static int
142c1662bbSAndrew Boyer iocpt_cq_init(struct iocpt_cq *cq, uint16_t num_descs)
152c1662bbSAndrew Boyer {
162c1662bbSAndrew Boyer 	if (!rte_is_power_of_2(num_descs) ||
172c1662bbSAndrew Boyer 	    num_descs < IOCPT_MIN_RING_DESC ||
182c1662bbSAndrew Boyer 	    num_descs > IOCPT_MAX_RING_DESC) {
192c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "%u descriptors (min: %u max: %u)",
202c1662bbSAndrew Boyer 			num_descs, IOCPT_MIN_RING_DESC, IOCPT_MAX_RING_DESC);
212c1662bbSAndrew Boyer 		return -EINVAL;
222c1662bbSAndrew Boyer 	}
232c1662bbSAndrew Boyer 
242c1662bbSAndrew Boyer 	cq->num_descs = num_descs;
252c1662bbSAndrew Boyer 	cq->size_mask = num_descs - 1;
262c1662bbSAndrew Boyer 	cq->tail_idx = 0;
272c1662bbSAndrew Boyer 	cq->done_color = 1;
282c1662bbSAndrew Boyer 
292c1662bbSAndrew Boyer 	return 0;
302c1662bbSAndrew Boyer }
312c1662bbSAndrew Boyer 
322c1662bbSAndrew Boyer static void
33*80518852SAndrew Boyer iocpt_cq_reset(struct iocpt_cq *cq)
34*80518852SAndrew Boyer {
35*80518852SAndrew Boyer 	cq->tail_idx = 0;
36*80518852SAndrew Boyer 	cq->done_color = 1;
37*80518852SAndrew Boyer 
38*80518852SAndrew Boyer 	memset(cq->base, 0, sizeof(struct iocpt_nop_comp) * cq->num_descs);
39*80518852SAndrew Boyer }
40*80518852SAndrew Boyer 
41*80518852SAndrew Boyer static void
422c1662bbSAndrew Boyer iocpt_cq_map(struct iocpt_cq *cq, void *base, rte_iova_t base_pa)
432c1662bbSAndrew Boyer {
442c1662bbSAndrew Boyer 	cq->base = base;
452c1662bbSAndrew Boyer 	cq->base_pa = base_pa;
462c1662bbSAndrew Boyer }
472c1662bbSAndrew Boyer 
482c1662bbSAndrew Boyer uint32_t
492c1662bbSAndrew Boyer iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do,
502c1662bbSAndrew Boyer 		iocpt_cq_cb cb, void *cb_arg)
512c1662bbSAndrew Boyer {
522c1662bbSAndrew Boyer 	uint32_t work_done = 0;
532c1662bbSAndrew Boyer 
542c1662bbSAndrew Boyer 	if (work_to_do == 0)
552c1662bbSAndrew Boyer 		return 0;
562c1662bbSAndrew Boyer 
572c1662bbSAndrew Boyer 	while (cb(cq, cq->tail_idx, cb_arg)) {
582c1662bbSAndrew Boyer 		cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
592c1662bbSAndrew Boyer 		if (cq->tail_idx == 0)
602c1662bbSAndrew Boyer 			cq->done_color = !cq->done_color;
612c1662bbSAndrew Boyer 
622c1662bbSAndrew Boyer 		if (++work_done == work_to_do)
632c1662bbSAndrew Boyer 			break;
642c1662bbSAndrew Boyer 	}
652c1662bbSAndrew Boyer 
662c1662bbSAndrew Boyer 	return work_done;
672c1662bbSAndrew Boyer }
682c1662bbSAndrew Boyer 
692c1662bbSAndrew Boyer static int
702c1662bbSAndrew Boyer iocpt_q_init(struct iocpt_queue *q, uint8_t type, uint32_t index,
712c1662bbSAndrew Boyer 	uint16_t num_descs, uint16_t num_segs, uint32_t socket_id)
722c1662bbSAndrew Boyer {
732c1662bbSAndrew Boyer 	uint32_t ring_size;
742c1662bbSAndrew Boyer 
752c1662bbSAndrew Boyer 	if (!rte_is_power_of_2(num_descs))
762c1662bbSAndrew Boyer 		return -EINVAL;
772c1662bbSAndrew Boyer 
782c1662bbSAndrew Boyer 	ring_size = rte_log2_u32(num_descs);
792c1662bbSAndrew Boyer 	if (ring_size < 2 || ring_size > 16)
802c1662bbSAndrew Boyer 		return -EINVAL;
812c1662bbSAndrew Boyer 
822c1662bbSAndrew Boyer 	q->type = type;
832c1662bbSAndrew Boyer 	q->index = index;
842c1662bbSAndrew Boyer 	q->num_descs = num_descs;
852c1662bbSAndrew Boyer 	q->num_segs = num_segs;
862c1662bbSAndrew Boyer 	q->size_mask = num_descs - 1;
872c1662bbSAndrew Boyer 	q->head_idx = 0;
882c1662bbSAndrew Boyer 	q->tail_idx = 0;
892c1662bbSAndrew Boyer 
902c1662bbSAndrew Boyer 	q->info = rte_calloc_socket("iocpt",
912c1662bbSAndrew Boyer 				num_descs * num_segs, sizeof(void *),
922c1662bbSAndrew Boyer 				rte_mem_page_size(), socket_id);
932c1662bbSAndrew Boyer 	if (q->info == NULL) {
942c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate queue info");
952c1662bbSAndrew Boyer 		return -ENOMEM;
962c1662bbSAndrew Boyer 	}
972c1662bbSAndrew Boyer 
982c1662bbSAndrew Boyer 	return 0;
992c1662bbSAndrew Boyer }
1002c1662bbSAndrew Boyer 
1012c1662bbSAndrew Boyer static void
102*80518852SAndrew Boyer iocpt_q_reset(struct iocpt_queue *q)
103*80518852SAndrew Boyer {
104*80518852SAndrew Boyer 	q->head_idx = 0;
105*80518852SAndrew Boyer 	q->tail_idx = 0;
106*80518852SAndrew Boyer }
107*80518852SAndrew Boyer 
108*80518852SAndrew Boyer static void
1092c1662bbSAndrew Boyer iocpt_q_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
1102c1662bbSAndrew Boyer {
1112c1662bbSAndrew Boyer 	q->base = base;
1122c1662bbSAndrew Boyer 	q->base_pa = base_pa;
1132c1662bbSAndrew Boyer }
1142c1662bbSAndrew Boyer 
1152c1662bbSAndrew Boyer static void
1162c1662bbSAndrew Boyer iocpt_q_sg_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
1172c1662bbSAndrew Boyer {
1182c1662bbSAndrew Boyer 	q->sg_base = base;
1192c1662bbSAndrew Boyer 	q->sg_base_pa = base_pa;
1202c1662bbSAndrew Boyer }
1212c1662bbSAndrew Boyer 
1222c1662bbSAndrew Boyer static void
1232c1662bbSAndrew Boyer iocpt_q_free(struct iocpt_queue *q)
1242c1662bbSAndrew Boyer {
1252c1662bbSAndrew Boyer 	if (q->info != NULL) {
1262c1662bbSAndrew Boyer 		rte_free(q->info);
1272c1662bbSAndrew Boyer 		q->info = NULL;
1282c1662bbSAndrew Boyer 	}
1292c1662bbSAndrew Boyer }
1302c1662bbSAndrew Boyer 
1316bc7f2cfSAndrew Boyer static int
1326bc7f2cfSAndrew Boyer iocpt_session_write(struct iocpt_session_priv *priv,
1336bc7f2cfSAndrew Boyer 		enum iocpt_sess_control_oper oper)
1346bc7f2cfSAndrew Boyer {
1356bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = priv->dev;
1366bc7f2cfSAndrew Boyer 	struct iocpt_admin_ctx ctx = {
1376bc7f2cfSAndrew Boyer 		.pending_work = true,
1386bc7f2cfSAndrew Boyer 		.cmd.sess_control = {
1396bc7f2cfSAndrew Boyer 			.opcode = IOCPT_CMD_SESS_CONTROL,
1406bc7f2cfSAndrew Boyer 			.type = priv->type,
1416bc7f2cfSAndrew Boyer 			.oper = oper,
1426bc7f2cfSAndrew Boyer 			.index = rte_cpu_to_le_32(priv->index),
1436bc7f2cfSAndrew Boyer 			.key_len = rte_cpu_to_le_16(priv->key_len),
1446bc7f2cfSAndrew Boyer 			.key_seg_len = (uint8_t)RTE_MIN(priv->key_len,
1456bc7f2cfSAndrew Boyer 						IOCPT_SESS_KEY_SEG_LEN),
1466bc7f2cfSAndrew Boyer 		},
1476bc7f2cfSAndrew Boyer 	};
1486bc7f2cfSAndrew Boyer 	struct iocpt_sess_control_cmd *cmd = &ctx.cmd.sess_control;
1496bc7f2cfSAndrew Boyer 	uint16_t key_offset;
1506bc7f2cfSAndrew Boyer 	uint8_t key_segs, seg;
1516bc7f2cfSAndrew Boyer 	int err;
1526bc7f2cfSAndrew Boyer 
1536bc7f2cfSAndrew Boyer 	key_segs = ((priv->key_len - 1) >> IOCPT_SESS_KEY_SEG_SHFT) + 1;
1546bc7f2cfSAndrew Boyer 
1556bc7f2cfSAndrew Boyer 	for (seg = 0; seg < key_segs; seg++) {
1566bc7f2cfSAndrew Boyer 		ctx.pending_work = true;
1576bc7f2cfSAndrew Boyer 
1586bc7f2cfSAndrew Boyer 		key_offset = seg * cmd->key_seg_len;
1596bc7f2cfSAndrew Boyer 		memcpy(cmd->key, &priv->key[key_offset],
1606bc7f2cfSAndrew Boyer 			IOCPT_SESS_KEY_SEG_LEN);
1616bc7f2cfSAndrew Boyer 		cmd->key_seg_idx = seg;
1626bc7f2cfSAndrew Boyer 
1636bc7f2cfSAndrew Boyer 		/* Mark final segment */
1646bc7f2cfSAndrew Boyer 		if (seg + 1 == key_segs)
1656bc7f2cfSAndrew Boyer 			cmd->flags |= rte_cpu_to_le_16(IOCPT_SCTL_F_END);
1666bc7f2cfSAndrew Boyer 
1676bc7f2cfSAndrew Boyer 		err = iocpt_adminq_post_wait(dev, &ctx);
1686bc7f2cfSAndrew Boyer 		if (err != 0)
1696bc7f2cfSAndrew Boyer 			return err;
1706bc7f2cfSAndrew Boyer 	}
1716bc7f2cfSAndrew Boyer 
1726bc7f2cfSAndrew Boyer 	return 0;
1736bc7f2cfSAndrew Boyer }
1746bc7f2cfSAndrew Boyer 
1756bc7f2cfSAndrew Boyer int
1766bc7f2cfSAndrew Boyer iocpt_session_init(struct iocpt_session_priv *priv)
1776bc7f2cfSAndrew Boyer {
1786bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = priv->dev;
1796bc7f2cfSAndrew Boyer 	uint64_t bm_slab = 0;
1806bc7f2cfSAndrew Boyer 	uint32_t bm_pos = 0;
1816bc7f2cfSAndrew Boyer 	int err = 0;
1826bc7f2cfSAndrew Boyer 
1836bc7f2cfSAndrew Boyer 	rte_spinlock_lock(&dev->adminq_lock);
1846bc7f2cfSAndrew Boyer 
1856bc7f2cfSAndrew Boyer 	if (rte_bitmap_scan(dev->sess_bm, &bm_pos, &bm_slab) > 0) {
1866bc7f2cfSAndrew Boyer 		priv->index = bm_pos + rte_ctz64(bm_slab);
1876bc7f2cfSAndrew Boyer 		rte_bitmap_clear(dev->sess_bm, priv->index);
1886bc7f2cfSAndrew Boyer 	} else
1896bc7f2cfSAndrew Boyer 		err = -ENOSPC;
1906bc7f2cfSAndrew Boyer 
1916bc7f2cfSAndrew Boyer 	rte_spinlock_unlock(&dev->adminq_lock);
1926bc7f2cfSAndrew Boyer 
1936bc7f2cfSAndrew Boyer 	if (err != 0) {
1946bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "session index space exhausted");
1956bc7f2cfSAndrew Boyer 		return err;
1966bc7f2cfSAndrew Boyer 	}
1976bc7f2cfSAndrew Boyer 
1986bc7f2cfSAndrew Boyer 	err = iocpt_session_write(priv, IOCPT_SESS_INIT);
1996bc7f2cfSAndrew Boyer 	if (err != 0) {
2006bc7f2cfSAndrew Boyer 		rte_spinlock_lock(&dev->adminq_lock);
2016bc7f2cfSAndrew Boyer 		rte_bitmap_set(dev->sess_bm, priv->index);
2026bc7f2cfSAndrew Boyer 		rte_spinlock_unlock(&dev->adminq_lock);
2036bc7f2cfSAndrew Boyer 		return err;
2046bc7f2cfSAndrew Boyer 	}
2056bc7f2cfSAndrew Boyer 
2066bc7f2cfSAndrew Boyer 	priv->flags |= IOCPT_S_F_INITED;
2076bc7f2cfSAndrew Boyer 
2086bc7f2cfSAndrew Boyer 	return 0;
2096bc7f2cfSAndrew Boyer }
2106bc7f2cfSAndrew Boyer 
2116bc7f2cfSAndrew Boyer int
2126bc7f2cfSAndrew Boyer iocpt_session_update(struct iocpt_session_priv *priv)
2136bc7f2cfSAndrew Boyer {
2146bc7f2cfSAndrew Boyer 	return iocpt_session_write(priv, IOCPT_SESS_UPDATE_KEY);
2156bc7f2cfSAndrew Boyer }
2166bc7f2cfSAndrew Boyer 
2176bc7f2cfSAndrew Boyer void
2186bc7f2cfSAndrew Boyer iocpt_session_deinit(struct iocpt_session_priv *priv)
2196bc7f2cfSAndrew Boyer {
2206bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = priv->dev;
2216bc7f2cfSAndrew Boyer 	struct iocpt_admin_ctx ctx = {
2226bc7f2cfSAndrew Boyer 		.pending_work = true,
2236bc7f2cfSAndrew Boyer 		.cmd.sess_control = {
2246bc7f2cfSAndrew Boyer 			.opcode = IOCPT_CMD_SESS_CONTROL,
2256bc7f2cfSAndrew Boyer 			.type = priv->type,
2266bc7f2cfSAndrew Boyer 			.oper = IOCPT_SESS_DISABLE,
2276bc7f2cfSAndrew Boyer 			.index = rte_cpu_to_le_32(priv->index),
2286bc7f2cfSAndrew Boyer 			.key_len = rte_cpu_to_le_16(priv->key_len),
2296bc7f2cfSAndrew Boyer 		},
2306bc7f2cfSAndrew Boyer 	};
2316bc7f2cfSAndrew Boyer 
2326bc7f2cfSAndrew Boyer 	(void)iocpt_adminq_post_wait(dev, &ctx);
2336bc7f2cfSAndrew Boyer 
2346bc7f2cfSAndrew Boyer 	rte_spinlock_lock(&dev->adminq_lock);
2356bc7f2cfSAndrew Boyer 	rte_bitmap_set(dev->sess_bm, priv->index);
2366bc7f2cfSAndrew Boyer 	rte_spinlock_unlock(&dev->adminq_lock);
2376bc7f2cfSAndrew Boyer 
2386bc7f2cfSAndrew Boyer 	priv->flags &= ~IOCPT_S_F_INITED;
2396bc7f2cfSAndrew Boyer }
2406bc7f2cfSAndrew Boyer 
241a677112dSAndrew Boyer static const struct rte_memzone *
242a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size,
243a677112dSAndrew Boyer 			unsigned int align, int socket_id)
244a677112dSAndrew Boyer {
245a677112dSAndrew Boyer 	char zone_name[RTE_MEMZONE_NAMESIZE];
246a677112dSAndrew Boyer 	const struct rte_memzone *mz;
247a677112dSAndrew Boyer 	int err;
248a677112dSAndrew Boyer 
249a677112dSAndrew Boyer 	err = snprintf(zone_name, sizeof(zone_name),
250a677112dSAndrew Boyer 			"iocpt_%s_%u", type_name, qid);
251a677112dSAndrew Boyer 	if (err >= RTE_MEMZONE_NAMESIZE) {
252a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Name %s too long", type_name);
253a677112dSAndrew Boyer 		return NULL;
254a677112dSAndrew Boyer 	}
255a677112dSAndrew Boyer 
256a677112dSAndrew Boyer 	mz = rte_memzone_lookup(zone_name);
257a677112dSAndrew Boyer 	if (mz != NULL)
258a677112dSAndrew Boyer 		return mz;
259a677112dSAndrew Boyer 
260a677112dSAndrew Boyer 	return rte_memzone_reserve_aligned(zone_name, size, socket_id,
261a677112dSAndrew Boyer 			RTE_MEMZONE_IOVA_CONTIG, align);
262a677112dSAndrew Boyer }
263a677112dSAndrew Boyer 
264a677112dSAndrew Boyer static int
2652c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev,
2662c1662bbSAndrew Boyer 		uint8_t type,
2672c1662bbSAndrew Boyer 		size_t struct_size,
2682c1662bbSAndrew Boyer 		uint32_t socket_id,
2692c1662bbSAndrew Boyer 		uint32_t index,
2702c1662bbSAndrew Boyer 		const char *type_name,
2712c1662bbSAndrew Boyer 		uint16_t flags,
2722c1662bbSAndrew Boyer 		uint16_t num_descs,
2732c1662bbSAndrew Boyer 		uint16_t num_segs,
2742c1662bbSAndrew Boyer 		uint16_t desc_size,
2752c1662bbSAndrew Boyer 		uint16_t cq_desc_size,
2762c1662bbSAndrew Boyer 		uint16_t sg_desc_size,
2772c1662bbSAndrew Boyer 		struct iocpt_common_q **comq)
2782c1662bbSAndrew Boyer {
2792c1662bbSAndrew Boyer 	struct iocpt_common_q *new;
2802c1662bbSAndrew Boyer 	uint32_t q_size, cq_size, sg_size, total_size;
2812c1662bbSAndrew Boyer 	void *q_base, *cq_base, *sg_base;
2822c1662bbSAndrew Boyer 	rte_iova_t q_base_pa = 0;
2832c1662bbSAndrew Boyer 	rte_iova_t cq_base_pa = 0;
2842c1662bbSAndrew Boyer 	rte_iova_t sg_base_pa = 0;
2852c1662bbSAndrew Boyer 	size_t page_size = rte_mem_page_size();
2862c1662bbSAndrew Boyer 	int err;
2872c1662bbSAndrew Boyer 
2882c1662bbSAndrew Boyer 	*comq = NULL;
2892c1662bbSAndrew Boyer 
2902c1662bbSAndrew Boyer 	q_size	= num_descs * desc_size;
2912c1662bbSAndrew Boyer 	cq_size = num_descs * cq_desc_size;
2922c1662bbSAndrew Boyer 	sg_size = num_descs * sg_desc_size;
2932c1662bbSAndrew Boyer 
2942c1662bbSAndrew Boyer 	/*
2952c1662bbSAndrew Boyer 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
2962c1662bbSAndrew Boyer 	 * aligning as q_base could be not aligned to the page.
2972c1662bbSAndrew Boyer 	 * Adding page_size.
2982c1662bbSAndrew Boyer 	 */
2992c1662bbSAndrew Boyer 	total_size = RTE_ALIGN(q_size, page_size) +
3002c1662bbSAndrew Boyer 		RTE_ALIGN(cq_size, page_size) + page_size;
3012c1662bbSAndrew Boyer 	if (flags & IOCPT_Q_F_SG)
3022c1662bbSAndrew Boyer 		total_size += RTE_ALIGN(sg_size, page_size) + page_size;
3032c1662bbSAndrew Boyer 
3042c1662bbSAndrew Boyer 	new = rte_zmalloc_socket("iocpt", struct_size,
3052c1662bbSAndrew Boyer 			RTE_CACHE_LINE_SIZE, socket_id);
3062c1662bbSAndrew Boyer 	if (new == NULL) {
3072c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate queue structure");
3082c1662bbSAndrew Boyer 		return -ENOMEM;
3092c1662bbSAndrew Boyer 	}
3102c1662bbSAndrew Boyer 
3112c1662bbSAndrew Boyer 	new->dev = dev;
3122c1662bbSAndrew Boyer 
3132c1662bbSAndrew Boyer 	err = iocpt_q_init(&new->q, type, index, num_descs, num_segs,
3142c1662bbSAndrew Boyer 			socket_id);
3152c1662bbSAndrew Boyer 	if (err != 0) {
3162c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Queue initialization failed");
3172c1662bbSAndrew Boyer 		goto err_free_q;
3182c1662bbSAndrew Boyer 	}
3192c1662bbSAndrew Boyer 
3202c1662bbSAndrew Boyer 	err = iocpt_cq_init(&new->cq, num_descs);
3212c1662bbSAndrew Boyer 	if (err != 0) {
3222c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Completion queue initialization failed");
3232c1662bbSAndrew Boyer 		goto err_deinit_q;
3242c1662bbSAndrew Boyer 	}
3252c1662bbSAndrew Boyer 
3262c1662bbSAndrew Boyer 	new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size,
3272c1662bbSAndrew Boyer 					IONIC_ALIGN, socket_id);
3282c1662bbSAndrew Boyer 	if (new->base_z == NULL) {
3292c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory");
3302c1662bbSAndrew Boyer 		err = -ENOMEM;
3312c1662bbSAndrew Boyer 		goto err_deinit_cq;
3322c1662bbSAndrew Boyer 	}
3332c1662bbSAndrew Boyer 
3342c1662bbSAndrew Boyer 	new->base = new->base_z->addr;
3352c1662bbSAndrew Boyer 	new->base_pa = new->base_z->iova;
3362c1662bbSAndrew Boyer 
3372c1662bbSAndrew Boyer 	q_base = new->base;
3382c1662bbSAndrew Boyer 	q_base_pa = new->base_pa;
3392c1662bbSAndrew Boyer 	iocpt_q_map(&new->q, q_base, q_base_pa);
3402c1662bbSAndrew Boyer 
3412c1662bbSAndrew Boyer 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
3422c1662bbSAndrew Boyer 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
3432c1662bbSAndrew Boyer 	iocpt_cq_map(&new->cq, cq_base, cq_base_pa);
3442c1662bbSAndrew Boyer 
3452c1662bbSAndrew Boyer 	if (flags & IOCPT_Q_F_SG) {
3462c1662bbSAndrew Boyer 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
3472c1662bbSAndrew Boyer 			page_size);
3482c1662bbSAndrew Boyer 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
3492c1662bbSAndrew Boyer 		iocpt_q_sg_map(&new->q, sg_base, sg_base_pa);
3502c1662bbSAndrew Boyer 	}
3512c1662bbSAndrew Boyer 
3522c1662bbSAndrew Boyer 	IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx",
3532c1662bbSAndrew Boyer 		q_base_pa, cq_base_pa, sg_base_pa);
3542c1662bbSAndrew Boyer 
3552c1662bbSAndrew Boyer 	*comq = new;
3562c1662bbSAndrew Boyer 
3572c1662bbSAndrew Boyer 	return 0;
3582c1662bbSAndrew Boyer 
3592c1662bbSAndrew Boyer err_deinit_cq:
3602c1662bbSAndrew Boyer err_deinit_q:
3612c1662bbSAndrew Boyer 	iocpt_q_free(&new->q);
3622c1662bbSAndrew Boyer err_free_q:
3632c1662bbSAndrew Boyer 	rte_free(new);
3642c1662bbSAndrew Boyer 	return err;
3652c1662bbSAndrew Boyer }
3662c1662bbSAndrew Boyer 
367*80518852SAndrew Boyer int
368*80518852SAndrew Boyer iocpt_cryptoq_alloc(struct iocpt_dev *dev, uint32_t socket_id, uint32_t index,
369*80518852SAndrew Boyer 		uint16_t num_descs)
370*80518852SAndrew Boyer {
371*80518852SAndrew Boyer 	struct iocpt_crypto_q *cptq;
372*80518852SAndrew Boyer 	uint16_t flags = 0;
373*80518852SAndrew Boyer 	int err;
374*80518852SAndrew Boyer 
375*80518852SAndrew Boyer 	/* CryptoQ always supports scatter-gather */
376*80518852SAndrew Boyer 	flags |= IOCPT_Q_F_SG;
377*80518852SAndrew Boyer 
378*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq %u num_descs %u num_segs %u",
379*80518852SAndrew Boyer 		index, num_descs, 1);
380*80518852SAndrew Boyer 
381*80518852SAndrew Boyer 	err = iocpt_commonq_alloc(dev,
382*80518852SAndrew Boyer 		IOCPT_QTYPE_CRYPTOQ,
383*80518852SAndrew Boyer 		sizeof(struct iocpt_crypto_q),
384*80518852SAndrew Boyer 		socket_id,
385*80518852SAndrew Boyer 		index,
386*80518852SAndrew Boyer 		"crypto",
387*80518852SAndrew Boyer 		flags,
388*80518852SAndrew Boyer 		num_descs,
389*80518852SAndrew Boyer 		1,
390*80518852SAndrew Boyer 		sizeof(struct iocpt_crypto_desc),
391*80518852SAndrew Boyer 		sizeof(struct iocpt_crypto_comp),
392*80518852SAndrew Boyer 		sizeof(struct iocpt_crypto_sg_desc),
393*80518852SAndrew Boyer 		(struct iocpt_common_q **)&cptq);
394*80518852SAndrew Boyer 	if (err != 0)
395*80518852SAndrew Boyer 		return err;
396*80518852SAndrew Boyer 
397*80518852SAndrew Boyer 	cptq->flags = flags;
398*80518852SAndrew Boyer 
399*80518852SAndrew Boyer 	dev->cryptoqs[index] = cptq;
400*80518852SAndrew Boyer 
401*80518852SAndrew Boyer 	return 0;
402*80518852SAndrew Boyer }
403*80518852SAndrew Boyer 
4042c1662bbSAndrew Boyer struct ionic_doorbell *
4052c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q)
4062c1662bbSAndrew Boyer {
4072c1662bbSAndrew Boyer 	return dev->db_pages + q->hw_type;
4082c1662bbSAndrew Boyer }
4092c1662bbSAndrew Boyer 
4102c1662bbSAndrew Boyer static int
411*80518852SAndrew Boyer iocpt_cryptoq_init(struct iocpt_crypto_q *cptq)
412*80518852SAndrew Boyer {
413*80518852SAndrew Boyer 	struct iocpt_queue *q = &cptq->q;
414*80518852SAndrew Boyer 	struct iocpt_dev *dev = cptq->dev;
415*80518852SAndrew Boyer 	struct iocpt_cq *cq = &cptq->cq;
416*80518852SAndrew Boyer 	struct iocpt_admin_ctx ctx = {
417*80518852SAndrew Boyer 		.pending_work = true,
418*80518852SAndrew Boyer 		.cmd.q_init = {
419*80518852SAndrew Boyer 			.opcode = IOCPT_CMD_Q_INIT,
420*80518852SAndrew Boyer 			.type = IOCPT_QTYPE_CRYPTOQ,
421*80518852SAndrew Boyer 			.ver = dev->qtype_info[IOCPT_QTYPE_CRYPTOQ].version,
422*80518852SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
423*80518852SAndrew Boyer 			.flags = rte_cpu_to_le_16(IOCPT_QINIT_F_ENA |
424*80518852SAndrew Boyer 						IOCPT_QINIT_F_SG),
425*80518852SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
426*80518852SAndrew Boyer 			.ring_size = rte_log2_u32(q->num_descs),
427*80518852SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
428*80518852SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
429*80518852SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
430*80518852SAndrew Boyer 		},
431*80518852SAndrew Boyer 	};
432*80518852SAndrew Boyer 	int err;
433*80518852SAndrew Boyer 
434*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.index %d", q->index);
435*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.ring_base %#jx", q->base_pa);
436*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.ring_size %d",
437*80518852SAndrew Boyer 		ctx.cmd.q_init.ring_size);
438*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.ver %u", ctx.cmd.q_init.ver);
439*80518852SAndrew Boyer 
440*80518852SAndrew Boyer 	iocpt_q_reset(q);
441*80518852SAndrew Boyer 	iocpt_cq_reset(cq);
442*80518852SAndrew Boyer 
443*80518852SAndrew Boyer 	err = iocpt_adminq_post_wait(dev, &ctx);
444*80518852SAndrew Boyer 	if (err != 0)
445*80518852SAndrew Boyer 		return err;
446*80518852SAndrew Boyer 
447*80518852SAndrew Boyer 	q->hw_type = ctx.comp.q_init.hw_type;
448*80518852SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
449*80518852SAndrew Boyer 	q->db = iocpt_db_map(dev, q);
450*80518852SAndrew Boyer 
451*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq->hw_type %d", q->hw_type);
452*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq->hw_index %d", q->hw_index);
453*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq->db %p", q->db);
454*80518852SAndrew Boyer 
455*80518852SAndrew Boyer 	cptq->flags |= IOCPT_Q_F_INITED;
456*80518852SAndrew Boyer 
457*80518852SAndrew Boyer 	return 0;
458*80518852SAndrew Boyer }
459*80518852SAndrew Boyer 
460*80518852SAndrew Boyer static void
461*80518852SAndrew Boyer iocpt_cryptoq_deinit(struct iocpt_crypto_q *cptq)
462*80518852SAndrew Boyer {
463*80518852SAndrew Boyer 	struct iocpt_dev *dev = cptq->dev;
464*80518852SAndrew Boyer 	struct iocpt_admin_ctx ctx = {
465*80518852SAndrew Boyer 		.pending_work = true,
466*80518852SAndrew Boyer 		.cmd.q_control = {
467*80518852SAndrew Boyer 			.opcode = IOCPT_CMD_Q_CONTROL,
468*80518852SAndrew Boyer 			.type = IOCPT_QTYPE_CRYPTOQ,
469*80518852SAndrew Boyer 			.index = rte_cpu_to_le_32(cptq->q.index),
470*80518852SAndrew Boyer 			.oper = IOCPT_Q_DISABLE,
471*80518852SAndrew Boyer 		},
472*80518852SAndrew Boyer 	};
473*80518852SAndrew Boyer 	unsigned long sleep_usec = 100UL * 1000;
474*80518852SAndrew Boyer 	uint32_t sleep_cnt, sleep_max = IOCPT_CRYPTOQ_WAIT;
475*80518852SAndrew Boyer 	int err;
476*80518852SAndrew Boyer 
477*80518852SAndrew Boyer 	for (sleep_cnt = 0; sleep_cnt < sleep_max; sleep_cnt++) {
478*80518852SAndrew Boyer 		ctx.pending_work = true;
479*80518852SAndrew Boyer 
480*80518852SAndrew Boyer 		err = iocpt_adminq_post_wait(dev, &ctx);
481*80518852SAndrew Boyer 		if (err != -EAGAIN)
482*80518852SAndrew Boyer 			break;
483*80518852SAndrew Boyer 
484*80518852SAndrew Boyer 		rte_delay_us_block(sleep_usec);
485*80518852SAndrew Boyer 	}
486*80518852SAndrew Boyer 
487*80518852SAndrew Boyer 	if (err != 0)
488*80518852SAndrew Boyer 		IOCPT_PRINT(ERR, "Deinit queue %u returned %d after %u ms",
489*80518852SAndrew Boyer 			cptq->q.index, err, sleep_cnt * 100);
490*80518852SAndrew Boyer 	else
491*80518852SAndrew Boyer 		IOCPT_PRINT(DEBUG, "Deinit queue %u returned %d after %u ms",
492*80518852SAndrew Boyer 			cptq->q.index, err, sleep_cnt * 100);
493*80518852SAndrew Boyer 
494*80518852SAndrew Boyer 	cptq->flags &= ~IOCPT_Q_F_INITED;
495*80518852SAndrew Boyer }
496*80518852SAndrew Boyer 
497*80518852SAndrew Boyer void
498*80518852SAndrew Boyer iocpt_cryptoq_free(struct iocpt_crypto_q *cptq)
499*80518852SAndrew Boyer {
500*80518852SAndrew Boyer 	if (cptq == NULL)
501*80518852SAndrew Boyer 		return;
502*80518852SAndrew Boyer 
503*80518852SAndrew Boyer 	if (cptq->base_z != NULL) {
504*80518852SAndrew Boyer 		rte_memzone_free(cptq->base_z);
505*80518852SAndrew Boyer 		cptq->base_z = NULL;
506*80518852SAndrew Boyer 		cptq->base = NULL;
507*80518852SAndrew Boyer 		cptq->base_pa = 0;
508*80518852SAndrew Boyer 	}
509*80518852SAndrew Boyer 
510*80518852SAndrew Boyer 	iocpt_q_free(&cptq->q);
511*80518852SAndrew Boyer 
512*80518852SAndrew Boyer 	rte_free(cptq);
513*80518852SAndrew Boyer }
514*80518852SAndrew Boyer 
515*80518852SAndrew Boyer static int
5162c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev)
5172c1662bbSAndrew Boyer {
5182c1662bbSAndrew Boyer 	struct iocpt_admin_q *aq;
5192c1662bbSAndrew Boyer 	uint16_t num_descs = IOCPT_ADMINQ_LENGTH;
5202c1662bbSAndrew Boyer 	uint16_t flags = 0;
5212c1662bbSAndrew Boyer 	int err;
5222c1662bbSAndrew Boyer 
5232c1662bbSAndrew Boyer 	err = iocpt_commonq_alloc(dev,
5242c1662bbSAndrew Boyer 		IOCPT_QTYPE_ADMINQ,
5252c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_q),
5262c1662bbSAndrew Boyer 		rte_socket_id(),
5272c1662bbSAndrew Boyer 		0,
5282c1662bbSAndrew Boyer 		"admin",
5292c1662bbSAndrew Boyer 		flags,
5302c1662bbSAndrew Boyer 		num_descs,
5312c1662bbSAndrew Boyer 		1,
5322c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_cmd),
5332c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_comp),
5342c1662bbSAndrew Boyer 		0,
5352c1662bbSAndrew Boyer 		(struct iocpt_common_q **)&aq);
5362c1662bbSAndrew Boyer 	if (err != 0)
5372c1662bbSAndrew Boyer 		return err;
5382c1662bbSAndrew Boyer 
5392c1662bbSAndrew Boyer 	aq->flags = flags;
5402c1662bbSAndrew Boyer 
5412c1662bbSAndrew Boyer 	dev->adminq = aq;
5422c1662bbSAndrew Boyer 
5432c1662bbSAndrew Boyer 	return 0;
5442c1662bbSAndrew Boyer }
5452c1662bbSAndrew Boyer 
5462c1662bbSAndrew Boyer static int
5472c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev)
5482c1662bbSAndrew Boyer {
5492c1662bbSAndrew Boyer 	return iocpt_dev_adminq_init(dev);
5502c1662bbSAndrew Boyer }
5512c1662bbSAndrew Boyer 
5522c1662bbSAndrew Boyer static void
5532c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev)
5542c1662bbSAndrew Boyer {
5552c1662bbSAndrew Boyer 	dev->adminq->flags &= ~IOCPT_Q_F_INITED;
5562c1662bbSAndrew Boyer }
5572c1662bbSAndrew Boyer 
5582c1662bbSAndrew Boyer static void
5592c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq)
5602c1662bbSAndrew Boyer {
5612c1662bbSAndrew Boyer 	if (aq->base_z != NULL) {
5622c1662bbSAndrew Boyer 		rte_memzone_free(aq->base_z);
5632c1662bbSAndrew Boyer 		aq->base_z = NULL;
5642c1662bbSAndrew Boyer 		aq->base = NULL;
5652c1662bbSAndrew Boyer 		aq->base_pa = 0;
5662c1662bbSAndrew Boyer 	}
5672c1662bbSAndrew Boyer 
5682c1662bbSAndrew Boyer 	iocpt_q_free(&aq->q);
5692c1662bbSAndrew Boyer 
5702c1662bbSAndrew Boyer 	rte_free(aq);
5712c1662bbSAndrew Boyer }
5722c1662bbSAndrew Boyer 
5732c1662bbSAndrew Boyer static int
574a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev)
575a677112dSAndrew Boyer {
5766bc7f2cfSAndrew Boyer 	uint32_t bmsize, i;
5776bc7f2cfSAndrew Boyer 	uint8_t *bm;
578a677112dSAndrew Boyer 	int err;
579a677112dSAndrew Boyer 
580a677112dSAndrew Boyer 	IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name);
581a677112dSAndrew Boyer 
582*80518852SAndrew Boyer 	dev->cryptoqs = rte_calloc_socket("iocpt",
583*80518852SAndrew Boyer 				dev->max_qps, sizeof(*dev->cryptoqs),
584*80518852SAndrew Boyer 				RTE_CACHE_LINE_SIZE, dev->socket_id);
585*80518852SAndrew Boyer 	if (dev->cryptoqs == NULL) {
586*80518852SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate tx queues array");
587*80518852SAndrew Boyer 		return -ENOMEM;
588*80518852SAndrew Boyer 	}
589*80518852SAndrew Boyer 
5902c1662bbSAndrew Boyer 	rte_spinlock_init(&dev->adminq_lock);
5912c1662bbSAndrew Boyer 	rte_spinlock_init(&dev->adminq_service_lock);
5922c1662bbSAndrew Boyer 
5932c1662bbSAndrew Boyer 	err = iocpt_adminq_alloc(dev);
5942c1662bbSAndrew Boyer 	if (err != 0) {
5952c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate admin queue");
5962c1662bbSAndrew Boyer 		err = -ENOMEM;
597*80518852SAndrew Boyer 		goto err_free_cryptoqs;
5982c1662bbSAndrew Boyer 	}
5992c1662bbSAndrew Boyer 
600a677112dSAndrew Boyer 	dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size());
601a677112dSAndrew Boyer 	dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz,
602a677112dSAndrew Boyer 					IONIC_ALIGN, dev->socket_id);
603a677112dSAndrew Boyer 	if (dev->info_z == NULL) {
604a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate dev info memory");
605a677112dSAndrew Boyer 		err = -ENOMEM;
6062c1662bbSAndrew Boyer 		goto err_free_adminq;
607a677112dSAndrew Boyer 	}
608a677112dSAndrew Boyer 
609a677112dSAndrew Boyer 	dev->info = dev->info_z->addr;
610a677112dSAndrew Boyer 	dev->info_pa = dev->info_z->iova;
611a677112dSAndrew Boyer 
6126bc7f2cfSAndrew Boyer 	bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions);
6136bc7f2cfSAndrew Boyer 	bm = rte_malloc_socket("iocpt", bmsize,
6146bc7f2cfSAndrew Boyer 			RTE_CACHE_LINE_SIZE, dev->socket_id);
6156bc7f2cfSAndrew Boyer 	if (bm == NULL) {
6166bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize);
6176bc7f2cfSAndrew Boyer 		err = -ENOMEM;
6186bc7f2cfSAndrew Boyer 		goto err_free_dmazone;
6196bc7f2cfSAndrew Boyer 	}
6206bc7f2cfSAndrew Boyer 
6216bc7f2cfSAndrew Boyer 	dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize);
6226bc7f2cfSAndrew Boyer 	if (dev->sess_bm == NULL) {
6236bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot initialize bitmap");
6246bc7f2cfSAndrew Boyer 		err = -EFAULT;
6256bc7f2cfSAndrew Boyer 		goto err_free_bm;
6266bc7f2cfSAndrew Boyer 	}
6276bc7f2cfSAndrew Boyer 	for (i = 0; i < dev->max_sessions; i++)
6286bc7f2cfSAndrew Boyer 		rte_bitmap_set(dev->sess_bm, i);
6296bc7f2cfSAndrew Boyer 
630a677112dSAndrew Boyer 	return 0;
631a677112dSAndrew Boyer 
6326bc7f2cfSAndrew Boyer err_free_bm:
6336bc7f2cfSAndrew Boyer 	rte_free(bm);
6346bc7f2cfSAndrew Boyer err_free_dmazone:
6356bc7f2cfSAndrew Boyer 	rte_memzone_free(dev->info_z);
6366bc7f2cfSAndrew Boyer 	dev->info_z = NULL;
6376bc7f2cfSAndrew Boyer 	dev->info = NULL;
6386bc7f2cfSAndrew Boyer 	dev->info_pa = 0;
6392c1662bbSAndrew Boyer err_free_adminq:
6402c1662bbSAndrew Boyer 	iocpt_adminq_free(dev->adminq);
6412c1662bbSAndrew Boyer 	dev->adminq = NULL;
642*80518852SAndrew Boyer err_free_cryptoqs:
643*80518852SAndrew Boyer 	rte_free(dev->cryptoqs);
644*80518852SAndrew Boyer 	dev->cryptoqs = NULL;
645a677112dSAndrew Boyer 	return err;
646a677112dSAndrew Boyer }
647a677112dSAndrew Boyer 
6484610ac93SAndrew Boyer static int
6494610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev)
6504610ac93SAndrew Boyer {
651a677112dSAndrew Boyer 	int err;
652a677112dSAndrew Boyer 
653a677112dSAndrew Boyer 	/* Uses dev_cmds */
654a677112dSAndrew Boyer 	err = iocpt_dev_init(dev, dev->info_pa);
655a677112dSAndrew Boyer 	if (err != 0)
656a677112dSAndrew Boyer 		return err;
657a677112dSAndrew Boyer 
6582c1662bbSAndrew Boyer 	err = iocpt_adminq_init(dev);
6592c1662bbSAndrew Boyer 	if (err != 0)
6602c1662bbSAndrew Boyer 		return err;
6612c1662bbSAndrew Boyer 
6624610ac93SAndrew Boyer 	dev->state |= IOCPT_DEV_F_INITED;
6634610ac93SAndrew Boyer 
6644610ac93SAndrew Boyer 	return 0;
6654610ac93SAndrew Boyer }
6664610ac93SAndrew Boyer 
6674610ac93SAndrew Boyer void
6684610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev)
6694610ac93SAndrew Boyer {
6704610ac93SAndrew Boyer 	RTE_SET_USED(dev);
6714610ac93SAndrew Boyer }
6724610ac93SAndrew Boyer 
673*80518852SAndrew Boyer int
674*80518852SAndrew Boyer iocpt_start(struct iocpt_dev *dev)
675*80518852SAndrew Boyer {
676*80518852SAndrew Boyer 	uint32_t i;
677*80518852SAndrew Boyer 	int err;
678*80518852SAndrew Boyer 
679*80518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "Starting %u queues",
680*80518852SAndrew Boyer 		dev->crypto_dev->data->nb_queue_pairs);
681*80518852SAndrew Boyer 
682*80518852SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
683*80518852SAndrew Boyer 		err = iocpt_cryptoq_init(dev->cryptoqs[i]);
684*80518852SAndrew Boyer 		if (err != 0)
685*80518852SAndrew Boyer 			return err;
686*80518852SAndrew Boyer 	}
687*80518852SAndrew Boyer 
688*80518852SAndrew Boyer 	dev->state |= IOCPT_DEV_F_UP;
689*80518852SAndrew Boyer 
690*80518852SAndrew Boyer 	return 0;
691*80518852SAndrew Boyer }
692*80518852SAndrew Boyer 
693*80518852SAndrew Boyer void
694*80518852SAndrew Boyer iocpt_stop(struct iocpt_dev *dev)
695*80518852SAndrew Boyer {
696*80518852SAndrew Boyer 	uint32_t i;
697*80518852SAndrew Boyer 
698*80518852SAndrew Boyer 	IOCPT_PRINT_CALL();
699*80518852SAndrew Boyer 
700*80518852SAndrew Boyer 	dev->state &= ~IOCPT_DEV_F_UP;
701*80518852SAndrew Boyer 
702*80518852SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
703*80518852SAndrew Boyer 		struct iocpt_crypto_q *cptq = dev->cryptoqs[i];
704*80518852SAndrew Boyer 
705*80518852SAndrew Boyer 		if (cptq->flags & IOCPT_Q_F_INITED)
706*80518852SAndrew Boyer 			(void)iocpt_cryptoq_deinit(cptq);
707*80518852SAndrew Boyer 	}
708*80518852SAndrew Boyer }
709*80518852SAndrew Boyer 
7104610ac93SAndrew Boyer void
7114610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev)
7124610ac93SAndrew Boyer {
7134610ac93SAndrew Boyer 	IOCPT_PRINT_CALL();
7144610ac93SAndrew Boyer 
7154610ac93SAndrew Boyer 	if (!(dev->state & IOCPT_DEV_F_INITED))
7164610ac93SAndrew Boyer 		return;
7174610ac93SAndrew Boyer 
7182c1662bbSAndrew Boyer 	iocpt_adminq_deinit(dev);
7192c1662bbSAndrew Boyer 
7204610ac93SAndrew Boyer 	dev->state &= ~IOCPT_DEV_F_INITED;
7214610ac93SAndrew Boyer }
7224610ac93SAndrew Boyer 
723a677112dSAndrew Boyer static void
724a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev)
725a677112dSAndrew Boyer {
726*80518852SAndrew Boyer 	void **queue_pairs = dev->crypto_dev->data->queue_pairs;
727*80518852SAndrew Boyer 	uint32_t i;
728*80518852SAndrew Boyer 
729a677112dSAndrew Boyer 	IOCPT_PRINT_CALL();
730a677112dSAndrew Boyer 
731*80518852SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
732*80518852SAndrew Boyer 		iocpt_cryptoq_free(queue_pairs[i]);
733*80518852SAndrew Boyer 		queue_pairs[i] = NULL;
734*80518852SAndrew Boyer 	}
735*80518852SAndrew Boyer 
7366bc7f2cfSAndrew Boyer 	if (dev->sess_bm != NULL) {
7376bc7f2cfSAndrew Boyer 		rte_bitmap_free(dev->sess_bm);
7386bc7f2cfSAndrew Boyer 		rte_free(dev->sess_bm);
7396bc7f2cfSAndrew Boyer 		dev->sess_bm = NULL;
7406bc7f2cfSAndrew Boyer 	}
7416bc7f2cfSAndrew Boyer 
7422c1662bbSAndrew Boyer 	if (dev->adminq != NULL) {
7432c1662bbSAndrew Boyer 		iocpt_adminq_free(dev->adminq);
7442c1662bbSAndrew Boyer 		dev->adminq = NULL;
7452c1662bbSAndrew Boyer 	}
7462c1662bbSAndrew Boyer 
747*80518852SAndrew Boyer 	if (dev->cryptoqs != NULL) {
748*80518852SAndrew Boyer 		rte_free(dev->cryptoqs);
749*80518852SAndrew Boyer 		dev->cryptoqs = NULL;
750*80518852SAndrew Boyer 	}
751*80518852SAndrew Boyer 
752a677112dSAndrew Boyer 	if (dev->info != NULL) {
753a677112dSAndrew Boyer 		rte_memzone_free(dev->info_z);
754a677112dSAndrew Boyer 		dev->info_z = NULL;
755a677112dSAndrew Boyer 		dev->info = NULL;
756a677112dSAndrew Boyer 		dev->info_pa = 0;
757a677112dSAndrew Boyer 	}
758a677112dSAndrew Boyer }
759a677112dSAndrew Boyer 
7604610ac93SAndrew Boyer static int
7614610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev)
7624610ac93SAndrew Boyer {
7634610ac93SAndrew Boyer 	RTE_SET_USED(devargs);
7644610ac93SAndrew Boyer 	RTE_SET_USED(dev);
7654610ac93SAndrew Boyer 
7664610ac93SAndrew Boyer 	return 0;
7674610ac93SAndrew Boyer }
7684610ac93SAndrew Boyer 
7694610ac93SAndrew Boyer int
7704610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
7714610ac93SAndrew Boyer 	struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf,
7724610ac93SAndrew Boyer 	uint8_t driver_id, uint8_t socket_id)
7734610ac93SAndrew Boyer {
7744610ac93SAndrew Boyer 	struct rte_cryptodev_pmd_init_params init_params = {
7754610ac93SAndrew Boyer 		"iocpt",
7764610ac93SAndrew Boyer 		sizeof(struct iocpt_dev),
7774610ac93SAndrew Boyer 		socket_id,
7784610ac93SAndrew Boyer 		RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
7794610ac93SAndrew Boyer 	};
7804610ac93SAndrew Boyer 	struct rte_cryptodev *cdev;
7814610ac93SAndrew Boyer 	struct iocpt_dev *dev;
78225c896eaSAndrew Boyer 	uint32_t i, sig;
7834610ac93SAndrew Boyer 	int err;
7844610ac93SAndrew Boyer 
78525c896eaSAndrew Boyer 	/* Check structs (trigger error at compilation time) */
78625c896eaSAndrew Boyer 	iocpt_struct_size_checks();
78725c896eaSAndrew Boyer 
7884610ac93SAndrew Boyer 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
7894610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Multi-process not supported");
7904610ac93SAndrew Boyer 		err = -EPERM;
7914610ac93SAndrew Boyer 		goto err;
7924610ac93SAndrew Boyer 	}
7934610ac93SAndrew Boyer 
7944610ac93SAndrew Boyer 	cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params);
7954610ac93SAndrew Boyer 	if (cdev == NULL) {
7964610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Out of memory");
7974610ac93SAndrew Boyer 		err = -ENOMEM;
7984610ac93SAndrew Boyer 		goto err;
7994610ac93SAndrew Boyer 	}
8004610ac93SAndrew Boyer 
8014610ac93SAndrew Boyer 	dev = cdev->data->dev_private;
8024610ac93SAndrew Boyer 	dev->crypto_dev = cdev;
8034610ac93SAndrew Boyer 	dev->bus_dev = bus_dev;
8044610ac93SAndrew Boyer 	dev->intf = intf;
8054610ac93SAndrew Boyer 	dev->driver_id = driver_id;
8064610ac93SAndrew Boyer 	dev->socket_id = socket_id;
8074610ac93SAndrew Boyer 
8084610ac93SAndrew Boyer 	for (i = 0; i < bars->num_bars; i++) {
8094610ac93SAndrew Boyer 		struct ionic_dev_bar *bar = &bars->bar[i];
8104610ac93SAndrew Boyer 
8114610ac93SAndrew Boyer 		IOCPT_PRINT(DEBUG,
8124610ac93SAndrew Boyer 			"bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }",
8134610ac93SAndrew Boyer 			i, bar->vaddr, bar->bus_addr, bar->len);
8144610ac93SAndrew Boyer 		if (bar->vaddr == NULL) {
8154610ac93SAndrew Boyer 			IOCPT_PRINT(ERR, "Null bar found, aborting");
8164610ac93SAndrew Boyer 			err = -EFAULT;
8174610ac93SAndrew Boyer 			goto err_destroy_crypto_dev;
8184610ac93SAndrew Boyer 		}
8194610ac93SAndrew Boyer 
8204610ac93SAndrew Boyer 		dev->bars.bar[i].vaddr = bar->vaddr;
8214610ac93SAndrew Boyer 		dev->bars.bar[i].bus_addr = bar->bus_addr;
8224610ac93SAndrew Boyer 		dev->bars.bar[i].len = bar->len;
8234610ac93SAndrew Boyer 	}
8244610ac93SAndrew Boyer 	dev->bars.num_bars = bars->num_bars;
8254610ac93SAndrew Boyer 
8264610ac93SAndrew Boyer 	err = iocpt_devargs(rte_dev->devargs, dev);
8274610ac93SAndrew Boyer 	if (err != 0) {
8284610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot parse device arguments");
8294610ac93SAndrew Boyer 		goto err_destroy_crypto_dev;
8304610ac93SAndrew Boyer 	}
8314610ac93SAndrew Boyer 
8324610ac93SAndrew Boyer 	err = iocpt_setup_bars(dev);
8334610ac93SAndrew Boyer 	if (err != 0) {
8344610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err);
8354610ac93SAndrew Boyer 		goto err_destroy_crypto_dev;
8364610ac93SAndrew Boyer 	}
8374610ac93SAndrew Boyer 
83825c896eaSAndrew Boyer 	sig = ioread32(&dev->dev_info->signature);
83925c896eaSAndrew Boyer 	if (sig != IOCPT_DEV_INFO_SIGNATURE) {
84025c896eaSAndrew Boyer 		IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig);
84125c896eaSAndrew Boyer 		err = -EFAULT;
84225c896eaSAndrew Boyer 		goto err_destroy_crypto_dev;
84325c896eaSAndrew Boyer 	}
84425c896eaSAndrew Boyer 
84525c896eaSAndrew Boyer 	for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++)
84625c896eaSAndrew Boyer 		dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]);
84725c896eaSAndrew Boyer 	dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0';
84825c896eaSAndrew Boyer 	IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version);
84925c896eaSAndrew Boyer 
850a677112dSAndrew Boyer 	err = iocpt_dev_identify(dev);
851a677112dSAndrew Boyer 	if (err != 0) {
852a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting",
853a677112dSAndrew Boyer 			err);
854a677112dSAndrew Boyer 		goto err_destroy_crypto_dev;
855a677112dSAndrew Boyer 	}
856a677112dSAndrew Boyer 
857a677112dSAndrew Boyer 	err = iocpt_alloc_objs(dev);
858a677112dSAndrew Boyer 	if (err != 0) {
859a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err);
860a677112dSAndrew Boyer 		goto err_destroy_crypto_dev;
861a677112dSAndrew Boyer 	}
862a677112dSAndrew Boyer 
8634610ac93SAndrew Boyer 	err = iocpt_init(dev);
8644610ac93SAndrew Boyer 	if (err != 0) {
8654610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err);
866a677112dSAndrew Boyer 		goto err_free_objs;
8674610ac93SAndrew Boyer 	}
8684610ac93SAndrew Boyer 
869dddfb0d9SAndrew Boyer 	err = iocpt_assign_ops(cdev);
870dddfb0d9SAndrew Boyer 	if (err != 0) {
871dddfb0d9SAndrew Boyer 		IOCPT_PRINT(ERR, "Failed to configure opts");
872dddfb0d9SAndrew Boyer 		goto err_deinit_dev;
873dddfb0d9SAndrew Boyer 	}
874dddfb0d9SAndrew Boyer 
8754610ac93SAndrew Boyer 	return 0;
8764610ac93SAndrew Boyer 
877dddfb0d9SAndrew Boyer err_deinit_dev:
878dddfb0d9SAndrew Boyer 	iocpt_deinit(dev);
879a677112dSAndrew Boyer err_free_objs:
880a677112dSAndrew Boyer 	iocpt_free_objs(dev);
8814610ac93SAndrew Boyer err_destroy_crypto_dev:
8824610ac93SAndrew Boyer 	rte_cryptodev_pmd_destroy(cdev);
8834610ac93SAndrew Boyer err:
8844610ac93SAndrew Boyer 	return err;
8854610ac93SAndrew Boyer }
8864610ac93SAndrew Boyer 
8874610ac93SAndrew Boyer int
8884610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev)
8894610ac93SAndrew Boyer {
8904610ac93SAndrew Boyer 	struct rte_cryptodev *cdev;
8914610ac93SAndrew Boyer 	struct iocpt_dev *dev;
8924610ac93SAndrew Boyer 
8934610ac93SAndrew Boyer 	cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name);
8944610ac93SAndrew Boyer 	if (cdev == NULL) {
8954610ac93SAndrew Boyer 		IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name);
8964610ac93SAndrew Boyer 		return -ENODEV;
8974610ac93SAndrew Boyer 	}
8984610ac93SAndrew Boyer 
8994610ac93SAndrew Boyer 	dev = cdev->data->dev_private;
9004610ac93SAndrew Boyer 
9014610ac93SAndrew Boyer 	iocpt_deinit(dev);
9024610ac93SAndrew Boyer 
903a677112dSAndrew Boyer 	iocpt_dev_reset(dev);
904a677112dSAndrew Boyer 
905a677112dSAndrew Boyer 	iocpt_free_objs(dev);
906a677112dSAndrew Boyer 
9074610ac93SAndrew Boyer 	rte_cryptodev_pmd_destroy(cdev);
9084610ac93SAndrew Boyer 
9094610ac93SAndrew Boyer 	return 0;
9104610ac93SAndrew Boyer }
9114610ac93SAndrew Boyer 
9124610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE);
913