xref: /dpdk/drivers/net/bnxt/bnxt_reps.c (revision ef9e424aa72477cc5fd35efeb31c923a67383241)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2023 Broadcom
3  * All rights reserved.
4  */
5 
6 #include "bnxt.h"
7 #include "bnxt_ring.h"
8 #include "bnxt_reps.h"
9 #include "bnxt_rxq.h"
10 #include "bnxt_rxr.h"
11 #include "bnxt_txq.h"
12 #include "bnxt_txr.h"
13 #include "bnxt_hwrm.h"
14 #include "hsi_struct_def_dpdk.h"
15 #include "bnxt_tf_common.h"
16 #include "bnxt_ulp_utils.h"
17 #include "ulp_port_db.h"
18 #include "ulp_flow_db.h"
19 
20 static const struct eth_dev_ops bnxt_rep_dev_ops = {
21 	.dev_infos_get = bnxt_rep_dev_info_get_op,
22 	.dev_configure = bnxt_rep_dev_configure_op,
23 	.dev_start = bnxt_rep_dev_start_op,
24 	.rx_queue_setup = bnxt_rep_rx_queue_setup_op,
25 	.rx_queue_release = bnxt_rep_rx_queue_release_op,
26 	.tx_queue_setup = bnxt_rep_tx_queue_setup_op,
27 	.tx_queue_release = bnxt_rep_tx_queue_release_op,
28 	.link_update = bnxt_rep_link_update_op,
29 	.dev_close = bnxt_rep_dev_close_op,
30 	.dev_stop = bnxt_rep_dev_stop_op,
31 	.stats_get = bnxt_rep_stats_get_op,
32 	.stats_reset = bnxt_rep_stats_reset_op,
33 	.flow_ops_get = bnxt_flow_ops_get_op
34 };
35 
36 static bool bnxt_rep_check_parent(struct bnxt_representor *rep)
37 {
38 	if (!rep->parent_dev->data || !rep->parent_dev->data->dev_private)
39 		return false;
40 
41 	return true;
42 }
43 
44 uint16_t
45 bnxt_vfr_recv(uint16_t port_id, uint16_t queue_id, struct rte_mbuf *mbuf)
46 {
47 	struct bnxt_representor *vfr_bp = NULL;
48 	struct bnxt_rx_ring_info *rep_rxr;
49 	struct rte_eth_dev *vfr_eth_dev;
50 	struct rte_mbuf **prod_rx_buf;
51 	struct bnxt_rx_queue *rep_rxq;
52 	uint16_t mask;
53 	uint8_t que;
54 
55 	vfr_eth_dev = &rte_eth_devices[port_id];
56 	vfr_bp = vfr_eth_dev ? vfr_eth_dev->data->dev_private : NULL;
57 
58 	if (unlikely(vfr_bp == NULL))
59 		return 1;
60 
61 	/* If rxq_id happens to be > nr_rings, use ring 0 */
62 	que = queue_id < vfr_bp->rx_nr_rings ? queue_id : 0;
63 	rep_rxq = vfr_bp->rx_queues[que];
64 	/* Ideally should not happen now, paranoid check */
65 	if (!rep_rxq)
66 		return 1;
67 	rep_rxr = rep_rxq->rx_ring;
68 	mask = rep_rxr->rx_ring_struct->ring_mask;
69 
70 	/* Put this mbuf on the RxQ of the Representor */
71 	prod_rx_buf = &rep_rxr->rx_buf_ring[rep_rxr->rx_raw_prod & mask];
72 	if (*prod_rx_buf == NULL) {
73 		*prod_rx_buf = mbuf;
74 		vfr_bp->rx_bytes[que] += mbuf->pkt_len;
75 		vfr_bp->rx_pkts[que]++;
76 		rep_rxr->rx_raw_prod++;
77 	} else {
78 		/* Representor Rx ring full, drop pkt */
79 		vfr_bp->rx_drop_bytes[que] += mbuf->pkt_len;
80 		vfr_bp->rx_drop_pkts[que]++;
81 		rte_mbuf_raw_free(mbuf);
82 	}
83 
84 	return 0;
85 }
86 
87 static uint16_t
88 bnxt_rep_rx_burst(void *rx_queue,
89 		     struct rte_mbuf **rx_pkts,
90 		     uint16_t nb_pkts)
91 {
92 	struct bnxt_rx_queue *rxq = rx_queue;
93 	struct rte_mbuf **cons_rx_buf;
94 	struct bnxt_rx_ring_info *rxr;
95 	uint16_t nb_rx_pkts = 0;
96 	uint16_t mask, i;
97 
98 	if (!rxq)
99 		return 0;
100 
101 	rxr = rxq->rx_ring;
102 	mask = rxr->rx_ring_struct->ring_mask;
103 	for (i = 0; i < nb_pkts; i++) {
104 		cons_rx_buf = &rxr->rx_buf_ring[rxr->rx_cons & mask];
105 		if (*cons_rx_buf == NULL)
106 			return nb_rx_pkts;
107 		rx_pkts[nb_rx_pkts] = *cons_rx_buf;
108 		rx_pkts[nb_rx_pkts]->port = rxq->port_id;
109 		*cons_rx_buf = NULL;
110 		nb_rx_pkts++;
111 		rxr->rx_cons++;
112 	}
113 
114 	return nb_rx_pkts;
115 }
116 
117 static uint16_t
118 bnxt_rep_tx_burst(void *tx_queue,
119 		     struct rte_mbuf **tx_pkts,
120 		     uint16_t nb_pkts)
121 {
122 	struct bnxt_vf_rep_tx_queue *vfr_txq = tx_queue;
123 	struct bnxt_tx_queue *ptxq;
124 	struct bnxt *parent;
125 	struct  bnxt_representor *vf_rep_bp;
126 	int qid;
127 	int rc;
128 	int i;
129 
130 	if (!vfr_txq)
131 		return 0;
132 
133 	qid = vfr_txq->txq->queue_id;
134 	vf_rep_bp = vfr_txq->bp;
135 	parent = vf_rep_bp->parent_dev->data->dev_private;
136 	ptxq = parent->tx_queues[qid];
137 	pthread_mutex_lock(&ptxq->txq_lock);
138 
139 	ptxq->vfr_tx_cfa_action = vf_rep_bp->vfr_tx_cfa_action;
140 
141 	for (i = 0; i < nb_pkts; i++) {
142 		vf_rep_bp->tx_bytes[qid] += tx_pkts[i]->pkt_len;
143 		vf_rep_bp->tx_pkts[qid]++;
144 	}
145 
146 	rc = _bnxt_xmit_pkts(ptxq, tx_pkts, nb_pkts);
147 	ptxq->vfr_tx_cfa_action = 0;
148 	pthread_mutex_unlock(&ptxq->txq_lock);
149 
150 	return rc;
151 }
152 
153 static int
154 bnxt_get_dflt_vnic_svif(struct bnxt *bp, struct bnxt_representor *vf_rep_bp)
155 {
156 	struct bnxt_rep_info *rep_info;
157 	int rc;
158 
159 	rc = bnxt_hwrm_get_dflt_vnic_svif(bp, vf_rep_bp->fw_fid,
160 					  &vf_rep_bp->dflt_vnic_id,
161 					  &vf_rep_bp->svif);
162 	if (rc) {
163 		PMD_DRV_LOG_LINE(ERR, "Failed to get default vnic id of VF");
164 		vf_rep_bp->dflt_vnic_id = BNXT_DFLT_VNIC_ID_INVALID;
165 		vf_rep_bp->svif = BNXT_SVIF_INVALID;
166 	} else {
167 		PMD_DRV_LOG_LINE(INFO, "vf_rep->dflt_vnic_id = %d",
168 				vf_rep_bp->dflt_vnic_id);
169 	}
170 	if (vf_rep_bp->dflt_vnic_id != BNXT_DFLT_VNIC_ID_INVALID &&
171 	    vf_rep_bp->svif != BNXT_SVIF_INVALID) {
172 		rep_info = &bp->rep_info[vf_rep_bp->vf_id];
173 		rep_info->conduit_valid = true;
174 	}
175 
176 	return rc;
177 }
178 
179 int bnxt_representor_init(struct rte_eth_dev *eth_dev, void *params)
180 {
181 	struct bnxt_representor *vf_rep_bp = eth_dev->data->dev_private;
182 	struct bnxt_representor *rep_params =
183 				 (struct bnxt_representor *)params;
184 	struct rte_eth_link *link;
185 	struct bnxt *parent_bp;
186 	uint16_t first_vf_id;
187 	int rc = 0;
188 
189 	PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR init", eth_dev->data->port_id);
190 	vf_rep_bp->vf_id = rep_params->vf_id;
191 	vf_rep_bp->switch_domain_id = rep_params->switch_domain_id;
192 	vf_rep_bp->parent_dev = rep_params->parent_dev;
193 	vf_rep_bp->rep_based_pf = rep_params->rep_based_pf;
194 	vf_rep_bp->flags = rep_params->flags;
195 	vf_rep_bp->rep_q_r2f = rep_params->rep_q_r2f;
196 	vf_rep_bp->rep_q_f2r = rep_params->rep_q_f2r;
197 	vf_rep_bp->rep_fc_r2f = rep_params->rep_fc_r2f;
198 	vf_rep_bp->rep_fc_f2r = rep_params->rep_fc_f2r;
199 
200 	eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR |
201 					RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
202 	eth_dev->data->representor_id = rep_params->vf_id;
203 	eth_dev->data->backer_port_id = rep_params->parent_dev->data->port_id;
204 
205 	rte_eth_random_addr(vf_rep_bp->dflt_mac_addr);
206 	memcpy(vf_rep_bp->mac_addr, vf_rep_bp->dflt_mac_addr,
207 	       sizeof(vf_rep_bp->mac_addr));
208 	eth_dev->data->mac_addrs =
209 		(struct rte_ether_addr *)&vf_rep_bp->mac_addr;
210 	eth_dev->dev_ops = &bnxt_rep_dev_ops;
211 
212 	/* No data-path, but need stub Rx/Tx functions to avoid crash
213 	 * when testing with ovs-dpdk
214 	 */
215 	eth_dev->rx_pkt_burst = bnxt_rep_rx_burst;
216 	eth_dev->tx_pkt_burst = bnxt_rep_tx_burst;
217 	/* Link state. Inherited from PF or trusted VF */
218 	parent_bp = vf_rep_bp->parent_dev->data->dev_private;
219 	link = &parent_bp->eth_dev->data->dev_link;
220 
221 	eth_dev->data->dev_link.link_speed = link->link_speed;
222 	eth_dev->data->dev_link.link_duplex = link->link_duplex;
223 	eth_dev->data->dev_link.link_status = link->link_status;
224 	eth_dev->data->dev_link.link_autoneg = link->link_autoneg;
225 
226 	bnxt_print_link_info(eth_dev);
227 
228 	PMD_DRV_LOG_LINE(INFO,
229 		    "Switch domain id %d: Representor Device %d init done",
230 		    vf_rep_bp->switch_domain_id, vf_rep_bp->vf_id);
231 
232 	if (BNXT_REP_BASED_PF(vf_rep_bp)) {
233 		vf_rep_bp->fw_fid = vf_rep_bp->rep_based_pf + 1;
234 		vf_rep_bp->parent_pf_idx = vf_rep_bp->rep_based_pf;
235 		if (!(BNXT_REP_PF(vf_rep_bp))) {
236 			/* VF representor for the remote PF,get first_vf_id */
237 			rc = bnxt_hwrm_first_vf_id_query(parent_bp,
238 							 vf_rep_bp->fw_fid,
239 							 &first_vf_id);
240 			if (rc)
241 				return rc;
242 			if (first_vf_id == 0xffff) {
243 				PMD_DRV_LOG_LINE(ERR,
244 					    "Invalid first_vf_id fid:%x",
245 					    vf_rep_bp->fw_fid);
246 				return -EINVAL;
247 			}
248 			PMD_DRV_LOG_LINE(INFO, "first_vf_id = %x parent_fid:%x",
249 				    first_vf_id, vf_rep_bp->fw_fid);
250 			vf_rep_bp->fw_fid = rep_params->vf_id + first_vf_id;
251 		}
252 	}  else {
253 		vf_rep_bp->fw_fid = rep_params->vf_id + parent_bp->first_vf_id;
254 		if (BNXT_VF_IS_TRUSTED(parent_bp))
255 			vf_rep_bp->parent_pf_idx = parent_bp->parent->fid - 1;
256 		else
257 			vf_rep_bp->parent_pf_idx = parent_bp->fw_fid - 1;
258 	}
259 
260 	PMD_DRV_LOG_LINE(INFO, "vf_rep->fw_fid = %d", vf_rep_bp->fw_fid);
261 
262 	return 0;
263 }
264 
265 int bnxt_representor_uninit(struct rte_eth_dev *eth_dev)
266 {
267 	struct bnxt *parent_bp;
268 	struct bnxt_representor *rep =
269 		(struct bnxt_representor *)eth_dev->data->dev_private;
270 	uint16_t vf_id;
271 
272 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
273 		return 0;
274 
275 	PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR uninit", eth_dev->data->port_id);
276 	eth_dev->data->mac_addrs = NULL;
277 
278 	if (!bnxt_rep_check_parent(rep)) {
279 		PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d already freed",
280 			    eth_dev->data->port_id);
281 		return 0;
282 	}
283 	parent_bp = rep->parent_dev->data->dev_private;
284 
285 	parent_bp->num_reps--;
286 	vf_id = rep->vf_id;
287 	if (parent_bp->rep_info)
288 		memset(&parent_bp->rep_info[vf_id], 0,
289 		       sizeof(parent_bp->rep_info[vf_id]));
290 		/* mark that this representor has been freed */
291 	return 0;
292 }
293 
294 int bnxt_rep_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_compl)
295 {
296 	struct bnxt *parent_bp;
297 	struct bnxt_representor *rep =
298 		(struct bnxt_representor *)eth_dev->data->dev_private;
299 	struct rte_eth_link *link;
300 	int rc;
301 
302 	parent_bp = rep->parent_dev->data->dev_private;
303 	if (!parent_bp)
304 		return 0;
305 
306 	rc = bnxt_link_update_op(parent_bp->eth_dev, wait_to_compl);
307 
308 	/* Link state. Inherited from PF or trusted VF */
309 	link = &parent_bp->eth_dev->data->dev_link;
310 
311 	eth_dev->data->dev_link.link_speed = link->link_speed;
312 	eth_dev->data->dev_link.link_duplex = link->link_duplex;
313 	eth_dev->data->dev_link.link_status = link->link_status;
314 	eth_dev->data->dev_link.link_autoneg = link->link_autoneg;
315 	bnxt_print_link_info(eth_dev);
316 
317 	return rc;
318 }
319 
320 static int bnxt_tf_vfr_alloc(struct rte_eth_dev *vfr_ethdev)
321 {
322 	int rc;
323 	struct bnxt_representor *vfr = vfr_ethdev->data->dev_private;
324 	struct rte_eth_dev *parent_dev = vfr->parent_dev;
325 	struct bnxt *parent_bp = parent_dev->data->dev_private;
326 
327 	if (!parent_bp || !parent_bp->ulp_ctx) {
328 		PMD_DRV_LOG_LINE(ERR, "Invalid arguments");
329 		return 0;
330 	}
331 	/* update the port id so you can backtrack to ethdev */
332 	vfr->dpdk_port_id = vfr_ethdev->data->port_id;
333 
334 	/* If pair is present, then delete the pair */
335 	if (!BNXT_CHIP_P7(parent_bp))
336 		if (bnxt_hwrm_cfa_pair_exists(parent_bp, vfr))
337 			(void)bnxt_hwrm_cfa_pair_free(parent_bp, vfr);
338 
339 	/* Update the ULP portdata base with the new VFR interface */
340 	rc = ulp_port_db_port_update(parent_bp->ulp_ctx, vfr_ethdev);
341 	if (rc) {
342 		PMD_DRV_LOG_LINE(ERR, "Failed to update ulp port details vfr:%u",
343 				 vfr->vf_id);
344 		return rc;
345 	}
346 
347 	/* Create the default rules for the VFR */
348 	rc = bnxt_ulp_create_vfr_default_rules(vfr_ethdev);
349 	if (rc) {
350 		PMD_DRV_LOG_LINE(ERR, "Failed to create VFR default rules vfr:%u",
351 				 vfr->vf_id);
352 		return rc;
353 	}
354 	/* update the port id so you can backtrack to ethdev */
355 	vfr->dpdk_port_id = vfr_ethdev->data->port_id;
356 
357 	if (BNXT_CHIP_P7(parent_bp))  {
358 		rc = bnxt_hwrm_release_afm_func(parent_bp,
359 				vfr->fw_fid,
360 				parent_bp->fw_fid,
361 				HWRM_CFA_RELEASE_AFM_FUNC_INPUT_TYPE_EFID,
362 				0);
363 
364 		if (rc) {
365 			PMD_DRV_LOG_LINE(ERR,
366 					 "Failed to release EFID:%d from RFID:%d rc=%d",
367 					 vfr->vf_id, parent_bp->fw_fid, rc);
368 			goto error_del_rules;
369 		}
370 		PMD_DRV_LOG_LINE(DEBUG, "Released EFID:%d from RFID:%d",
371 				 vfr->fw_fid, parent_bp->fw_fid);
372 
373 	} else {
374 		rc = bnxt_hwrm_cfa_pair_alloc(parent_bp, vfr);
375 		if (rc) {
376 			PMD_DRV_LOG_LINE(ERR,
377 					 "Failed in hwrm vfr alloc vfr:%u rc=%d",
378 					 vfr->vf_id, rc);
379 			goto error_del_rules;
380 		}
381 	}
382 
383 	/* if supported, it will add the vfr endpoint to the session, otherwise
384 	 * it returns success
385 	 */
386 	rc = bnxt_ulp_vfr_session_fid_add(parent_bp->ulp_ctx, vfr->fw_fid);
387 	if (rc)
388 		goto error_del_rules;
389 	else
390 		PMD_DRV_LOG_LINE(DEBUG,
391 				 "BNXT Port:%d VFR created and initialized",
392 				 vfr->dpdk_port_id);
393 	return rc;
394 error_del_rules:
395 	(void)bnxt_ulp_delete_vfr_default_rules(vfr);
396 	return rc;
397 }
398 
399 static int bnxt_vfr_alloc(struct rte_eth_dev *vfr_ethdev)
400 {
401 	int rc = 0;
402 	struct bnxt_representor *vfr = vfr_ethdev->data->dev_private;
403 	struct bnxt *parent_bp;
404 
405 	if (!vfr || !vfr->parent_dev) {
406 		PMD_DRV_LOG_LINE(ERR,
407 				"No memory allocated for representor");
408 		return -ENOMEM;
409 	}
410 
411 	parent_bp = vfr->parent_dev->data->dev_private;
412 	if (parent_bp && !parent_bp->ulp_ctx) {
413 		PMD_DRV_LOG_LINE(ERR,
414 			    "ulp context not allocated for parent");
415 		return -EIO;
416 	}
417 
418 	/* Check if representor has been already allocated in FW */
419 	if (vfr->vfr_tx_cfa_action)
420 		return 0;
421 
422 	/*
423 	 * Alloc VF rep rules in CFA after default VNIC is created.
424 	 * Otherwise the FW will create the VF-rep rules with
425 	 * default drop action.
426 	 */
427 	rc = bnxt_tf_vfr_alloc(vfr_ethdev);
428 	if (!rc)
429 		PMD_DRV_LOG_LINE(DEBUG, "allocated representor %d in FW",
430 			    vfr->vf_id);
431 	else
432 		PMD_DRV_LOG_LINE(ERR,
433 			    "Failed to alloc representor %d in FW",
434 			    vfr->vf_id);
435 
436 	return rc;
437 }
438 
439 static void bnxt_vfr_rx_queue_release_mbufs(struct bnxt_rx_queue *rxq)
440 {
441 	struct rte_mbuf **sw_ring;
442 	unsigned int i;
443 
444 	if (!rxq || !rxq->rx_ring)
445 		return;
446 
447 	sw_ring = rxq->rx_ring->rx_buf_ring;
448 	if (sw_ring) {
449 		for (i = 0; i < rxq->rx_ring->rx_ring_struct->ring_size; i++) {
450 			if (sw_ring[i]) {
451 				if (sw_ring[i] != &rxq->fake_mbuf)
452 					rte_pktmbuf_free_seg(sw_ring[i]);
453 				sw_ring[i] = NULL;
454 			}
455 		}
456 	}
457 }
458 
459 static void bnxt_rep_free_rx_mbufs(struct bnxt_representor *rep_bp)
460 {
461 	struct bnxt_rx_queue *rxq;
462 	unsigned int i;
463 
464 	for (i = 0; i < rep_bp->rx_nr_rings; i++) {
465 		rxq = rep_bp->rx_queues[i];
466 		bnxt_vfr_rx_queue_release_mbufs(rxq);
467 	}
468 }
469 
470 int bnxt_rep_dev_start_op(struct rte_eth_dev *eth_dev)
471 {
472 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
473 	struct bnxt_rep_info *rep_info;
474 	struct bnxt *parent_bp;
475 	int rc;
476 
477 	parent_bp = rep_bp->parent_dev->data->dev_private;
478 	rep_info = &parent_bp->rep_info[rep_bp->vf_id];
479 
480 	PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR start",
481 			 eth_dev->data->port_id);
482 	pthread_mutex_lock(&rep_info->vfr_start_lock);
483 	if (!rep_info->conduit_valid) {
484 		rc = bnxt_get_dflt_vnic_svif(parent_bp, rep_bp);
485 		if (rc || !rep_info->conduit_valid) {
486 			pthread_mutex_unlock(&rep_info->vfr_start_lock);
487 			return rc;
488 		}
489 	}
490 	pthread_mutex_unlock(&rep_info->vfr_start_lock);
491 
492 	rc = bnxt_vfr_alloc(eth_dev);
493 	if (rc) {
494 		eth_dev->data->dev_link.link_status = 0;
495 		bnxt_rep_free_rx_mbufs(rep_bp);
496 		return rc;
497 	}
498 	eth_dev->rx_pkt_burst = &bnxt_rep_rx_burst;
499 	eth_dev->tx_pkt_burst = &bnxt_rep_tx_burst;
500 	bnxt_rep_link_update_op(eth_dev, 1);
501 
502 	return 0;
503 }
504 
505 static int bnxt_tf_vfr_free(struct bnxt_representor *vfr)
506 {
507 	struct bnxt *parent_bp;
508 	int32_t rc;
509 
510 	PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR ulp free", vfr->dpdk_port_id);
511 	rc = bnxt_ulp_delete_vfr_default_rules(vfr);
512 	if (rc)
513 		PMD_DRV_LOG_LINE(ERR,
514 				 "Failed to delete dflt rules from Port:%d VFR",
515 				 vfr->dpdk_port_id);
516 
517 	/* Need to remove the vfr fid from the session regardless */
518 	parent_bp = vfr->parent_dev->data->dev_private;
519 	if (!parent_bp) {
520 		PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR already freed",
521 				 vfr->dpdk_port_id);
522 		return 0;
523 	}
524 	rc = bnxt_ulp_vfr_session_fid_rem(parent_bp->ulp_ctx, vfr->fw_fid);
525 	if (rc)
526 		PMD_DRV_LOG_LINE(ERR,
527 				 "Failed to remove BNXT Port:%d VFR from session",
528 				 vfr->dpdk_port_id);
529 	return rc;
530 }
531 
532 static int bnxt_vfr_free(struct bnxt_representor *vfr)
533 {
534 	int rc = 0;
535 	struct bnxt *parent_bp;
536 
537 	if (!vfr || !vfr->parent_dev) {
538 		PMD_DRV_LOG_LINE(ERR,
539 			    "No memory allocated for representor");
540 		return -ENOMEM;
541 	}
542 
543 	if (!bnxt_rep_check_parent(vfr)) {
544 		PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR already freed",
545 			    vfr->dpdk_port_id);
546 		return 0;
547 	}
548 	parent_bp = vfr->parent_dev->data->dev_private;
549 
550 	/* Check if representor has been already freed in FW */
551 	if (!vfr->vfr_tx_cfa_action)
552 		return 0;
553 
554 	rc = bnxt_tf_vfr_free(vfr);
555 	if (rc) {
556 		PMD_DRV_LOG_LINE(ERR,
557 			    "Failed to free representor %d in FW",
558 			    vfr->vf_id);
559 	}
560 
561 	PMD_DRV_LOG_LINE(DEBUG, "freed representor %d in FW",
562 		    vfr->vf_id);
563 	vfr->vfr_tx_cfa_action = 0;
564 
565 	if  (!BNXT_CHIP_P7(parent_bp))
566 		rc = bnxt_hwrm_cfa_pair_free(parent_bp, vfr);
567 
568 	return rc;
569 }
570 
571 int bnxt_rep_dev_stop_op(struct rte_eth_dev *eth_dev)
572 {
573 	struct bnxt_representor *vfr_bp = eth_dev->data->dev_private;
574 
575 	/* Avoid crashes as we are about to free queues */
576 	bnxt_stop_rxtx(eth_dev);
577 
578 	PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR stop",
579 			 eth_dev->data->port_id);
580 
581 	bnxt_vfr_free(vfr_bp);
582 
583 	if (eth_dev->data->dev_started)
584 		eth_dev->data->dev_link.link_status = 0;
585 
586 	bnxt_rep_free_rx_mbufs(vfr_bp);
587 
588 	return 0;
589 }
590 
591 int bnxt_rep_dev_close_op(struct rte_eth_dev *eth_dev)
592 {
593 	PMD_DRV_LOG_LINE(DEBUG, "BNXT Port:%d VFR close",
594 			 eth_dev->data->port_id);
595 	bnxt_representor_uninit(eth_dev);
596 	return 0;
597 }
598 
599 int bnxt_rep_dev_info_get_op(struct rte_eth_dev *eth_dev,
600 				struct rte_eth_dev_info *dev_info)
601 {
602 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
603 	struct bnxt *parent_bp;
604 	unsigned int max_rx_rings;
605 
606 	/* MAC Specifics */
607 	if (!bnxt_rep_check_parent(rep_bp)) {
608 		PMD_DRV_LOG_LINE(INFO, "Rep parent port does not exist");
609 		/* Need be an error scenario, if parent is removed first */
610 		if (eth_dev->device->driver == NULL)
611 			return -ENODEV;
612 		/* Need not be an error scenario, if parent is closed first */
613 		return 0;
614 	}
615 	parent_bp = rep_bp->parent_dev->data->dev_private;
616 	PMD_DRV_LOG_LINE(DEBUG, "Representor dev_info_get_op");
617 	dev_info->max_mac_addrs = parent_bp->max_l2_ctx;
618 	dev_info->max_hash_mac_addrs = 0;
619 
620 	max_rx_rings = parent_bp->rx_nr_rings ?
621 		RTE_MIN(parent_bp->rx_nr_rings, BNXT_MAX_VF_REP_RINGS) :
622 		BNXT_MAX_VF_REP_RINGS;
623 
624 	/* For the sake of symmetry, max_rx_queues = max_tx_queues */
625 	dev_info->max_rx_queues = max_rx_rings;
626 	dev_info->max_tx_queues = max_rx_rings;
627 	dev_info->reta_size = bnxt_rss_hash_tbl_size(parent_bp);
628 	dev_info->hash_key_size = 40;
629 	dev_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
630 
631 	/* MTU specifics */
632 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
633 	dev_info->max_mtu = BNXT_MAX_MTU;
634 
635 	/* Fast path specifics */
636 	dev_info->min_rx_bufsize = 1;
637 	dev_info->max_rx_pktlen = BNXT_MAX_PKT_LEN;
638 
639 	dev_info->rx_offload_capa = bnxt_get_rx_port_offloads(parent_bp);
640 	dev_info->tx_offload_capa = bnxt_get_tx_port_offloads(parent_bp);
641 	dev_info->flow_type_rss_offloads = bnxt_eth_rss_support(parent_bp);
642 
643 	dev_info->switch_info.name = eth_dev->device->name;
644 	dev_info->switch_info.domain_id = rep_bp->switch_domain_id;
645 	dev_info->switch_info.port_id =
646 			rep_bp->vf_id & BNXT_SWITCH_PORT_ID_VF_MASK;
647 
648 	return 0;
649 }
650 
651 int bnxt_rep_dev_configure_op(struct rte_eth_dev *eth_dev)
652 {
653 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
654 
655 	PMD_DRV_LOG_LINE(DEBUG, "Representor dev_configure_op");
656 	rep_bp->rx_queues = (void *)eth_dev->data->rx_queues;
657 	rep_bp->tx_nr_rings = eth_dev->data->nb_tx_queues;
658 	rep_bp->rx_nr_rings = eth_dev->data->nb_rx_queues;
659 
660 	return 0;
661 }
662 
663 static int bnxt_init_rep_rx_ring(struct bnxt_rx_queue *rxq,
664 				 unsigned int socket_id)
665 {
666 	struct bnxt_rx_ring_info *rxr;
667 	struct bnxt_ring *ring;
668 
669 	rxr = rte_zmalloc_socket("bnxt_rep_rx_ring",
670 				 sizeof(struct bnxt_rx_ring_info),
671 				 RTE_CACHE_LINE_SIZE, socket_id);
672 	if (rxr == NULL)
673 		return -ENOMEM;
674 	rxq->rx_ring = rxr;
675 
676 	ring = rte_zmalloc_socket("bnxt_rep_rx_ring_struct",
677 				  sizeof(struct bnxt_ring),
678 				  RTE_CACHE_LINE_SIZE, socket_id);
679 	if (ring == NULL)
680 		return -ENOMEM;
681 	rxr->rx_ring_struct = ring;
682 	ring->ring_size = rte_align32pow2(rxq->nb_rx_desc);
683 	ring->ring_mask = ring->ring_size - 1;
684 
685 	return 0;
686 }
687 
688 int bnxt_rep_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
689 			       uint16_t queue_idx,
690 			       uint16_t nb_desc,
691 			       unsigned int socket_id,
692 			       __rte_unused const struct rte_eth_rxconf *rx_conf,
693 			       __rte_unused struct rte_mempool *mp)
694 {
695 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
696 	struct bnxt *parent_bp = rep_bp->parent_dev->data->dev_private;
697 	struct bnxt_rx_queue *parent_rxq;
698 	struct bnxt_rx_queue *rxq;
699 	struct rte_mbuf **buf_ring;
700 	int rc = 0;
701 
702 	if (queue_idx >= rep_bp->rx_nr_rings) {
703 		PMD_DRV_LOG_LINE(ERR,
704 			    "Cannot create Rx ring %d. %d rings available",
705 			    queue_idx, rep_bp->rx_nr_rings);
706 		return -EINVAL;
707 	}
708 
709 	if (!nb_desc || nb_desc > MAX_RX_DESC_CNT) {
710 		PMD_DRV_LOG_LINE(ERR, "nb_desc %d is invalid", nb_desc);
711 		return -EINVAL;
712 	}
713 
714 	if (!parent_bp->rx_queues) {
715 		PMD_DRV_LOG_LINE(ERR, "Parent Rx qs not configured yet");
716 		return -EINVAL;
717 	}
718 
719 	parent_rxq = parent_bp->rx_queues[queue_idx];
720 	if (!parent_rxq) {
721 		PMD_DRV_LOG_LINE(ERR, "Parent RxQ has not been configured yet");
722 		return -EINVAL;
723 	}
724 
725 	if (nb_desc != parent_rxq->nb_rx_desc) {
726 		PMD_DRV_LOG_LINE(ERR, "nb_desc %d do not match parent rxq", nb_desc);
727 		return -EINVAL;
728 	}
729 
730 	if (eth_dev->data->rx_queues) {
731 		rxq = eth_dev->data->rx_queues[queue_idx];
732 		if (rxq)
733 			bnxt_rx_queue_release_op(eth_dev, queue_idx);
734 	}
735 
736 	rxq = rte_zmalloc_socket("bnxt_vfr_rx_queue",
737 				 sizeof(struct bnxt_rx_queue),
738 				 RTE_CACHE_LINE_SIZE, socket_id);
739 	if (!rxq) {
740 		PMD_DRV_LOG_LINE(ERR, "bnxt_vfr_rx_queue allocation failed!");
741 		return -ENOMEM;
742 	}
743 
744 	eth_dev->data->rx_queues[queue_idx] = rxq;
745 
746 	rxq->nb_rx_desc = nb_desc;
747 
748 	rc = bnxt_init_rep_rx_ring(rxq, socket_id);
749 	if (rc)
750 		goto out;
751 
752 	buf_ring = rte_zmalloc_socket("bnxt_rx_vfr_buf_ring",
753 				      sizeof(struct rte_mbuf *) *
754 				      rxq->rx_ring->rx_ring_struct->ring_size,
755 				      RTE_CACHE_LINE_SIZE, socket_id);
756 	if (!buf_ring) {
757 		PMD_DRV_LOG_LINE(ERR, "bnxt_rx_vfr_buf_ring allocation failed!");
758 		rc = -ENOMEM;
759 		goto out;
760 	}
761 
762 	rxq->rx_ring->rx_buf_ring = buf_ring;
763 	rxq->queue_id = queue_idx;
764 	rxq->port_id = eth_dev->data->port_id;
765 
766 	return 0;
767 
768 out:
769 	if (rxq) {
770  #if (RTE_VERSION_NUM(21, 8, 0, 0) < RTE_VERSION)
771 		bnxt_rep_rx_queue_release_op(eth_dev, queue_idx);
772  #else
773 		bnxt_rx_queue_release_op(rxq);
774  #endif
775 	}
776 
777 	return rc;
778 }
779 
780 void bnxt_rep_rx_queue_release_op(struct rte_eth_dev *dev, uint16_t queue_idx)
781 {
782 	struct bnxt_rx_queue *rxq = dev->data->rx_queues[queue_idx];
783 
784 	if (!rxq)
785 		return;
786 
787 	bnxt_rx_queue_release_mbufs(rxq);
788 
789 	bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
790 	rte_free(rxq->rx_ring->rx_ring_struct);
791 	rte_free(rxq->rx_ring);
792 
793 	rte_free(rxq);
794 }
795 
796 int bnxt_rep_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
797 			       uint16_t queue_idx,
798 			       uint16_t nb_desc,
799 			       unsigned int socket_id,
800 			       __rte_unused const struct rte_eth_txconf *tx_conf)
801 {
802 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
803 	struct bnxt *parent_bp = rep_bp->parent_dev->data->dev_private;
804 	struct bnxt_tx_queue *parent_txq, *txq;
805 	struct bnxt_vf_rep_tx_queue *vfr_txq;
806 
807 	if (queue_idx >= rep_bp->tx_nr_rings) {
808 		PMD_DRV_LOG_LINE(ERR,
809 			    "Cannot create Tx rings %d. %d rings available",
810 			    queue_idx, rep_bp->tx_nr_rings);
811 		return -EINVAL;
812 	}
813 
814 	if (!nb_desc || nb_desc > MAX_TX_DESC_CNT) {
815 		PMD_DRV_LOG_LINE(ERR, "nb_desc %d is invalid", nb_desc);
816 		return -EINVAL;
817 	}
818 
819 	if (!parent_bp->tx_queues) {
820 		PMD_DRV_LOG_LINE(ERR, "Parent Tx qs not configured yet");
821 		return -EINVAL;
822 	}
823 
824 	parent_txq = parent_bp->tx_queues[queue_idx];
825 	if (!parent_txq) {
826 		PMD_DRV_LOG_LINE(ERR, "Parent TxQ has not been configured yet");
827 		return -EINVAL;
828 	}
829 
830 	if (nb_desc != parent_txq->nb_tx_desc) {
831 		PMD_DRV_LOG_LINE(ERR, "nb_desc %d do not match parent txq", nb_desc);
832 		return -EINVAL;
833 	}
834 
835 	if (eth_dev->data->tx_queues) {
836 		vfr_txq = eth_dev->data->tx_queues[queue_idx];
837 		if (vfr_txq != NULL)
838 			bnxt_rep_tx_queue_release_op(eth_dev, queue_idx);
839 	}
840 
841 	vfr_txq = rte_zmalloc_socket("bnxt_vfr_tx_queue",
842 				     sizeof(struct bnxt_vf_rep_tx_queue),
843 				     RTE_CACHE_LINE_SIZE, socket_id);
844 	if (!vfr_txq) {
845 		PMD_DRV_LOG_LINE(ERR, "bnxt_vfr_tx_queue allocation failed!");
846 		return -ENOMEM;
847 	}
848 	txq = rte_zmalloc_socket("bnxt_tx_queue",
849 				 sizeof(struct bnxt_tx_queue),
850 				 RTE_CACHE_LINE_SIZE, socket_id);
851 	if (!txq) {
852 		PMD_DRV_LOG_LINE(ERR, "bnxt_tx_queue allocation failed!");
853 		rte_free(vfr_txq);
854 		return -ENOMEM;
855 	}
856 
857 	txq->nb_tx_desc = nb_desc;
858 	txq->queue_id = queue_idx;
859 	txq->port_id = eth_dev->data->port_id;
860 	vfr_txq->txq = txq;
861 	vfr_txq->bp = rep_bp;
862 	eth_dev->data->tx_queues[queue_idx] = vfr_txq;
863 
864 	return 0;
865 }
866 
867 void bnxt_rep_tx_queue_release_op(struct rte_eth_dev *dev, uint16_t queue_idx)
868 {
869 	struct bnxt_vf_rep_tx_queue *vfr_txq = dev->data->tx_queues[queue_idx];
870 
871 	if (!vfr_txq)
872 		return;
873 
874 	rte_free(vfr_txq->txq);
875 	rte_free(vfr_txq);
876 	dev->data->tx_queues[queue_idx] = NULL;
877 }
878 
879 int bnxt_rep_stats_get_op(struct rte_eth_dev *eth_dev,
880 			     struct rte_eth_stats *stats)
881 {
882 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
883 	unsigned int i;
884 
885 	memset(stats, 0, sizeof(*stats));
886 	for (i = 0; i < rep_bp->rx_nr_rings; i++) {
887 		stats->obytes += rep_bp->tx_bytes[i];
888 		stats->opackets += rep_bp->tx_pkts[i];
889 		stats->ibytes += rep_bp->rx_bytes[i];
890 		stats->ipackets += rep_bp->rx_pkts[i];
891 		stats->imissed += rep_bp->rx_drop_pkts[i];
892 
893 		stats->q_ipackets[i] = rep_bp->rx_pkts[i];
894 		stats->q_ibytes[i] = rep_bp->rx_bytes[i];
895 		stats->q_opackets[i] = rep_bp->tx_pkts[i];
896 		stats->q_obytes[i] = rep_bp->tx_bytes[i];
897 		stats->q_errors[i] = rep_bp->rx_drop_pkts[i];
898 	}
899 
900 	return 0;
901 }
902 
903 int bnxt_rep_stats_reset_op(struct rte_eth_dev *eth_dev)
904 {
905 	struct bnxt_representor *rep_bp = eth_dev->data->dev_private;
906 	unsigned int i;
907 
908 	for (i = 0; i < rep_bp->rx_nr_rings; i++) {
909 		rep_bp->tx_pkts[i] = 0;
910 		rep_bp->tx_bytes[i] = 0;
911 		rep_bp->rx_pkts[i] = 0;
912 		rep_bp->rx_bytes[i] = 0;
913 		rep_bp->rx_drop_pkts[i] = 0;
914 	}
915 	return 0;
916 }
917 
918 int bnxt_rep_stop_all(struct bnxt *bp)
919 {
920 	uint16_t vf_id;
921 	struct rte_eth_dev *rep_eth_dev;
922 	int ret;
923 
924 	/* No vfrep ports just exit */
925 	if (!bp->rep_info)
926 		return 0;
927 
928 	for (vf_id = 0; vf_id < BNXT_MAX_VF_REPS(bp); vf_id++) {
929 		rep_eth_dev = bp->rep_info[vf_id].vfr_eth_dev;
930 		if (!rep_eth_dev)
931 			continue;
932 		ret = bnxt_rep_dev_stop_op(rep_eth_dev);
933 		if (ret != 0)
934 			return ret;
935 	}
936 
937 	return 0;
938 }
939