xref: /dpdk/drivers/crypto/ionic/ionic_crypto_main.c (revision 2c1662bb53cab994552d82814ce81ad183947f62)
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 
13*2c1662bbSAndrew Boyer static int
14*2c1662bbSAndrew Boyer iocpt_cq_init(struct iocpt_cq *cq, uint16_t num_descs)
15*2c1662bbSAndrew Boyer {
16*2c1662bbSAndrew Boyer 	if (!rte_is_power_of_2(num_descs) ||
17*2c1662bbSAndrew Boyer 	    num_descs < IOCPT_MIN_RING_DESC ||
18*2c1662bbSAndrew Boyer 	    num_descs > IOCPT_MAX_RING_DESC) {
19*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "%u descriptors (min: %u max: %u)",
20*2c1662bbSAndrew Boyer 			num_descs, IOCPT_MIN_RING_DESC, IOCPT_MAX_RING_DESC);
21*2c1662bbSAndrew Boyer 		return -EINVAL;
22*2c1662bbSAndrew Boyer 	}
23*2c1662bbSAndrew Boyer 
24*2c1662bbSAndrew Boyer 	cq->num_descs = num_descs;
25*2c1662bbSAndrew Boyer 	cq->size_mask = num_descs - 1;
26*2c1662bbSAndrew Boyer 	cq->tail_idx = 0;
27*2c1662bbSAndrew Boyer 	cq->done_color = 1;
28*2c1662bbSAndrew Boyer 
29*2c1662bbSAndrew Boyer 	return 0;
30*2c1662bbSAndrew Boyer }
31*2c1662bbSAndrew Boyer 
32*2c1662bbSAndrew Boyer static void
33*2c1662bbSAndrew Boyer iocpt_cq_map(struct iocpt_cq *cq, void *base, rte_iova_t base_pa)
34*2c1662bbSAndrew Boyer {
35*2c1662bbSAndrew Boyer 	cq->base = base;
36*2c1662bbSAndrew Boyer 	cq->base_pa = base_pa;
37*2c1662bbSAndrew Boyer }
38*2c1662bbSAndrew Boyer 
39*2c1662bbSAndrew Boyer uint32_t
40*2c1662bbSAndrew Boyer iocpt_cq_service(struct iocpt_cq *cq, uint32_t work_to_do,
41*2c1662bbSAndrew Boyer 		iocpt_cq_cb cb, void *cb_arg)
42*2c1662bbSAndrew Boyer {
43*2c1662bbSAndrew Boyer 	uint32_t work_done = 0;
44*2c1662bbSAndrew Boyer 
45*2c1662bbSAndrew Boyer 	if (work_to_do == 0)
46*2c1662bbSAndrew Boyer 		return 0;
47*2c1662bbSAndrew Boyer 
48*2c1662bbSAndrew Boyer 	while (cb(cq, cq->tail_idx, cb_arg)) {
49*2c1662bbSAndrew Boyer 		cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
50*2c1662bbSAndrew Boyer 		if (cq->tail_idx == 0)
51*2c1662bbSAndrew Boyer 			cq->done_color = !cq->done_color;
52*2c1662bbSAndrew Boyer 
53*2c1662bbSAndrew Boyer 		if (++work_done == work_to_do)
54*2c1662bbSAndrew Boyer 			break;
55*2c1662bbSAndrew Boyer 	}
56*2c1662bbSAndrew Boyer 
57*2c1662bbSAndrew Boyer 	return work_done;
58*2c1662bbSAndrew Boyer }
59*2c1662bbSAndrew Boyer 
60*2c1662bbSAndrew Boyer static int
61*2c1662bbSAndrew Boyer iocpt_q_init(struct iocpt_queue *q, uint8_t type, uint32_t index,
62*2c1662bbSAndrew Boyer 	uint16_t num_descs, uint16_t num_segs, uint32_t socket_id)
63*2c1662bbSAndrew Boyer {
64*2c1662bbSAndrew Boyer 	uint32_t ring_size;
65*2c1662bbSAndrew Boyer 
66*2c1662bbSAndrew Boyer 	if (!rte_is_power_of_2(num_descs))
67*2c1662bbSAndrew Boyer 		return -EINVAL;
68*2c1662bbSAndrew Boyer 
69*2c1662bbSAndrew Boyer 	ring_size = rte_log2_u32(num_descs);
70*2c1662bbSAndrew Boyer 	if (ring_size < 2 || ring_size > 16)
71*2c1662bbSAndrew Boyer 		return -EINVAL;
72*2c1662bbSAndrew Boyer 
73*2c1662bbSAndrew Boyer 	q->type = type;
74*2c1662bbSAndrew Boyer 	q->index = index;
75*2c1662bbSAndrew Boyer 	q->num_descs = num_descs;
76*2c1662bbSAndrew Boyer 	q->num_segs = num_segs;
77*2c1662bbSAndrew Boyer 	q->size_mask = num_descs - 1;
78*2c1662bbSAndrew Boyer 	q->head_idx = 0;
79*2c1662bbSAndrew Boyer 	q->tail_idx = 0;
80*2c1662bbSAndrew Boyer 
81*2c1662bbSAndrew Boyer 	q->info = rte_calloc_socket("iocpt",
82*2c1662bbSAndrew Boyer 				num_descs * num_segs, sizeof(void *),
83*2c1662bbSAndrew Boyer 				rte_mem_page_size(), socket_id);
84*2c1662bbSAndrew Boyer 	if (q->info == NULL) {
85*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate queue info");
86*2c1662bbSAndrew Boyer 		return -ENOMEM;
87*2c1662bbSAndrew Boyer 	}
88*2c1662bbSAndrew Boyer 
89*2c1662bbSAndrew Boyer 	return 0;
90*2c1662bbSAndrew Boyer }
91*2c1662bbSAndrew Boyer 
92*2c1662bbSAndrew Boyer static void
93*2c1662bbSAndrew Boyer iocpt_q_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
94*2c1662bbSAndrew Boyer {
95*2c1662bbSAndrew Boyer 	q->base = base;
96*2c1662bbSAndrew Boyer 	q->base_pa = base_pa;
97*2c1662bbSAndrew Boyer }
98*2c1662bbSAndrew Boyer 
99*2c1662bbSAndrew Boyer static void
100*2c1662bbSAndrew Boyer iocpt_q_sg_map(struct iocpt_queue *q, void *base, rte_iova_t base_pa)
101*2c1662bbSAndrew Boyer {
102*2c1662bbSAndrew Boyer 	q->sg_base = base;
103*2c1662bbSAndrew Boyer 	q->sg_base_pa = base_pa;
104*2c1662bbSAndrew Boyer }
105*2c1662bbSAndrew Boyer 
106*2c1662bbSAndrew Boyer static void
107*2c1662bbSAndrew Boyer iocpt_q_free(struct iocpt_queue *q)
108*2c1662bbSAndrew Boyer {
109*2c1662bbSAndrew Boyer 	if (q->info != NULL) {
110*2c1662bbSAndrew Boyer 		rte_free(q->info);
111*2c1662bbSAndrew Boyer 		q->info = NULL;
112*2c1662bbSAndrew Boyer 	}
113*2c1662bbSAndrew Boyer }
114*2c1662bbSAndrew Boyer 
115a677112dSAndrew Boyer static const struct rte_memzone *
116a677112dSAndrew Boyer iocpt_dma_zone_reserve(const char *type_name, uint16_t qid, size_t size,
117a677112dSAndrew Boyer 			unsigned int align, int socket_id)
118a677112dSAndrew Boyer {
119a677112dSAndrew Boyer 	char zone_name[RTE_MEMZONE_NAMESIZE];
120a677112dSAndrew Boyer 	const struct rte_memzone *mz;
121a677112dSAndrew Boyer 	int err;
122a677112dSAndrew Boyer 
123a677112dSAndrew Boyer 	err = snprintf(zone_name, sizeof(zone_name),
124a677112dSAndrew Boyer 			"iocpt_%s_%u", type_name, qid);
125a677112dSAndrew Boyer 	if (err >= RTE_MEMZONE_NAMESIZE) {
126a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Name %s too long", type_name);
127a677112dSAndrew Boyer 		return NULL;
128a677112dSAndrew Boyer 	}
129a677112dSAndrew Boyer 
130a677112dSAndrew Boyer 	mz = rte_memzone_lookup(zone_name);
131a677112dSAndrew Boyer 	if (mz != NULL)
132a677112dSAndrew Boyer 		return mz;
133a677112dSAndrew Boyer 
134a677112dSAndrew Boyer 	return rte_memzone_reserve_aligned(zone_name, size, socket_id,
135a677112dSAndrew Boyer 			RTE_MEMZONE_IOVA_CONTIG, align);
136a677112dSAndrew Boyer }
137a677112dSAndrew Boyer 
138a677112dSAndrew Boyer static int
139*2c1662bbSAndrew Boyer iocpt_commonq_alloc(struct iocpt_dev *dev,
140*2c1662bbSAndrew Boyer 		uint8_t type,
141*2c1662bbSAndrew Boyer 		size_t struct_size,
142*2c1662bbSAndrew Boyer 		uint32_t socket_id,
143*2c1662bbSAndrew Boyer 		uint32_t index,
144*2c1662bbSAndrew Boyer 		const char *type_name,
145*2c1662bbSAndrew Boyer 		uint16_t flags,
146*2c1662bbSAndrew Boyer 		uint16_t num_descs,
147*2c1662bbSAndrew Boyer 		uint16_t num_segs,
148*2c1662bbSAndrew Boyer 		uint16_t desc_size,
149*2c1662bbSAndrew Boyer 		uint16_t cq_desc_size,
150*2c1662bbSAndrew Boyer 		uint16_t sg_desc_size,
151*2c1662bbSAndrew Boyer 		struct iocpt_common_q **comq)
152*2c1662bbSAndrew Boyer {
153*2c1662bbSAndrew Boyer 	struct iocpt_common_q *new;
154*2c1662bbSAndrew Boyer 	uint32_t q_size, cq_size, sg_size, total_size;
155*2c1662bbSAndrew Boyer 	void *q_base, *cq_base, *sg_base;
156*2c1662bbSAndrew Boyer 	rte_iova_t q_base_pa = 0;
157*2c1662bbSAndrew Boyer 	rte_iova_t cq_base_pa = 0;
158*2c1662bbSAndrew Boyer 	rte_iova_t sg_base_pa = 0;
159*2c1662bbSAndrew Boyer 	size_t page_size = rte_mem_page_size();
160*2c1662bbSAndrew Boyer 	int err;
161*2c1662bbSAndrew Boyer 
162*2c1662bbSAndrew Boyer 	*comq = NULL;
163*2c1662bbSAndrew Boyer 
164*2c1662bbSAndrew Boyer 	q_size	= num_descs * desc_size;
165*2c1662bbSAndrew Boyer 	cq_size = num_descs * cq_desc_size;
166*2c1662bbSAndrew Boyer 	sg_size = num_descs * sg_desc_size;
167*2c1662bbSAndrew Boyer 
168*2c1662bbSAndrew Boyer 	/*
169*2c1662bbSAndrew Boyer 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
170*2c1662bbSAndrew Boyer 	 * aligning as q_base could be not aligned to the page.
171*2c1662bbSAndrew Boyer 	 * Adding page_size.
172*2c1662bbSAndrew Boyer 	 */
173*2c1662bbSAndrew Boyer 	total_size = RTE_ALIGN(q_size, page_size) +
174*2c1662bbSAndrew Boyer 		RTE_ALIGN(cq_size, page_size) + page_size;
175*2c1662bbSAndrew Boyer 	if (flags & IOCPT_Q_F_SG)
176*2c1662bbSAndrew Boyer 		total_size += RTE_ALIGN(sg_size, page_size) + page_size;
177*2c1662bbSAndrew Boyer 
178*2c1662bbSAndrew Boyer 	new = rte_zmalloc_socket("iocpt", struct_size,
179*2c1662bbSAndrew Boyer 			RTE_CACHE_LINE_SIZE, socket_id);
180*2c1662bbSAndrew Boyer 	if (new == NULL) {
181*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate queue structure");
182*2c1662bbSAndrew Boyer 		return -ENOMEM;
183*2c1662bbSAndrew Boyer 	}
184*2c1662bbSAndrew Boyer 
185*2c1662bbSAndrew Boyer 	new->dev = dev;
186*2c1662bbSAndrew Boyer 
187*2c1662bbSAndrew Boyer 	err = iocpt_q_init(&new->q, type, index, num_descs, num_segs,
188*2c1662bbSAndrew Boyer 			socket_id);
189*2c1662bbSAndrew Boyer 	if (err != 0) {
190*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Queue initialization failed");
191*2c1662bbSAndrew Boyer 		goto err_free_q;
192*2c1662bbSAndrew Boyer 	}
193*2c1662bbSAndrew Boyer 
194*2c1662bbSAndrew Boyer 	err = iocpt_cq_init(&new->cq, num_descs);
195*2c1662bbSAndrew Boyer 	if (err != 0) {
196*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Completion queue initialization failed");
197*2c1662bbSAndrew Boyer 		goto err_deinit_q;
198*2c1662bbSAndrew Boyer 	}
199*2c1662bbSAndrew Boyer 
200*2c1662bbSAndrew Boyer 	new->base_z = iocpt_dma_zone_reserve(type_name, index, total_size,
201*2c1662bbSAndrew Boyer 					IONIC_ALIGN, socket_id);
202*2c1662bbSAndrew Boyer 	if (new->base_z == NULL) {
203*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot reserve queue DMA memory");
204*2c1662bbSAndrew Boyer 		err = -ENOMEM;
205*2c1662bbSAndrew Boyer 		goto err_deinit_cq;
206*2c1662bbSAndrew Boyer 	}
207*2c1662bbSAndrew Boyer 
208*2c1662bbSAndrew Boyer 	new->base = new->base_z->addr;
209*2c1662bbSAndrew Boyer 	new->base_pa = new->base_z->iova;
210*2c1662bbSAndrew Boyer 
211*2c1662bbSAndrew Boyer 	q_base = new->base;
212*2c1662bbSAndrew Boyer 	q_base_pa = new->base_pa;
213*2c1662bbSAndrew Boyer 	iocpt_q_map(&new->q, q_base, q_base_pa);
214*2c1662bbSAndrew Boyer 
215*2c1662bbSAndrew Boyer 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
216*2c1662bbSAndrew Boyer 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
217*2c1662bbSAndrew Boyer 	iocpt_cq_map(&new->cq, cq_base, cq_base_pa);
218*2c1662bbSAndrew Boyer 
219*2c1662bbSAndrew Boyer 	if (flags & IOCPT_Q_F_SG) {
220*2c1662bbSAndrew Boyer 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
221*2c1662bbSAndrew Boyer 			page_size);
222*2c1662bbSAndrew Boyer 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
223*2c1662bbSAndrew Boyer 		iocpt_q_sg_map(&new->q, sg_base, sg_base_pa);
224*2c1662bbSAndrew Boyer 	}
225*2c1662bbSAndrew Boyer 
226*2c1662bbSAndrew Boyer 	IOCPT_PRINT(DEBUG, "q_base_pa %#jx cq_base_pa %#jx sg_base_pa %#jx",
227*2c1662bbSAndrew Boyer 		q_base_pa, cq_base_pa, sg_base_pa);
228*2c1662bbSAndrew Boyer 
229*2c1662bbSAndrew Boyer 	*comq = new;
230*2c1662bbSAndrew Boyer 
231*2c1662bbSAndrew Boyer 	return 0;
232*2c1662bbSAndrew Boyer 
233*2c1662bbSAndrew Boyer err_deinit_cq:
234*2c1662bbSAndrew Boyer err_deinit_q:
235*2c1662bbSAndrew Boyer 	iocpt_q_free(&new->q);
236*2c1662bbSAndrew Boyer err_free_q:
237*2c1662bbSAndrew Boyer 	rte_free(new);
238*2c1662bbSAndrew Boyer 	return err;
239*2c1662bbSAndrew Boyer }
240*2c1662bbSAndrew Boyer 
241*2c1662bbSAndrew Boyer struct ionic_doorbell *
242*2c1662bbSAndrew Boyer iocpt_db_map(struct iocpt_dev *dev, struct iocpt_queue *q)
243*2c1662bbSAndrew Boyer {
244*2c1662bbSAndrew Boyer 	return dev->db_pages + q->hw_type;
245*2c1662bbSAndrew Boyer }
246*2c1662bbSAndrew Boyer 
247*2c1662bbSAndrew Boyer static int
248*2c1662bbSAndrew Boyer iocpt_adminq_alloc(struct iocpt_dev *dev)
249*2c1662bbSAndrew Boyer {
250*2c1662bbSAndrew Boyer 	struct iocpt_admin_q *aq;
251*2c1662bbSAndrew Boyer 	uint16_t num_descs = IOCPT_ADMINQ_LENGTH;
252*2c1662bbSAndrew Boyer 	uint16_t flags = 0;
253*2c1662bbSAndrew Boyer 	int err;
254*2c1662bbSAndrew Boyer 
255*2c1662bbSAndrew Boyer 	err = iocpt_commonq_alloc(dev,
256*2c1662bbSAndrew Boyer 		IOCPT_QTYPE_ADMINQ,
257*2c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_q),
258*2c1662bbSAndrew Boyer 		rte_socket_id(),
259*2c1662bbSAndrew Boyer 		0,
260*2c1662bbSAndrew Boyer 		"admin",
261*2c1662bbSAndrew Boyer 		flags,
262*2c1662bbSAndrew Boyer 		num_descs,
263*2c1662bbSAndrew Boyer 		1,
264*2c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_cmd),
265*2c1662bbSAndrew Boyer 		sizeof(struct iocpt_admin_comp),
266*2c1662bbSAndrew Boyer 		0,
267*2c1662bbSAndrew Boyer 		(struct iocpt_common_q **)&aq);
268*2c1662bbSAndrew Boyer 	if (err != 0)
269*2c1662bbSAndrew Boyer 		return err;
270*2c1662bbSAndrew Boyer 
271*2c1662bbSAndrew Boyer 	aq->flags = flags;
272*2c1662bbSAndrew Boyer 
273*2c1662bbSAndrew Boyer 	dev->adminq = aq;
274*2c1662bbSAndrew Boyer 
275*2c1662bbSAndrew Boyer 	return 0;
276*2c1662bbSAndrew Boyer }
277*2c1662bbSAndrew Boyer 
278*2c1662bbSAndrew Boyer static int
279*2c1662bbSAndrew Boyer iocpt_adminq_init(struct iocpt_dev *dev)
280*2c1662bbSAndrew Boyer {
281*2c1662bbSAndrew Boyer 	return iocpt_dev_adminq_init(dev);
282*2c1662bbSAndrew Boyer }
283*2c1662bbSAndrew Boyer 
284*2c1662bbSAndrew Boyer static void
285*2c1662bbSAndrew Boyer iocpt_adminq_deinit(struct iocpt_dev *dev)
286*2c1662bbSAndrew Boyer {
287*2c1662bbSAndrew Boyer 	dev->adminq->flags &= ~IOCPT_Q_F_INITED;
288*2c1662bbSAndrew Boyer }
289*2c1662bbSAndrew Boyer 
290*2c1662bbSAndrew Boyer static void
291*2c1662bbSAndrew Boyer iocpt_adminq_free(struct iocpt_admin_q *aq)
292*2c1662bbSAndrew Boyer {
293*2c1662bbSAndrew Boyer 	if (aq->base_z != NULL) {
294*2c1662bbSAndrew Boyer 		rte_memzone_free(aq->base_z);
295*2c1662bbSAndrew Boyer 		aq->base_z = NULL;
296*2c1662bbSAndrew Boyer 		aq->base = NULL;
297*2c1662bbSAndrew Boyer 		aq->base_pa = 0;
298*2c1662bbSAndrew Boyer 	}
299*2c1662bbSAndrew Boyer 
300*2c1662bbSAndrew Boyer 	iocpt_q_free(&aq->q);
301*2c1662bbSAndrew Boyer 
302*2c1662bbSAndrew Boyer 	rte_free(aq);
303*2c1662bbSAndrew Boyer }
304*2c1662bbSAndrew Boyer 
305*2c1662bbSAndrew Boyer static int
306a677112dSAndrew Boyer iocpt_alloc_objs(struct iocpt_dev *dev)
307a677112dSAndrew Boyer {
308a677112dSAndrew Boyer 	int err;
309a677112dSAndrew Boyer 
310a677112dSAndrew Boyer 	IOCPT_PRINT(DEBUG, "Crypto: %s", dev->name);
311a677112dSAndrew Boyer 
312*2c1662bbSAndrew Boyer 	rte_spinlock_init(&dev->adminq_lock);
313*2c1662bbSAndrew Boyer 	rte_spinlock_init(&dev->adminq_service_lock);
314*2c1662bbSAndrew Boyer 
315*2c1662bbSAndrew Boyer 	err = iocpt_adminq_alloc(dev);
316*2c1662bbSAndrew Boyer 	if (err != 0) {
317*2c1662bbSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate admin queue");
318*2c1662bbSAndrew Boyer 		err = -ENOMEM;
319*2c1662bbSAndrew Boyer 		goto err_out;
320*2c1662bbSAndrew Boyer 	}
321*2c1662bbSAndrew Boyer 
322a677112dSAndrew Boyer 	dev->info_sz = RTE_ALIGN(sizeof(*dev->info), rte_mem_page_size());
323a677112dSAndrew Boyer 	dev->info_z = iocpt_dma_zone_reserve("info", 0, dev->info_sz,
324a677112dSAndrew Boyer 					IONIC_ALIGN, dev->socket_id);
325a677112dSAndrew Boyer 	if (dev->info_z == NULL) {
326a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot allocate dev info memory");
327a677112dSAndrew Boyer 		err = -ENOMEM;
328*2c1662bbSAndrew Boyer 		goto err_free_adminq;
329a677112dSAndrew Boyer 	}
330a677112dSAndrew Boyer 
331a677112dSAndrew Boyer 	dev->info = dev->info_z->addr;
332a677112dSAndrew Boyer 	dev->info_pa = dev->info_z->iova;
333a677112dSAndrew Boyer 
334a677112dSAndrew Boyer 	return 0;
335a677112dSAndrew Boyer 
336*2c1662bbSAndrew Boyer err_free_adminq:
337*2c1662bbSAndrew Boyer 	iocpt_adminq_free(dev->adminq);
338*2c1662bbSAndrew Boyer 	dev->adminq = NULL;
339a677112dSAndrew Boyer err_out:
340a677112dSAndrew Boyer 	return err;
341a677112dSAndrew Boyer }
342a677112dSAndrew Boyer 
3434610ac93SAndrew Boyer static int
3444610ac93SAndrew Boyer iocpt_init(struct iocpt_dev *dev)
3454610ac93SAndrew Boyer {
346a677112dSAndrew Boyer 	int err;
347a677112dSAndrew Boyer 
348a677112dSAndrew Boyer 	/* Uses dev_cmds */
349a677112dSAndrew Boyer 	err = iocpt_dev_init(dev, dev->info_pa);
350a677112dSAndrew Boyer 	if (err != 0)
351a677112dSAndrew Boyer 		return err;
352a677112dSAndrew Boyer 
353*2c1662bbSAndrew Boyer 	err = iocpt_adminq_init(dev);
354*2c1662bbSAndrew Boyer 	if (err != 0)
355*2c1662bbSAndrew Boyer 		return err;
356*2c1662bbSAndrew Boyer 
3574610ac93SAndrew Boyer 	dev->state |= IOCPT_DEV_F_INITED;
3584610ac93SAndrew Boyer 
3594610ac93SAndrew Boyer 	return 0;
3604610ac93SAndrew Boyer }
3614610ac93SAndrew Boyer 
3624610ac93SAndrew Boyer void
3634610ac93SAndrew Boyer iocpt_configure(struct iocpt_dev *dev)
3644610ac93SAndrew Boyer {
3654610ac93SAndrew Boyer 	RTE_SET_USED(dev);
3664610ac93SAndrew Boyer }
3674610ac93SAndrew Boyer 
3684610ac93SAndrew Boyer void
3694610ac93SAndrew Boyer iocpt_deinit(struct iocpt_dev *dev)
3704610ac93SAndrew Boyer {
3714610ac93SAndrew Boyer 	IOCPT_PRINT_CALL();
3724610ac93SAndrew Boyer 
3734610ac93SAndrew Boyer 	if (!(dev->state & IOCPT_DEV_F_INITED))
3744610ac93SAndrew Boyer 		return;
3754610ac93SAndrew Boyer 
376*2c1662bbSAndrew Boyer 	iocpt_adminq_deinit(dev);
377*2c1662bbSAndrew Boyer 
3784610ac93SAndrew Boyer 	dev->state &= ~IOCPT_DEV_F_INITED;
3794610ac93SAndrew Boyer }
3804610ac93SAndrew Boyer 
381a677112dSAndrew Boyer static void
382a677112dSAndrew Boyer iocpt_free_objs(struct iocpt_dev *dev)
383a677112dSAndrew Boyer {
384a677112dSAndrew Boyer 	IOCPT_PRINT_CALL();
385a677112dSAndrew Boyer 
386*2c1662bbSAndrew Boyer 	if (dev->adminq != NULL) {
387*2c1662bbSAndrew Boyer 		iocpt_adminq_free(dev->adminq);
388*2c1662bbSAndrew Boyer 		dev->adminq = NULL;
389*2c1662bbSAndrew Boyer 	}
390*2c1662bbSAndrew Boyer 
391a677112dSAndrew Boyer 	if (dev->info != NULL) {
392a677112dSAndrew Boyer 		rte_memzone_free(dev->info_z);
393a677112dSAndrew Boyer 		dev->info_z = NULL;
394a677112dSAndrew Boyer 		dev->info = NULL;
395a677112dSAndrew Boyer 		dev->info_pa = 0;
396a677112dSAndrew Boyer 	}
397a677112dSAndrew Boyer }
398a677112dSAndrew Boyer 
3994610ac93SAndrew Boyer static int
4004610ac93SAndrew Boyer iocpt_devargs(struct rte_devargs *devargs, struct iocpt_dev *dev)
4014610ac93SAndrew Boyer {
4024610ac93SAndrew Boyer 	RTE_SET_USED(devargs);
4034610ac93SAndrew Boyer 	RTE_SET_USED(dev);
4044610ac93SAndrew Boyer 
4054610ac93SAndrew Boyer 	return 0;
4064610ac93SAndrew Boyer }
4074610ac93SAndrew Boyer 
4084610ac93SAndrew Boyer int
4094610ac93SAndrew Boyer iocpt_probe(void *bus_dev, struct rte_device *rte_dev,
4104610ac93SAndrew Boyer 	struct iocpt_dev_bars *bars, const struct iocpt_dev_intf *intf,
4114610ac93SAndrew Boyer 	uint8_t driver_id, uint8_t socket_id)
4124610ac93SAndrew Boyer {
4134610ac93SAndrew Boyer 	struct rte_cryptodev_pmd_init_params init_params = {
4144610ac93SAndrew Boyer 		"iocpt",
4154610ac93SAndrew Boyer 		sizeof(struct iocpt_dev),
4164610ac93SAndrew Boyer 		socket_id,
4174610ac93SAndrew Boyer 		RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
4184610ac93SAndrew Boyer 	};
4194610ac93SAndrew Boyer 	struct rte_cryptodev *cdev;
4204610ac93SAndrew Boyer 	struct iocpt_dev *dev;
42125c896eaSAndrew Boyer 	uint32_t i, sig;
4224610ac93SAndrew Boyer 	int err;
4234610ac93SAndrew Boyer 
42425c896eaSAndrew Boyer 	/* Check structs (trigger error at compilation time) */
42525c896eaSAndrew Boyer 	iocpt_struct_size_checks();
42625c896eaSAndrew Boyer 
4274610ac93SAndrew Boyer 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
4284610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Multi-process not supported");
4294610ac93SAndrew Boyer 		err = -EPERM;
4304610ac93SAndrew Boyer 		goto err;
4314610ac93SAndrew Boyer 	}
4324610ac93SAndrew Boyer 
4334610ac93SAndrew Boyer 	cdev = rte_cryptodev_pmd_create(rte_dev->name, rte_dev, &init_params);
4344610ac93SAndrew Boyer 	if (cdev == NULL) {
4354610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Out of memory");
4364610ac93SAndrew Boyer 		err = -ENOMEM;
4374610ac93SAndrew Boyer 		goto err;
4384610ac93SAndrew Boyer 	}
4394610ac93SAndrew Boyer 
4404610ac93SAndrew Boyer 	dev = cdev->data->dev_private;
4414610ac93SAndrew Boyer 	dev->crypto_dev = cdev;
4424610ac93SAndrew Boyer 	dev->bus_dev = bus_dev;
4434610ac93SAndrew Boyer 	dev->intf = intf;
4444610ac93SAndrew Boyer 	dev->driver_id = driver_id;
4454610ac93SAndrew Boyer 	dev->socket_id = socket_id;
4464610ac93SAndrew Boyer 
4474610ac93SAndrew Boyer 	for (i = 0; i < bars->num_bars; i++) {
4484610ac93SAndrew Boyer 		struct ionic_dev_bar *bar = &bars->bar[i];
4494610ac93SAndrew Boyer 
4504610ac93SAndrew Boyer 		IOCPT_PRINT(DEBUG,
4514610ac93SAndrew Boyer 			"bar[%u] = { .va = %p, .pa = %#jx, .len = %lu }",
4524610ac93SAndrew Boyer 			i, bar->vaddr, bar->bus_addr, bar->len);
4534610ac93SAndrew Boyer 		if (bar->vaddr == NULL) {
4544610ac93SAndrew Boyer 			IOCPT_PRINT(ERR, "Null bar found, aborting");
4554610ac93SAndrew Boyer 			err = -EFAULT;
4564610ac93SAndrew Boyer 			goto err_destroy_crypto_dev;
4574610ac93SAndrew Boyer 		}
4584610ac93SAndrew Boyer 
4594610ac93SAndrew Boyer 		dev->bars.bar[i].vaddr = bar->vaddr;
4604610ac93SAndrew Boyer 		dev->bars.bar[i].bus_addr = bar->bus_addr;
4614610ac93SAndrew Boyer 		dev->bars.bar[i].len = bar->len;
4624610ac93SAndrew Boyer 	}
4634610ac93SAndrew Boyer 	dev->bars.num_bars = bars->num_bars;
4644610ac93SAndrew Boyer 
4654610ac93SAndrew Boyer 	err = iocpt_devargs(rte_dev->devargs, dev);
4664610ac93SAndrew Boyer 	if (err != 0) {
4674610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot parse device arguments");
4684610ac93SAndrew Boyer 		goto err_destroy_crypto_dev;
4694610ac93SAndrew Boyer 	}
4704610ac93SAndrew Boyer 
4714610ac93SAndrew Boyer 	err = iocpt_setup_bars(dev);
4724610ac93SAndrew Boyer 	if (err != 0) {
4734610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot setup BARs: %d, aborting", err);
4744610ac93SAndrew Boyer 		goto err_destroy_crypto_dev;
4754610ac93SAndrew Boyer 	}
4764610ac93SAndrew Boyer 
47725c896eaSAndrew Boyer 	sig = ioread32(&dev->dev_info->signature);
47825c896eaSAndrew Boyer 	if (sig != IOCPT_DEV_INFO_SIGNATURE) {
47925c896eaSAndrew Boyer 		IOCPT_PRINT(ERR, "Incompatible firmware signature %#x", sig);
48025c896eaSAndrew Boyer 		err = -EFAULT;
48125c896eaSAndrew Boyer 		goto err_destroy_crypto_dev;
48225c896eaSAndrew Boyer 	}
48325c896eaSAndrew Boyer 
48425c896eaSAndrew Boyer 	for (i = 0; i < IOCPT_FWVERS_BUFLEN; i++)
48525c896eaSAndrew Boyer 		dev->fw_version[i] = ioread8(&dev->dev_info->fw_version[i]);
48625c896eaSAndrew Boyer 	dev->fw_version[IOCPT_FWVERS_BUFLEN - 1] = '\0';
48725c896eaSAndrew Boyer 	IOCPT_PRINT(DEBUG, "%s firmware: %s", dev->name, dev->fw_version);
48825c896eaSAndrew Boyer 
489a677112dSAndrew Boyer 	err = iocpt_dev_identify(dev);
490a677112dSAndrew Boyer 	if (err != 0) {
491a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot identify device: %d, aborting",
492a677112dSAndrew Boyer 			err);
493a677112dSAndrew Boyer 		goto err_destroy_crypto_dev;
494a677112dSAndrew Boyer 	}
495a677112dSAndrew Boyer 
496a677112dSAndrew Boyer 	err = iocpt_alloc_objs(dev);
497a677112dSAndrew Boyer 	if (err != 0) {
498a677112dSAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot alloc device objects: %d", err);
499a677112dSAndrew Boyer 		goto err_destroy_crypto_dev;
500a677112dSAndrew Boyer 	}
501a677112dSAndrew Boyer 
5024610ac93SAndrew Boyer 	err = iocpt_init(dev);
5034610ac93SAndrew Boyer 	if (err != 0) {
5044610ac93SAndrew Boyer 		IOCPT_PRINT(ERR, "Cannot init device: %d, aborting", err);
505a677112dSAndrew Boyer 		goto err_free_objs;
5064610ac93SAndrew Boyer 	}
5074610ac93SAndrew Boyer 
5084610ac93SAndrew Boyer 	return 0;
5094610ac93SAndrew Boyer 
510a677112dSAndrew Boyer err_free_objs:
511a677112dSAndrew Boyer 	iocpt_free_objs(dev);
5124610ac93SAndrew Boyer err_destroy_crypto_dev:
5134610ac93SAndrew Boyer 	rte_cryptodev_pmd_destroy(cdev);
5144610ac93SAndrew Boyer err:
5154610ac93SAndrew Boyer 	return err;
5164610ac93SAndrew Boyer }
5174610ac93SAndrew Boyer 
5184610ac93SAndrew Boyer int
5194610ac93SAndrew Boyer iocpt_remove(struct rte_device *rte_dev)
5204610ac93SAndrew Boyer {
5214610ac93SAndrew Boyer 	struct rte_cryptodev *cdev;
5224610ac93SAndrew Boyer 	struct iocpt_dev *dev;
5234610ac93SAndrew Boyer 
5244610ac93SAndrew Boyer 	cdev = rte_cryptodev_pmd_get_named_dev(rte_dev->name);
5254610ac93SAndrew Boyer 	if (cdev == NULL) {
5264610ac93SAndrew Boyer 		IOCPT_PRINT(DEBUG, "Cannot find device %s", rte_dev->name);
5274610ac93SAndrew Boyer 		return -ENODEV;
5284610ac93SAndrew Boyer 	}
5294610ac93SAndrew Boyer 
5304610ac93SAndrew Boyer 	dev = cdev->data->dev_private;
5314610ac93SAndrew Boyer 
5324610ac93SAndrew Boyer 	iocpt_deinit(dev);
5334610ac93SAndrew Boyer 
534a677112dSAndrew Boyer 	iocpt_dev_reset(dev);
535a677112dSAndrew Boyer 
536a677112dSAndrew Boyer 	iocpt_free_objs(dev);
537a677112dSAndrew Boyer 
5384610ac93SAndrew Boyer 	rte_cryptodev_pmd_destroy(cdev);
5394610ac93SAndrew Boyer 
5404610ac93SAndrew Boyer 	return 0;
5414610ac93SAndrew Boyer }
5424610ac93SAndrew Boyer 
5434610ac93SAndrew Boyer RTE_LOG_REGISTER_DEFAULT(iocpt_logtype, NOTICE);
544