xref: /dpdk/drivers/crypto/ionic/ionic_crypto_main.c (revision 974cbdc3b7ecc9c8582e49c6776a141b5b84af39)
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
iocpt_cq_init(struct iocpt_cq * cq,uint16_t num_descs)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
iocpt_cq_reset(struct iocpt_cq * cq)3380518852SAndrew Boyer iocpt_cq_reset(struct iocpt_cq *cq)
3480518852SAndrew Boyer {
3580518852SAndrew Boyer 	cq->tail_idx = 0;
3680518852SAndrew Boyer 	cq->done_color = 1;
3780518852SAndrew Boyer 
3880518852SAndrew Boyer 	memset(cq->base, 0, sizeof(struct iocpt_nop_comp) * cq->num_descs);
3980518852SAndrew Boyer }
4080518852SAndrew Boyer 
4180518852SAndrew Boyer static void
iocpt_cq_map(struct iocpt_cq * cq,void * base,rte_iova_t base_pa)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
iocpt_cq_service(struct iocpt_cq * cq,uint32_t work_to_do,iocpt_cq_cb cb,void * cb_arg)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
iocpt_q_init(struct iocpt_queue * q,uint8_t type,uint32_t index,uint16_t num_descs,uint16_t num_segs,uint32_t socket_id)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",
91*974cbdc3SAndrew Boyer 				(uint64_t)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
iocpt_q_reset(struct iocpt_queue * q)10280518852SAndrew Boyer iocpt_q_reset(struct iocpt_queue *q)
10380518852SAndrew Boyer {
10480518852SAndrew Boyer 	q->head_idx = 0;
10580518852SAndrew Boyer 	q->tail_idx = 0;
10680518852SAndrew Boyer }
10780518852SAndrew Boyer 
10880518852SAndrew Boyer static void
iocpt_q_map(struct iocpt_queue * q,void * base,rte_iova_t base_pa)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
iocpt_q_sg_map(struct iocpt_queue * q,void * base,rte_iova_t base_pa)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
iocpt_q_free(struct iocpt_queue * q)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 
131aacc5f13SAndrew Boyer static void
iocpt_get_abs_stats(const struct iocpt_dev * dev,struct rte_cryptodev_stats * stats)132aacc5f13SAndrew Boyer iocpt_get_abs_stats(const struct iocpt_dev *dev,
133aacc5f13SAndrew Boyer 		struct rte_cryptodev_stats *stats)
134aacc5f13SAndrew Boyer {
135aacc5f13SAndrew Boyer 	uint32_t i;
136aacc5f13SAndrew Boyer 
137aacc5f13SAndrew Boyer 	memset(stats, 0, sizeof(*stats));
138aacc5f13SAndrew Boyer 
139aacc5f13SAndrew Boyer 	/* Sum up the per-queue stats counters */
140aacc5f13SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
141aacc5f13SAndrew Boyer 		struct rte_cryptodev_stats *q_stats = &dev->cryptoqs[i]->stats;
142aacc5f13SAndrew Boyer 
143aacc5f13SAndrew Boyer 		stats->enqueued_count    += q_stats->enqueued_count;
144aacc5f13SAndrew Boyer 		stats->dequeued_count    += q_stats->dequeued_count;
145aacc5f13SAndrew Boyer 		stats->enqueue_err_count += q_stats->enqueue_err_count;
146aacc5f13SAndrew Boyer 		stats->dequeue_err_count += q_stats->dequeue_err_count;
147aacc5f13SAndrew Boyer 	}
148aacc5f13SAndrew Boyer }
149aacc5f13SAndrew Boyer 
150aacc5f13SAndrew Boyer void
iocpt_get_stats(const struct iocpt_dev * dev,struct rte_cryptodev_stats * stats)151aacc5f13SAndrew Boyer iocpt_get_stats(const struct iocpt_dev *dev, struct rte_cryptodev_stats *stats)
152aacc5f13SAndrew Boyer {
153aacc5f13SAndrew Boyer 	/* Retrieve the new absolute stats values */
154aacc5f13SAndrew Boyer 	iocpt_get_abs_stats(dev, stats);
155aacc5f13SAndrew Boyer 
156aacc5f13SAndrew Boyer 	/* Subtract the base stats values to get relative values */
157aacc5f13SAndrew Boyer 	stats->enqueued_count    -= dev->stats_base.enqueued_count;
158aacc5f13SAndrew Boyer 	stats->dequeued_count    -= dev->stats_base.dequeued_count;
159aacc5f13SAndrew Boyer 	stats->enqueue_err_count -= dev->stats_base.enqueue_err_count;
160aacc5f13SAndrew Boyer 	stats->dequeue_err_count -= dev->stats_base.dequeue_err_count;
161aacc5f13SAndrew Boyer }
162aacc5f13SAndrew Boyer 
163aacc5f13SAndrew Boyer void
iocpt_reset_stats(struct iocpt_dev * dev)164aacc5f13SAndrew Boyer iocpt_reset_stats(struct iocpt_dev *dev)
165aacc5f13SAndrew Boyer {
166aacc5f13SAndrew Boyer 	uint32_t i;
167aacc5f13SAndrew Boyer 
168aacc5f13SAndrew Boyer 	/* Erase the per-queue stats counters */
169aacc5f13SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++)
170aacc5f13SAndrew Boyer 		memset(&dev->cryptoqs[i]->stats, 0,
171aacc5f13SAndrew Boyer 			sizeof(dev->cryptoqs[i]->stats));
172aacc5f13SAndrew Boyer 
173aacc5f13SAndrew Boyer 	/* Update the base stats values */
174aacc5f13SAndrew Boyer 	iocpt_get_abs_stats(dev, &dev->stats_base);
175aacc5f13SAndrew Boyer }
176aacc5f13SAndrew Boyer 
1776bc7f2cfSAndrew Boyer static int
iocpt_session_write(struct iocpt_session_priv * priv,enum iocpt_sess_control_oper oper)1786bc7f2cfSAndrew Boyer iocpt_session_write(struct iocpt_session_priv *priv,
1796bc7f2cfSAndrew Boyer 		enum iocpt_sess_control_oper oper)
1806bc7f2cfSAndrew Boyer {
1816bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = priv->dev;
1826bc7f2cfSAndrew Boyer 	struct iocpt_admin_ctx ctx = {
1836bc7f2cfSAndrew Boyer 		.pending_work = true,
1846bc7f2cfSAndrew Boyer 		.cmd.sess_control = {
1856bc7f2cfSAndrew Boyer 			.opcode = IOCPT_CMD_SESS_CONTROL,
1866bc7f2cfSAndrew Boyer 			.type = priv->type,
1876bc7f2cfSAndrew Boyer 			.oper = oper,
1886bc7f2cfSAndrew Boyer 			.index = rte_cpu_to_le_32(priv->index),
1896bc7f2cfSAndrew Boyer 			.key_len = rte_cpu_to_le_16(priv->key_len),
1906bc7f2cfSAndrew Boyer 			.key_seg_len = (uint8_t)RTE_MIN(priv->key_len,
1916bc7f2cfSAndrew Boyer 						IOCPT_SESS_KEY_SEG_LEN),
1926bc7f2cfSAndrew Boyer 		},
1936bc7f2cfSAndrew Boyer 	};
1946bc7f2cfSAndrew Boyer 	struct iocpt_sess_control_cmd *cmd = &ctx.cmd.sess_control;
1956bc7f2cfSAndrew Boyer 	uint16_t key_offset;
196c09a6e7aSAndrew Boyer 	uint8_t key_segs, seg, seg_len;
1976bc7f2cfSAndrew Boyer 	int err;
1986bc7f2cfSAndrew Boyer 
1996bc7f2cfSAndrew Boyer 	key_segs = ((priv->key_len - 1) >> IOCPT_SESS_KEY_SEG_SHFT) + 1;
2006bc7f2cfSAndrew Boyer 
2016bc7f2cfSAndrew Boyer 	for (seg = 0; seg < key_segs; seg++) {
2026bc7f2cfSAndrew Boyer 		ctx.pending_work = true;
2036bc7f2cfSAndrew Boyer 
2046bc7f2cfSAndrew Boyer 		key_offset = seg * cmd->key_seg_len;
205c09a6e7aSAndrew Boyer 		seg_len = (uint8_t)RTE_MIN(priv->key_len - key_offset,
2066bc7f2cfSAndrew Boyer 					IOCPT_SESS_KEY_SEG_LEN);
207c09a6e7aSAndrew Boyer 		memcpy(cmd->key, &priv->key[key_offset], seg_len);
2086bc7f2cfSAndrew Boyer 		cmd->key_seg_idx = seg;
2096bc7f2cfSAndrew Boyer 
2106bc7f2cfSAndrew Boyer 		/* Mark final segment */
2116bc7f2cfSAndrew Boyer 		if (seg + 1 == key_segs)
2126bc7f2cfSAndrew Boyer 			cmd->flags |= rte_cpu_to_le_16(IOCPT_SCTL_F_END);
2136bc7f2cfSAndrew Boyer 
2146bc7f2cfSAndrew Boyer 		err = iocpt_adminq_post_wait(dev, &ctx);
2156bc7f2cfSAndrew Boyer 		if (err != 0)
2166bc7f2cfSAndrew Boyer 			return err;
2176bc7f2cfSAndrew Boyer 	}
2186bc7f2cfSAndrew Boyer 
2196bc7f2cfSAndrew Boyer 	return 0;
2206bc7f2cfSAndrew Boyer }
2216bc7f2cfSAndrew Boyer 
22254d56abaSAndrew Boyer static int
iocpt_session_wdog(struct iocpt_dev * dev)22354d56abaSAndrew Boyer iocpt_session_wdog(struct iocpt_dev *dev)
22454d56abaSAndrew Boyer {
22554d56abaSAndrew Boyer 	struct iocpt_session_priv priv = {
22654d56abaSAndrew Boyer 		.dev = dev,
22754d56abaSAndrew Boyer 		.index = IOCPT_Q_WDOG_SESS_IDX,
22854d56abaSAndrew Boyer 		.type = IOCPT_SESS_AEAD_AES_GCM,
22954d56abaSAndrew Boyer 		.key_len = IOCPT_Q_WDOG_KEY_LEN,
23054d56abaSAndrew Boyer 	};
23154d56abaSAndrew Boyer 
23254d56abaSAndrew Boyer 	/* Reserve session 0 for queue watchdog */
23354d56abaSAndrew Boyer 	rte_bitmap_clear(dev->sess_bm, IOCPT_Q_WDOG_SESS_IDX);
23454d56abaSAndrew Boyer 
23554d56abaSAndrew Boyer 	return iocpt_session_write(&priv, IOCPT_SESS_INIT);
23654d56abaSAndrew Boyer }
23754d56abaSAndrew Boyer 
2386bc7f2cfSAndrew Boyer int
iocpt_session_init(struct iocpt_session_priv * priv)2396bc7f2cfSAndrew Boyer iocpt_session_init(struct iocpt_session_priv *priv)
2406bc7f2cfSAndrew Boyer {
2416bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = priv->dev;
2426bc7f2cfSAndrew Boyer 	uint64_t bm_slab = 0;
2436bc7f2cfSAndrew Boyer 	uint32_t bm_pos = 0;
2446bc7f2cfSAndrew Boyer 	int err = 0;
2456bc7f2cfSAndrew Boyer 
2466bc7f2cfSAndrew Boyer 	rte_spinlock_lock(&dev->adminq_lock);
2476bc7f2cfSAndrew Boyer 
2486bc7f2cfSAndrew Boyer 	if (rte_bitmap_scan(dev->sess_bm, &bm_pos, &bm_slab) > 0) {
2496bc7f2cfSAndrew Boyer 		priv->index = bm_pos + rte_ctz64(bm_slab);
2506bc7f2cfSAndrew Boyer 		rte_bitmap_clear(dev->sess_bm, priv->index);
2516bc7f2cfSAndrew Boyer 	} else
2526bc7f2cfSAndrew Boyer 		err = -ENOSPC;
2536bc7f2cfSAndrew Boyer 
2546bc7f2cfSAndrew Boyer 	rte_spinlock_unlock(&dev->adminq_lock);
2556bc7f2cfSAndrew Boyer 
2566bc7f2cfSAndrew Boyer 	if (err != 0) {
2576bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "session index space exhausted");
2586bc7f2cfSAndrew Boyer 		return err;
2596bc7f2cfSAndrew Boyer 	}
2606bc7f2cfSAndrew Boyer 
2616bc7f2cfSAndrew Boyer 	err = iocpt_session_write(priv, IOCPT_SESS_INIT);
2626bc7f2cfSAndrew Boyer 	if (err != 0) {
2636bc7f2cfSAndrew Boyer 		rte_spinlock_lock(&dev->adminq_lock);
2646bc7f2cfSAndrew Boyer 		rte_bitmap_set(dev->sess_bm, priv->index);
2656bc7f2cfSAndrew Boyer 		rte_spinlock_unlock(&dev->adminq_lock);
2666bc7f2cfSAndrew Boyer 		return err;
2676bc7f2cfSAndrew Boyer 	}
2686bc7f2cfSAndrew Boyer 
2696bc7f2cfSAndrew Boyer 	priv->flags |= IOCPT_S_F_INITED;
2706bc7f2cfSAndrew Boyer 
2716bc7f2cfSAndrew Boyer 	return 0;
2726bc7f2cfSAndrew Boyer }
2736bc7f2cfSAndrew Boyer 
2746bc7f2cfSAndrew Boyer int
iocpt_session_update(struct iocpt_session_priv * priv)2756bc7f2cfSAndrew Boyer iocpt_session_update(struct iocpt_session_priv *priv)
2766bc7f2cfSAndrew Boyer {
2776bc7f2cfSAndrew Boyer 	return iocpt_session_write(priv, IOCPT_SESS_UPDATE_KEY);
2786bc7f2cfSAndrew Boyer }
2796bc7f2cfSAndrew Boyer 
2806bc7f2cfSAndrew Boyer void
iocpt_session_deinit(struct iocpt_session_priv * priv)2816bc7f2cfSAndrew Boyer iocpt_session_deinit(struct iocpt_session_priv *priv)
2826bc7f2cfSAndrew Boyer {
2836bc7f2cfSAndrew Boyer 	struct iocpt_dev *dev = priv->dev;
2846bc7f2cfSAndrew Boyer 	struct iocpt_admin_ctx ctx = {
2856bc7f2cfSAndrew Boyer 		.pending_work = true,
2866bc7f2cfSAndrew Boyer 		.cmd.sess_control = {
2876bc7f2cfSAndrew Boyer 			.opcode = IOCPT_CMD_SESS_CONTROL,
2886bc7f2cfSAndrew Boyer 			.type = priv->type,
2896bc7f2cfSAndrew Boyer 			.oper = IOCPT_SESS_DISABLE,
2906bc7f2cfSAndrew Boyer 			.index = rte_cpu_to_le_32(priv->index),
2916bc7f2cfSAndrew Boyer 			.key_len = rte_cpu_to_le_16(priv->key_len),
2926bc7f2cfSAndrew Boyer 		},
2936bc7f2cfSAndrew Boyer 	};
2946bc7f2cfSAndrew Boyer 
2956bc7f2cfSAndrew Boyer 	(void)iocpt_adminq_post_wait(dev, &ctx);
2966bc7f2cfSAndrew Boyer 
2976bc7f2cfSAndrew Boyer 	rte_spinlock_lock(&dev->adminq_lock);
2986bc7f2cfSAndrew Boyer 	rte_bitmap_set(dev->sess_bm, priv->index);
2996bc7f2cfSAndrew Boyer 	rte_spinlock_unlock(&dev->adminq_lock);
3006bc7f2cfSAndrew Boyer 
3016bc7f2cfSAndrew Boyer 	priv->flags &= ~IOCPT_S_F_INITED;
3026bc7f2cfSAndrew Boyer }
3036bc7f2cfSAndrew Boyer 
304a677112dSAndrew Boyer static const struct rte_memzone *
iocpt_dma_zone_reserve(const char * type_name,uint16_t qid,size_t size,unsigned int align,int socket_id)305a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size,
306a677112dSAndrew Boyer 			unsigned int align, int socket_id)
307a677112dSAndrew Boyer {
308a677112dSAndrew Boyer 	char zone_name[RTE_MEMZONE_NAMESIZE];
309a677112dSAndrew Boyer 	const struct rte_memzone *mz;
310a677112dSAndrew Boyer 	int err;
311a677112dSAndrew Boyer 
312a677112dSAndrew Boyer 	err = snprintf(zone_name, sizeof(zone_name),
313a677112dSAndrew Boyer 			"iocpt_%s_%u", type_name, qid);
314a677112dSAndrew Boyer 	if (err >= RTE_MEMZONE_NAMESIZE) {
315a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Name %s too long", type_name);
316a677112dSAndrew Boyer 		return NULL;
317a677112dSAndrew Boyer 	}
318a677112dSAndrew Boyer 
319a677112dSAndrew Boyer 	mz = rte_memzone_lookup(zone_name);
320a677112dSAndrew Boyer 	if (mz != NULL)
321a677112dSAndrew Boyer 		return mz;
322a677112dSAndrew Boyer 
323a677112dSAndrew Boyer 	return rte_memzone_reserve_aligned(zone_name, size, socket_id,
324a677112dSAndrew Boyer 			RTE_MEMZONE_IOVA_CONTIG, align);
325a677112dSAndrew Boyer }
326a677112dSAndrew Boyer 
327a677112dSAndrew Boyer static int
iocpt_commonq_alloc(struct iocpt_dev * dev,uint8_t type,size_t struct_size,uint32_t socket_id,uint32_t index,const char * type_name,uint16_t flags,uint16_t num_descs,uint16_t num_segs,uint16_t desc_size,uint16_t cq_desc_size,uint16_t sg_desc_size,struct iocpt_common_q ** comq)3282c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev,
3292c1662bbSAndrew Boyer 		uint8_t type,
3302c1662bbSAndrew Boyer 		size_t struct_size,
3312c1662bbSAndrew Boyer 		uint32_t socket_id,
3322c1662bbSAndrew Boyer 		uint32_t index,
3332c1662bbSAndrew Boyer 		const char *type_name,
3342c1662bbSAndrew Boyer 		uint16_t flags,
3352c1662bbSAndrew Boyer 		uint16_t num_descs,
3362c1662bbSAndrew Boyer 		uint16_t num_segs,
3372c1662bbSAndrew Boyer 		uint16_t desc_size,
3382c1662bbSAndrew Boyer 		uint16_t cq_desc_size,
3392c1662bbSAndrew Boyer 		uint16_t sg_desc_size,
3402c1662bbSAndrew Boyer 		struct iocpt_common_q **comq)
3412c1662bbSAndrew Boyer {
3422c1662bbSAndrew Boyer 	struct iocpt_common_q *new;
3432c1662bbSAndrew Boyer 	uint32_t q_size, cq_size, sg_size, total_size;
3442c1662bbSAndrew Boyer 	void *q_base, *cq_base, *sg_base;
3452c1662bbSAndrew Boyer 	rte_iova_t q_base_pa = 0;
3462c1662bbSAndrew Boyer 	rte_iova_t cq_base_pa = 0;
3472c1662bbSAndrew Boyer 	rte_iova_t sg_base_pa = 0;
3482c1662bbSAndrew Boyer 	size_t page_size = rte_mem_page_size();
3492c1662bbSAndrew Boyer 	int err;
3502c1662bbSAndrew Boyer 
3512c1662bbSAndrew Boyer 	*comq = NULL;
3522c1662bbSAndrew Boyer 
3532c1662bbSAndrew Boyer 	q_size	= num_descs * desc_size;
3542c1662bbSAndrew Boyer 	cq_size = num_descs * cq_desc_size;
3552c1662bbSAndrew Boyer 	sg_size = num_descs * sg_desc_size;
3562c1662bbSAndrew Boyer 
3572c1662bbSAndrew Boyer 	/*
3582c1662bbSAndrew Boyer 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
3592c1662bbSAndrew Boyer 	 * aligning as q_base could be not aligned to the page.
3602c1662bbSAndrew Boyer 	 * Adding page_size.
3612c1662bbSAndrew Boyer 	 */
3622c1662bbSAndrew Boyer 	total_size = RTE_ALIGN(q_size, page_size) +
3632c1662bbSAndrew Boyer 		RTE_ALIGN(cq_size, page_size) + page_size;
3642c1662bbSAndrew Boyer 	if (flags & IOCPT_Q_F_SG)
3652c1662bbSAndrew Boyer 		total_size += RTE_ALIGN(sg_size, page_size) + page_size;
3662c1662bbSAndrew Boyer 
3672c1662bbSAndrew Boyer 	new = rte_zmalloc_socket("iocpt", struct_size,
3682c1662bbSAndrew Boyer 			RTE_CACHE_LINE_SIZE, socket_id);
3692c1662bbSAndrew Boyer 	if (new == NULL) {
3702c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate queue structure");
3712c1662bbSAndrew Boyer 		return -ENOMEM;
3722c1662bbSAndrew Boyer 	}
3732c1662bbSAndrew Boyer 
3742c1662bbSAndrew Boyer 	new->dev = dev;
3752c1662bbSAndrew Boyer 
3762c1662bbSAndrew Boyer 	err = iocpt_q_init(&new->q, type, index, num_descs, num_segs,
3772c1662bbSAndrew Boyer 			socket_id);
3782c1662bbSAndrew Boyer 	if (err != 0) {
3792c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Queue initialization failed");
3802c1662bbSAndrew Boyer 		goto err_free_q;
3812c1662bbSAndrew Boyer 	}
3822c1662bbSAndrew Boyer 
3832c1662bbSAndrew Boyer 	err = iocpt_cq_init(&new->cq, num_descs);
3842c1662bbSAndrew Boyer 	if (err != 0) {
3852c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Completion queue initialization failed");
3862c1662bbSAndrew Boyer 		goto err_deinit_q;
3872c1662bbSAndrew Boyer 	}
3882c1662bbSAndrew Boyer 
3892c1662bbSAndrew Boyer 	new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size,
3902c1662bbSAndrew Boyer 					IONIC_ALIGN, socket_id);
3912c1662bbSAndrew Boyer 	if (new->base_z == NULL) {
3922c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory");
3932c1662bbSAndrew Boyer 		err = -ENOMEM;
3942c1662bbSAndrew Boyer 		goto err_deinit_cq;
3952c1662bbSAndrew Boyer 	}
3962c1662bbSAndrew Boyer 
3972c1662bbSAndrew Boyer 	new->base = new->base_z->addr;
3982c1662bbSAndrew Boyer 	new->base_pa = new->base_z->iova;
3992c1662bbSAndrew Boyer 
4002c1662bbSAndrew Boyer 	q_base = new->base;
4012c1662bbSAndrew Boyer 	q_base_pa = new->base_pa;
4022c1662bbSAndrew Boyer 	iocpt_q_map(&new->q, q_base, q_base_pa);
4032c1662bbSAndrew Boyer 
4042c1662bbSAndrew Boyer 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
4052c1662bbSAndrew Boyer 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
4062c1662bbSAndrew Boyer 	iocpt_cq_map(&new->cq, cq_base, cq_base_pa);
4072c1662bbSAndrew Boyer 
4082c1662bbSAndrew Boyer 	if (flags & IOCPT_Q_F_SG) {
4092c1662bbSAndrew Boyer 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
4102c1662bbSAndrew Boyer 			page_size);
4112c1662bbSAndrew Boyer 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
4122c1662bbSAndrew Boyer 		iocpt_q_sg_map(&new->q, sg_base, sg_base_pa);
4132c1662bbSAndrew Boyer 	}
4142c1662bbSAndrew Boyer 
4152c1662bbSAndrew Boyer 	IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx",
4162c1662bbSAndrew Boyer 		q_base_pa, cq_base_pa, sg_base_pa);
4172c1662bbSAndrew Boyer 
4182c1662bbSAndrew Boyer 	*comq = new;
4192c1662bbSAndrew Boyer 
4202c1662bbSAndrew Boyer 	return 0;
4212c1662bbSAndrew Boyer 
4222c1662bbSAndrew Boyer err_deinit_cq:
4232c1662bbSAndrew Boyer err_deinit_q:
4242c1662bbSAndrew Boyer 	iocpt_q_free(&new->q);
4252c1662bbSAndrew Boyer err_free_q:
4262c1662bbSAndrew Boyer 	rte_free(new);
4272c1662bbSAndrew Boyer 	return err;
4282c1662bbSAndrew Boyer }
4292c1662bbSAndrew Boyer 
43080518852SAndrew Boyer int
iocpt_cryptoq_alloc(struct iocpt_dev * dev,uint32_t socket_id,uint32_t index,uint16_t num_descs)43180518852SAndrew Boyer iocpt_cryptoq_alloc(struct iocpt_dev *dev, uint32_t socket_id, uint32_t index,
43280518852SAndrew Boyer 		uint16_t num_descs)
43380518852SAndrew Boyer {
43480518852SAndrew Boyer 	struct iocpt_crypto_q *cptq;
43580518852SAndrew Boyer 	uint16_t flags = 0;
43680518852SAndrew Boyer 	int err;
43780518852SAndrew Boyer 
43880518852SAndrew Boyer 	/* CryptoQ always supports scatter-gather */
43980518852SAndrew Boyer 	flags |= IOCPT_Q_F_SG;
44080518852SAndrew Boyer 
44180518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq %u num_descs %u num_segs %u",
44280518852SAndrew Boyer 		index, num_descs, 1);
44380518852SAndrew Boyer 
44480518852SAndrew Boyer 	err = iocpt_commonq_alloc(dev,
44580518852SAndrew Boyer 		IOCPT_QTYPE_CRYPTOQ,
44680518852SAndrew Boyer 		sizeof(struct iocpt_crypto_q),
44780518852SAndrew Boyer 		socket_id,
44880518852SAndrew Boyer 		index,
44980518852SAndrew Boyer 		"crypto",
45080518852SAndrew Boyer 		flags,
45180518852SAndrew Boyer 		num_descs,
45280518852SAndrew Boyer 		1,
45380518852SAndrew Boyer 		sizeof(struct iocpt_crypto_desc),
45480518852SAndrew Boyer 		sizeof(struct iocpt_crypto_comp),
45580518852SAndrew Boyer 		sizeof(struct iocpt_crypto_sg_desc),
45680518852SAndrew Boyer 		(struct iocpt_common_q **)&cptq);
45780518852SAndrew Boyer 	if (err != 0)
45880518852SAndrew Boyer 		return err;
45980518852SAndrew Boyer 
46080518852SAndrew Boyer 	cptq->flags = flags;
46180518852SAndrew Boyer 
46280518852SAndrew Boyer 	dev->cryptoqs[index] = cptq;
46380518852SAndrew Boyer 
46480518852SAndrew Boyer 	return 0;
46580518852SAndrew Boyer }
46680518852SAndrew Boyer 
4672c1662bbSAndrew Boyer struct ionic_doorbell *
iocpt_db_map(struct iocpt_dev * dev,struct iocpt_queue * q)4682c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q)
4692c1662bbSAndrew Boyer {
4702c1662bbSAndrew Boyer 	return dev->db_pages + q->hw_type;
4712c1662bbSAndrew Boyer }
4722c1662bbSAndrew Boyer 
4732c1662bbSAndrew Boyer static int
iocpt_cryptoq_init(struct iocpt_crypto_q * cptq)47480518852SAndrew Boyer iocpt_cryptoq_init(struct iocpt_crypto_q *cptq)
47580518852SAndrew Boyer {
47680518852SAndrew Boyer 	struct iocpt_queue *q = &cptq->q;
47780518852SAndrew Boyer 	struct iocpt_dev *dev = cptq->dev;
47880518852SAndrew Boyer 	struct iocpt_cq *cq = &cptq->cq;
47980518852SAndrew Boyer 	struct iocpt_admin_ctx ctx = {
48080518852SAndrew Boyer 		.pending_work = true,
48180518852SAndrew Boyer 		.cmd.q_init = {
48280518852SAndrew Boyer 			.opcode = IOCPT_CMD_Q_INIT,
48380518852SAndrew Boyer 			.type = IOCPT_QTYPE_CRYPTOQ,
48480518852SAndrew Boyer 			.ver = dev->qtype_info[IOCPT_QTYPE_CRYPTOQ].version,
48580518852SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
48680518852SAndrew Boyer 			.flags = rte_cpu_to_le_16(IOCPT_QINIT_F_ENA |
48780518852SAndrew Boyer 						IOCPT_QINIT_F_SG),
48880518852SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
48980518852SAndrew Boyer 			.ring_size = rte_log2_u32(q->num_descs),
49080518852SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
49180518852SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
49280518852SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
49380518852SAndrew Boyer 		},
49480518852SAndrew Boyer 	};
49580518852SAndrew Boyer 	int err;
49680518852SAndrew Boyer 
49780518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.index %d", q->index);
49880518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.ring_base %#jx", q->base_pa);
49980518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.ring_size %d",
50080518852SAndrew Boyer 		ctx.cmd.q_init.ring_size);
50180518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq_init.ver %u", ctx.cmd.q_init.ver);
50280518852SAndrew Boyer 
50380518852SAndrew Boyer 	iocpt_q_reset(q);
50480518852SAndrew Boyer 	iocpt_cq_reset(cq);
50580518852SAndrew Boyer 
50680518852SAndrew Boyer 	err = iocpt_adminq_post_wait(dev, &ctx);
50780518852SAndrew Boyer 	if (err != 0)
50880518852SAndrew Boyer 		return err;
50980518852SAndrew Boyer 
51080518852SAndrew Boyer 	q->hw_type = ctx.comp.q_init.hw_type;
51180518852SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
51280518852SAndrew Boyer 	q->db = iocpt_db_map(dev, q);
51380518852SAndrew Boyer 
51480518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq->hw_type %d", q->hw_type);
51580518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq->hw_index %d", q->hw_index);
51680518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "cptq->db %p", q->db);
51780518852SAndrew Boyer 
51880518852SAndrew Boyer 	cptq->flags |= IOCPT_Q_F_INITED;
51980518852SAndrew Boyer 
52080518852SAndrew Boyer 	return 0;
52180518852SAndrew Boyer }
52280518852SAndrew Boyer 
52380518852SAndrew Boyer static void
iocpt_cryptoq_deinit(struct iocpt_crypto_q * cptq)52480518852SAndrew Boyer iocpt_cryptoq_deinit(struct iocpt_crypto_q *cptq)
52580518852SAndrew Boyer {
52680518852SAndrew Boyer 	struct iocpt_dev *dev = cptq->dev;
52780518852SAndrew Boyer 	struct iocpt_admin_ctx ctx = {
52880518852SAndrew Boyer 		.pending_work = true,
52980518852SAndrew Boyer 		.cmd.q_control = {
53080518852SAndrew Boyer 			.opcode = IOCPT_CMD_Q_CONTROL,
53180518852SAndrew Boyer 			.type = IOCPT_QTYPE_CRYPTOQ,
53280518852SAndrew Boyer 			.index = rte_cpu_to_le_32(cptq->q.index),
53380518852SAndrew Boyer 			.oper = IOCPT_Q_DISABLE,
53480518852SAndrew Boyer 		},
53580518852SAndrew Boyer 	};
53680518852SAndrew Boyer 	unsigned long sleep_usec = 100UL * 1000;
53780518852SAndrew Boyer 	uint32_t sleep_cnt, sleep_max = IOCPT_CRYPTOQ_WAIT;
53880518852SAndrew Boyer 	int err;
53980518852SAndrew Boyer 
54080518852SAndrew Boyer 	for (sleep_cnt = 0; sleep_cnt < sleep_max; sleep_cnt++) {
54180518852SAndrew Boyer 		ctx.pending_work = true;
54280518852SAndrew Boyer 
54380518852SAndrew Boyer 		err = iocpt_adminq_post_wait(dev, &ctx);
54480518852SAndrew Boyer 		if (err != -EAGAIN)
54580518852SAndrew Boyer 			break;
54680518852SAndrew Boyer 
54780518852SAndrew Boyer 		rte_delay_us_block(sleep_usec);
54880518852SAndrew Boyer 	}
54980518852SAndrew Boyer 
55080518852SAndrew Boyer 	if (err != 0)
55180518852SAndrew Boyer 		IOCPT_PRINT(ERR, "Deinit queue %u returned %d after %u ms",
55280518852SAndrew Boyer 			cptq->q.index, err, sleep_cnt * 100);
55380518852SAndrew Boyer 	else
55480518852SAndrew Boyer 		IOCPT_PRINT(DEBUG, "Deinit queue %u returned %d after %u ms",
55580518852SAndrew Boyer 			cptq->q.index, err, sleep_cnt * 100);
55680518852SAndrew Boyer 
55754d56abaSAndrew Boyer 	IOCPT_PRINT(DEBUG, "Queue %u watchdog: enq %"PRIu64" deq %"PRIu64,
55854d56abaSAndrew Boyer 		cptq->q.index, cptq->enqueued_wdogs, cptq->dequeued_wdogs);
55954d56abaSAndrew Boyer 
56080518852SAndrew Boyer 	cptq->flags &= ~IOCPT_Q_F_INITED;
56180518852SAndrew Boyer }
56280518852SAndrew Boyer 
56380518852SAndrew Boyer void
iocpt_cryptoq_free(struct iocpt_crypto_q * cptq)56480518852SAndrew Boyer iocpt_cryptoq_free(struct iocpt_crypto_q *cptq)
56580518852SAndrew Boyer {
56680518852SAndrew Boyer 	if (cptq == NULL)
56780518852SAndrew Boyer 		return;
56880518852SAndrew Boyer 
56980518852SAndrew Boyer 	if (cptq->base_z != NULL) {
57080518852SAndrew Boyer 		rte_memzone_free(cptq->base_z);
57180518852SAndrew Boyer 		cptq->base_z = NULL;
57280518852SAndrew Boyer 		cptq->base = NULL;
57380518852SAndrew Boyer 		cptq->base_pa = 0;
57480518852SAndrew Boyer 	}
57580518852SAndrew Boyer 
57680518852SAndrew Boyer 	iocpt_q_free(&cptq->q);
57780518852SAndrew Boyer 
57880518852SAndrew Boyer 	rte_free(cptq);
57980518852SAndrew Boyer }
58080518852SAndrew Boyer 
58180518852SAndrew Boyer static int
iocpt_adminq_alloc(struct iocpt_dev * dev)5822c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev)
5832c1662bbSAndrew Boyer {
5842c1662bbSAndrew Boyer 	struct iocpt_admin_q *aq;
5852c1662bbSAndrew Boyer 	uint16_t num_descs = IOCPT_ADMINQ_LENGTH;
5862c1662bbSAndrew Boyer 	uint16_t flags = 0;
5872c1662bbSAndrew Boyer 	int err;
5882c1662bbSAndrew Boyer 
5892c1662bbSAndrew Boyer 	err = iocpt_commonq_alloc(dev,
5902c1662bbSAndrew Boyer 		IOCPT_QTYPE_ADMINQ,
5912c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_q),
5922c1662bbSAndrew Boyer 		rte_socket_id(),
5932c1662bbSAndrew Boyer 		0,
5942c1662bbSAndrew Boyer 		"admin",
5952c1662bbSAndrew Boyer 		flags,
5962c1662bbSAndrew Boyer 		num_descs,
5972c1662bbSAndrew Boyer 		1,
5982c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_cmd),
5992c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_comp),
6002c1662bbSAndrew Boyer 		0,
6012c1662bbSAndrew Boyer 		(struct iocpt_common_q **)&aq);
6022c1662bbSAndrew Boyer 	if (err != 0)
6032c1662bbSAndrew Boyer 		return err;
6042c1662bbSAndrew Boyer 
6052c1662bbSAndrew Boyer 	aq->flags = flags;
6062c1662bbSAndrew Boyer 
6072c1662bbSAndrew Boyer 	dev->adminq = aq;
6082c1662bbSAndrew Boyer 
6092c1662bbSAndrew Boyer 	return 0;
6102c1662bbSAndrew Boyer }
6112c1662bbSAndrew Boyer 
6122c1662bbSAndrew Boyer static int
iocpt_adminq_init(struct iocpt_dev * dev)6132c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev)
6142c1662bbSAndrew Boyer {
6152c1662bbSAndrew Boyer 	return iocpt_dev_adminq_init(dev);
6162c1662bbSAndrew Boyer }
6172c1662bbSAndrew Boyer 
6182c1662bbSAndrew Boyer static void
iocpt_adminq_deinit(struct iocpt_dev * dev)6192c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev)
6202c1662bbSAndrew Boyer {
6212c1662bbSAndrew Boyer 	dev->adminq->flags &= ~IOCPT_Q_F_INITED;
6222c1662bbSAndrew Boyer }
6232c1662bbSAndrew Boyer 
6242c1662bbSAndrew Boyer static void
iocpt_adminq_free(struct iocpt_admin_q * aq)6252c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq)
6262c1662bbSAndrew Boyer {
6272c1662bbSAndrew Boyer 	if (aq->base_z != NULL) {
6282c1662bbSAndrew Boyer 		rte_memzone_free(aq->base_z);
6292c1662bbSAndrew Boyer 		aq->base_z = NULL;
6302c1662bbSAndrew Boyer 		aq->base = NULL;
6312c1662bbSAndrew Boyer 		aq->base_pa = 0;
6322c1662bbSAndrew Boyer 	}
6332c1662bbSAndrew Boyer 
6342c1662bbSAndrew Boyer 	iocpt_q_free(&aq->q);
6352c1662bbSAndrew Boyer 
6362c1662bbSAndrew Boyer 	rte_free(aq);
6372c1662bbSAndrew Boyer }
6382c1662bbSAndrew Boyer 
6392c1662bbSAndrew Boyer static int
iocpt_alloc_objs(struct iocpt_dev * dev)640a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev)
641a677112dSAndrew Boyer {
6426bc7f2cfSAndrew Boyer 	uint32_t bmsize, i;
6436bc7f2cfSAndrew Boyer 	uint8_t *bm;
644a677112dSAndrew Boyer 	int err;
645a677112dSAndrew Boyer 
646a677112dSAndrew Boyer 	IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name);
647a677112dSAndrew Boyer 
64880518852SAndrew Boyer 	dev->cryptoqs = rte_calloc_socket("iocpt",
64980518852SAndrew Boyer 				dev->max_qps, sizeof(*dev->cryptoqs),
65080518852SAndrew Boyer 				RTE_CACHE_LINE_SIZE, dev->socket_id);
65180518852SAndrew Boyer 	if (dev->cryptoqs == NULL) {
65280518852SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate tx queues array");
65380518852SAndrew Boyer 		return -ENOMEM;
65480518852SAndrew Boyer 	}
65580518852SAndrew Boyer 
6562c1662bbSAndrew Boyer 	rte_spinlock_init(&dev->adminq_lock);
6572c1662bbSAndrew Boyer 	rte_spinlock_init(&dev->adminq_service_lock);
6582c1662bbSAndrew Boyer 
6592c1662bbSAndrew Boyer 	err = iocpt_adminq_alloc(dev);
6602c1662bbSAndrew Boyer 	if (err != 0) {
6612c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate admin queue");
6622c1662bbSAndrew Boyer 		err = -ENOMEM;
66380518852SAndrew Boyer 		goto err_free_cryptoqs;
6642c1662bbSAndrew Boyer 	}
6652c1662bbSAndrew Boyer 
666a677112dSAndrew Boyer 	dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size());
667a677112dSAndrew Boyer 	dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz,
668a677112dSAndrew Boyer 					IONIC_ALIGN, dev->socket_id);
669a677112dSAndrew Boyer 	if (dev->info_z == NULL) {
670a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate dev info memory");
671a677112dSAndrew Boyer 		err = -ENOMEM;
6722c1662bbSAndrew Boyer 		goto err_free_adminq;
673a677112dSAndrew Boyer 	}
674a677112dSAndrew Boyer 
675a677112dSAndrew Boyer 	dev->info = dev->info_z->addr;
676a677112dSAndrew Boyer 	dev->info_pa = dev->info_z->iova;
677a677112dSAndrew Boyer 
6786bc7f2cfSAndrew Boyer 	bmsize = rte_bitmap_get_memory_footprint(dev->max_sessions);
6796bc7f2cfSAndrew Boyer 	bm = rte_malloc_socket("iocpt", bmsize,
6806bc7f2cfSAndrew Boyer 			RTE_CACHE_LINE_SIZE, dev->socket_id);
6816bc7f2cfSAndrew Boyer 	if (bm == NULL) {
6826bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate %uB bitmap memory", bmsize);
6836bc7f2cfSAndrew Boyer 		err = -ENOMEM;
6846bc7f2cfSAndrew Boyer 		goto err_free_dmazone;
6856bc7f2cfSAndrew Boyer 	}
6866bc7f2cfSAndrew Boyer 
6876bc7f2cfSAndrew Boyer 	dev->sess_bm = rte_bitmap_init(dev->max_sessions, bm, bmsize);
6886bc7f2cfSAndrew Boyer 	if (dev->sess_bm == NULL) {
6896bc7f2cfSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot initialize bitmap");
6906bc7f2cfSAndrew Boyer 		err = -EFAULT;
6916bc7f2cfSAndrew Boyer 		goto err_free_bm;
6926bc7f2cfSAndrew Boyer 	}
6936bc7f2cfSAndrew Boyer 	for (i = 0; i < dev->max_sessions; i++)
6946bc7f2cfSAndrew Boyer 		rte_bitmap_set(dev->sess_bm, i);
6956bc7f2cfSAndrew Boyer 
696a677112dSAndrew Boyer 	return 0;
697a677112dSAndrew Boyer 
6986bc7f2cfSAndrew Boyer err_free_bm:
6996bc7f2cfSAndrew Boyer 	rte_free(bm);
7006bc7f2cfSAndrew Boyer err_free_dmazone:
7016bc7f2cfSAndrew Boyer 	rte_memzone_free(dev->info_z);
7026bc7f2cfSAndrew Boyer 	dev->info_z = NULL;
7036bc7f2cfSAndrew Boyer 	dev->info = NULL;
7046bc7f2cfSAndrew Boyer 	dev->info_pa = 0;
7052c1662bbSAndrew Boyer err_free_adminq:
7062c1662bbSAndrew Boyer 	iocpt_adminq_free(dev->adminq);
7072c1662bbSAndrew Boyer 	dev->adminq = NULL;
70880518852SAndrew Boyer err_free_cryptoqs:
70980518852SAndrew Boyer 	rte_free(dev->cryptoqs);
71080518852SAndrew Boyer 	dev->cryptoqs = NULL;
711a677112dSAndrew Boyer 	return err;
712a677112dSAndrew Boyer }
713a677112dSAndrew Boyer 
7144610ac93SAndrew Boyer static int
iocpt_init(struct iocpt_dev * dev)7154610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev)
7164610ac93SAndrew Boyer {
717a677112dSAndrew Boyer 	int err;
718a677112dSAndrew Boyer 
719aacc5f13SAndrew Boyer 	memset(&dev->stats_base, 0, sizeof(dev->stats_base));
720aacc5f13SAndrew Boyer 
721a677112dSAndrew Boyer 	/* Uses dev_cmds */
722a677112dSAndrew Boyer 	err = iocpt_dev_init(dev, dev->info_pa);
723a677112dSAndrew Boyer 	if (err != 0)
724a677112dSAndrew Boyer 		return err;
725a677112dSAndrew Boyer 
7262c1662bbSAndrew Boyer 	err = iocpt_adminq_init(dev);
7272c1662bbSAndrew Boyer 	if (err != 0)
7282c1662bbSAndrew Boyer 		return err;
7292c1662bbSAndrew Boyer 
73054d56abaSAndrew Boyer 	/* Write the queue watchdog key */
73154d56abaSAndrew Boyer 	err = iocpt_session_wdog(dev);
73254d56abaSAndrew Boyer 	if (err != 0) {
73354d56abaSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot setup watchdog session");
73454d56abaSAndrew Boyer 		goto err_out_adminq_deinit;
73554d56abaSAndrew Boyer 	}
73654d56abaSAndrew Boyer 
7374610ac93SAndrew Boyer 	dev->state |= IOCPT_DEV_F_INITED;
7384610ac93SAndrew Boyer 
7394610ac93SAndrew Boyer 	return 0;
74054d56abaSAndrew Boyer 
74154d56abaSAndrew Boyer err_out_adminq_deinit:
74254d56abaSAndrew Boyer 	iocpt_adminq_deinit(dev);
74354d56abaSAndrew Boyer 
74454d56abaSAndrew Boyer 	return err;
7454610ac93SAndrew Boyer }
7464610ac93SAndrew Boyer 
7474610ac93SAndrew Boyer void
iocpt_configure(struct iocpt_dev * dev)7484610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev)
7494610ac93SAndrew Boyer {
7504610ac93SAndrew Boyer 	RTE_SET_USED(dev);
7514610ac93SAndrew Boyer }
7524610ac93SAndrew Boyer 
75380518852SAndrew Boyer int
iocpt_start(struct iocpt_dev * dev)75480518852SAndrew Boyer iocpt_start(struct iocpt_dev *dev)
75580518852SAndrew Boyer {
75680518852SAndrew Boyer 	uint32_t i;
75780518852SAndrew Boyer 	int err;
75880518852SAndrew Boyer 
75980518852SAndrew Boyer 	IOCPT_PRINT(DEBUG, "Starting %u queues",
76080518852SAndrew Boyer 		dev->crypto_dev->data->nb_queue_pairs);
76180518852SAndrew Boyer 
76280518852SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
76380518852SAndrew Boyer 		err = iocpt_cryptoq_init(dev->cryptoqs[i]);
76480518852SAndrew Boyer 		if (err != 0)
76580518852SAndrew Boyer 			return err;
76680518852SAndrew Boyer 	}
76780518852SAndrew Boyer 
76880518852SAndrew Boyer 	dev->state |= IOCPT_DEV_F_UP;
76980518852SAndrew Boyer 
77080518852SAndrew Boyer 	return 0;
77180518852SAndrew Boyer }
77280518852SAndrew Boyer 
77380518852SAndrew Boyer void
iocpt_stop(struct iocpt_dev * dev)77480518852SAndrew Boyer iocpt_stop(struct iocpt_dev *dev)
77580518852SAndrew Boyer {
77680518852SAndrew Boyer 	uint32_t i;
77780518852SAndrew Boyer 
77880518852SAndrew Boyer 	IOCPT_PRINT_CALL();
77980518852SAndrew Boyer 
78080518852SAndrew Boyer 	dev->state &= ~IOCPT_DEV_F_UP;
78180518852SAndrew Boyer 
78280518852SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
78380518852SAndrew Boyer 		struct iocpt_crypto_q *cptq = dev->cryptoqs[i];
78480518852SAndrew Boyer 
78580518852SAndrew Boyer 		if (cptq->flags & IOCPT_Q_F_INITED)
78680518852SAndrew Boyer 			(void)iocpt_cryptoq_deinit(cptq);
78780518852SAndrew Boyer 	}
78880518852SAndrew Boyer }
78980518852SAndrew Boyer 
7904610ac93SAndrew Boyer void
iocpt_deinit(struct iocpt_dev * dev)7914610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev)
7924610ac93SAndrew Boyer {
7934610ac93SAndrew Boyer 	IOCPT_PRINT_CALL();
7944610ac93SAndrew Boyer 
7954610ac93SAndrew Boyer 	if (!(dev->state & IOCPT_DEV_F_INITED))
7964610ac93SAndrew Boyer 		return;
7974610ac93SAndrew Boyer 
7982c1662bbSAndrew Boyer 	iocpt_adminq_deinit(dev);
7992c1662bbSAndrew Boyer 
8004610ac93SAndrew Boyer 	dev->state &= ~IOCPT_DEV_F_INITED;
8014610ac93SAndrew Boyer }
8024610ac93SAndrew Boyer 
803a677112dSAndrew Boyer static void
iocpt_free_objs(struct iocpt_dev * dev)804a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev)
805a677112dSAndrew Boyer {
80680518852SAndrew Boyer 	void **queue_pairs = dev->crypto_dev->data->queue_pairs;
80780518852SAndrew Boyer 	uint32_t i;
80880518852SAndrew Boyer 
809a677112dSAndrew Boyer 	IOCPT_PRINT_CALL();
810a677112dSAndrew Boyer 
81180518852SAndrew Boyer 	for (i = 0; i < dev->crypto_dev->data->nb_queue_pairs; i++) {
81280518852SAndrew Boyer 		iocpt_cryptoq_free(queue_pairs[i]);
81380518852SAndrew Boyer 		queue_pairs[i] = NULL;
81480518852SAndrew Boyer 	}
81580518852SAndrew Boyer 
8166bc7f2cfSAndrew Boyer 	if (dev->sess_bm != NULL) {
8176bc7f2cfSAndrew Boyer 		rte_bitmap_free(dev->sess_bm);
8186bc7f2cfSAndrew Boyer 		rte_free(dev->sess_bm);
8196bc7f2cfSAndrew Boyer 		dev->sess_bm = NULL;
8206bc7f2cfSAndrew Boyer 	}
8216bc7f2cfSAndrew Boyer 
8222c1662bbSAndrew Boyer 	if (dev->adminq != NULL) {
8232c1662bbSAndrew Boyer 		iocpt_adminq_free(dev->adminq);
8242c1662bbSAndrew Boyer 		dev->adminq = NULL;
8252c1662bbSAndrew Boyer 	}
8262c1662bbSAndrew Boyer 
82780518852SAndrew Boyer 	if (dev->cryptoqs != NULL) {
82880518852SAndrew Boyer 		rte_free(dev->cryptoqs);
82980518852SAndrew Boyer 		dev->cryptoqs = NULL;
83080518852SAndrew Boyer 	}
83180518852SAndrew Boyer 
832a677112dSAndrew Boyer 	if (dev->info != NULL) {
833a677112dSAndrew Boyer 		rte_memzone_free(dev->info_z);
834a677112dSAndrew Boyer 		dev->info_z = NULL;
835a677112dSAndrew Boyer 		dev->info = NULL;
836a677112dSAndrew Boyer 		dev->info_pa = 0;
837a677112dSAndrew Boyer 	}
838a677112dSAndrew Boyer }
839a677112dSAndrew Boyer 
8404610ac93SAndrew Boyer static int
iocpt_devargs(struct rte_devargs * devargs,struct iocpt_dev * dev)8414610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev)
8424610ac93SAndrew Boyer {
8434610ac93SAndrew Boyer 	RTE_SET_USED(devargs);
8444610ac93SAndrew Boyer 	RTE_SET_USED(dev);
8454610ac93SAndrew Boyer 
8464610ac93SAndrew Boyer 	return 0;
8474610ac93SAndrew Boyer }
8484610ac93SAndrew Boyer 
8494610ac93SAndrew Boyer int
iocpt_probe(void * bus_dev,struct rte_device * rte_dev,struct iocpt_dev_bars * bars,const struct iocpt_dev_intf * intf,uint8_t driver_id,uint8_t socket_id)8504610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
8514610ac93SAndrew Boyer 	struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf,
8524610ac93SAndrew Boyer 	uint8_t driver_id, uint8_t socket_id)
8534610ac93SAndrew Boyer {
8544610ac93SAndrew Boyer 	struct rte_cryptodev_pmd_init_params init_params = {
8554610ac93SAndrew Boyer 		"iocpt",
8564610ac93SAndrew Boyer 		sizeof(struct iocpt_dev),
8574610ac93SAndrew Boyer 		socket_id,
8584610ac93SAndrew Boyer 		RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
8594610ac93SAndrew Boyer 	};
8604610ac93SAndrew Boyer 	struct rte_cryptodev *cdev;
8614610ac93SAndrew Boyer 	struct iocpt_dev *dev;
86225c896eaSAndrew Boyer 	uint32_t i, sig;
8634610ac93SAndrew Boyer 	int err;
8644610ac93SAndrew Boyer 
86525c896eaSAndrew Boyer 	/* Check structs (trigger error at compilation time) */
86625c896eaSAndrew Boyer 	iocpt_struct_size_checks();
86725c896eaSAndrew Boyer 
8684610ac93SAndrew Boyer 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
8694610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Multi-process not supported");
8704610ac93SAndrew Boyer 		err = -EPERM;
8714610ac93SAndrew Boyer 		goto err;
8724610ac93SAndrew Boyer 	}
8734610ac93SAndrew Boyer 
8744610ac93SAndrew Boyer 	cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params);
8754610ac93SAndrew Boyer 	if (cdev == NULL) {
8764610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Out of memory");
8774610ac93SAndrew Boyer 		err = -ENOMEM;
8784610ac93SAndrew Boyer 		goto err;
8794610ac93SAndrew Boyer 	}
8804610ac93SAndrew Boyer 
8814610ac93SAndrew Boyer 	dev = cdev->data->dev_private;
8824610ac93SAndrew Boyer 	dev->crypto_dev = cdev;
8834610ac93SAndrew Boyer 	dev->bus_dev = bus_dev;
8844610ac93SAndrew Boyer 	dev->intf = intf;
8854610ac93SAndrew Boyer 	dev->driver_id = driver_id;
8864610ac93SAndrew Boyer 	dev->socket_id = socket_id;
8874610ac93SAndrew Boyer 
8884610ac93SAndrew Boyer 	for (i = 0; i < bars->num_bars; i++) {
8894610ac93SAndrew Boyer 		struct ionic_dev_bar *bar = &bars->bar[i];
8904610ac93SAndrew Boyer 
8914610ac93SAndrew Boyer 		IOCPT_PRINT(DEBUG,
8924610ac93SAndrew Boyer 			"bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }",
8934610ac93SAndrew Boyer 			i, bar->vaddr, bar->bus_addr, bar->len);
8944610ac93SAndrew Boyer 		if (bar->vaddr == NULL) {
8954610ac93SAndrew Boyer 			IOCPT_PRINT(ERR, "Null bar found, aborting");
8964610ac93SAndrew Boyer 			err = -EFAULT;
8974610ac93SAndrew Boyer 			goto err_destroy_crypto_dev;
8984610ac93SAndrew Boyer 		}
8994610ac93SAndrew Boyer 
9004610ac93SAndrew Boyer 		dev->bars.bar[i].vaddr = bar->vaddr;
9014610ac93SAndrew Boyer 		dev->bars.bar[i].bus_addr = bar->bus_addr;
9024610ac93SAndrew Boyer 		dev->bars.bar[i].len = bar->len;
9034610ac93SAndrew Boyer 	}
9044610ac93SAndrew Boyer 	dev->bars.num_bars = bars->num_bars;
9054610ac93SAndrew Boyer 
9064610ac93SAndrew Boyer 	err = iocpt_devargs(rte_dev->devargs, dev);
9074610ac93SAndrew Boyer 	if (err != 0) {
9084610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot parse device arguments");
9094610ac93SAndrew Boyer 		goto err_destroy_crypto_dev;
9104610ac93SAndrew Boyer 	}
9114610ac93SAndrew Boyer 
9124610ac93SAndrew Boyer 	err = iocpt_setup_bars(dev);
9134610ac93SAndrew Boyer 	if (err != 0) {
9144610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err);
9154610ac93SAndrew Boyer 		goto err_destroy_crypto_dev;
9164610ac93SAndrew Boyer 	}
9174610ac93SAndrew Boyer 
91825c896eaSAndrew Boyer 	sig = ioread32(&dev->dev_info->signature);
91925c896eaSAndrew Boyer 	if (sig != IOCPT_DEV_INFO_SIGNATURE) {
92025c896eaSAndrew Boyer 		IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig);
92125c896eaSAndrew Boyer 		err = -EFAULT;
92225c896eaSAndrew Boyer 		goto err_destroy_crypto_dev;
92325c896eaSAndrew Boyer 	}
92425c896eaSAndrew Boyer 
92525c896eaSAndrew Boyer 	for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++)
92625c896eaSAndrew Boyer 		dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]);
92725c896eaSAndrew Boyer 	dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0';
92825c896eaSAndrew Boyer 	IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version);
92925c896eaSAndrew Boyer 
930a677112dSAndrew Boyer 	err = iocpt_dev_identify(dev);
931a677112dSAndrew Boyer 	if (err != 0) {
932a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting",
933a677112dSAndrew Boyer 			err);
934a677112dSAndrew Boyer 		goto err_destroy_crypto_dev;
935a677112dSAndrew Boyer 	}
936a677112dSAndrew Boyer 
937a677112dSAndrew Boyer 	err = iocpt_alloc_objs(dev);
938a677112dSAndrew Boyer 	if (err != 0) {
939a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err);
940a677112dSAndrew Boyer 		goto err_destroy_crypto_dev;
941a677112dSAndrew Boyer 	}
942a677112dSAndrew Boyer 
9434610ac93SAndrew Boyer 	err = iocpt_init(dev);
9444610ac93SAndrew Boyer 	if (err != 0) {
9454610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err);
946a677112dSAndrew Boyer 		goto err_free_objs;
9474610ac93SAndrew Boyer 	}
9484610ac93SAndrew Boyer 
949dddfb0d9SAndrew Boyer 	err = iocpt_assign_ops(cdev);
950dddfb0d9SAndrew Boyer 	if (err != 0) {
951dddfb0d9SAndrew Boyer 		IOCPT_PRINT(ERR, "Failed to configure opts");
952dddfb0d9SAndrew Boyer 		goto err_deinit_dev;
953dddfb0d9SAndrew Boyer 	}
954dddfb0d9SAndrew Boyer 
9554610ac93SAndrew Boyer 	return 0;
9564610ac93SAndrew Boyer 
957dddfb0d9SAndrew Boyer err_deinit_dev:
958dddfb0d9SAndrew Boyer 	iocpt_deinit(dev);
959a677112dSAndrew Boyer err_free_objs:
960a677112dSAndrew Boyer 	iocpt_free_objs(dev);
9614610ac93SAndrew Boyer err_destroy_crypto_dev:
9624610ac93SAndrew Boyer 	rte_cryptodev_pmd_destroy(cdev);
9634610ac93SAndrew Boyer err:
9644610ac93SAndrew Boyer 	return err;
9654610ac93SAndrew Boyer }
9664610ac93SAndrew Boyer 
9674610ac93SAndrew Boyer int
iocpt_remove(struct rte_device * rte_dev)9684610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev)
9694610ac93SAndrew Boyer {
9704610ac93SAndrew Boyer 	struct rte_cryptodev *cdev;
9714610ac93SAndrew Boyer 	struct iocpt_dev *dev;
9724610ac93SAndrew Boyer 
9734610ac93SAndrew Boyer 	cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name);
9744610ac93SAndrew Boyer 	if (cdev == NULL) {
9754610ac93SAndrew Boyer 		IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name);
9764610ac93SAndrew Boyer 		return -ENODEV;
9774610ac93SAndrew Boyer 	}
9784610ac93SAndrew Boyer 
9794610ac93SAndrew Boyer 	dev = cdev->data->dev_private;
9804610ac93SAndrew Boyer 
9814610ac93SAndrew Boyer 	iocpt_deinit(dev);
9824610ac93SAndrew Boyer 
983a677112dSAndrew Boyer 	iocpt_dev_reset(dev);
984a677112dSAndrew Boyer 
985a677112dSAndrew Boyer 	iocpt_free_objs(dev);
986a677112dSAndrew Boyer 
9874610ac93SAndrew Boyer 	rte_cryptodev_pmd_destroy(cdev);
9884610ac93SAndrew Boyer 
9894610ac93SAndrew Boyer 	return 0;
9904610ac93SAndrew Boyer }
9914610ac93SAndrew Boyer 
9924610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE);
993