xref: /f-stack/dpdk/drivers/net/mlx5/mlx5_trigger.c (revision d30ea906)
1*d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2a9643ea8Slogwang  * Copyright 2015 6WIND S.A.
3*d30ea906Sjfb8856606  * Copyright 2015 Mellanox Technologies, Ltd
4a9643ea8Slogwang  */
5*d30ea906Sjfb8856606 
62bfe3f2eSlogwang #include <unistd.h>
7a9643ea8Slogwang 
8a9643ea8Slogwang #include <rte_ether.h>
9*d30ea906Sjfb8856606 #include <rte_ethdev_driver.h>
10a9643ea8Slogwang #include <rte_interrupts.h>
11a9643ea8Slogwang #include <rte_alarm.h>
12a9643ea8Slogwang 
13a9643ea8Slogwang #include "mlx5.h"
14a9643ea8Slogwang #include "mlx5_rxtx.h"
15a9643ea8Slogwang #include "mlx5_utils.h"
16a9643ea8Slogwang 
17579bf1e2Sjfb8856606 /**
18579bf1e2Sjfb8856606  * Stop traffic on Tx queues.
19579bf1e2Sjfb8856606  *
20579bf1e2Sjfb8856606  * @param dev
21579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
22579bf1e2Sjfb8856606  */
232bfe3f2eSlogwang static void
24579bf1e2Sjfb8856606 mlx5_txq_stop(struct rte_eth_dev *dev)
252bfe3f2eSlogwang {
26579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
272bfe3f2eSlogwang 	unsigned int i;
282bfe3f2eSlogwang 
292bfe3f2eSlogwang 	for (i = 0; i != priv->txqs_n; ++i)
30579bf1e2Sjfb8856606 		mlx5_txq_release(dev, i);
312bfe3f2eSlogwang }
322bfe3f2eSlogwang 
33579bf1e2Sjfb8856606 /**
34579bf1e2Sjfb8856606  * Start traffic on Tx queues.
35579bf1e2Sjfb8856606  *
36579bf1e2Sjfb8856606  * @param dev
37579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
38579bf1e2Sjfb8856606  *
39579bf1e2Sjfb8856606  * @return
40579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
41579bf1e2Sjfb8856606  */
422bfe3f2eSlogwang static int
43579bf1e2Sjfb8856606 mlx5_txq_start(struct rte_eth_dev *dev)
442bfe3f2eSlogwang {
45579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
462bfe3f2eSlogwang 	unsigned int i;
47579bf1e2Sjfb8856606 	int ret;
482bfe3f2eSlogwang 
492bfe3f2eSlogwang 	for (i = 0; i != priv->txqs_n; ++i) {
50579bf1e2Sjfb8856606 		struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i);
512bfe3f2eSlogwang 
522bfe3f2eSlogwang 		if (!txq_ctrl)
532bfe3f2eSlogwang 			continue;
542bfe3f2eSlogwang 		txq_alloc_elts(txq_ctrl);
55579bf1e2Sjfb8856606 		txq_ctrl->ibv = mlx5_txq_ibv_new(dev, i);
562bfe3f2eSlogwang 		if (!txq_ctrl->ibv) {
57579bf1e2Sjfb8856606 			rte_errno = ENOMEM;
582bfe3f2eSlogwang 			goto error;
592bfe3f2eSlogwang 		}
602bfe3f2eSlogwang 	}
61579bf1e2Sjfb8856606 	ret = mlx5_tx_uar_remap(dev, priv->ctx->cmd_fd);
62579bf1e2Sjfb8856606 	if (ret) {
63579bf1e2Sjfb8856606 		/* Adjust index for rollback. */
64579bf1e2Sjfb8856606 		i = priv->txqs_n - 1;
65579bf1e2Sjfb8856606 		goto error;
66579bf1e2Sjfb8856606 	}
67579bf1e2Sjfb8856606 	return 0;
682bfe3f2eSlogwang error:
69579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
70579bf1e2Sjfb8856606 	do {
71579bf1e2Sjfb8856606 		mlx5_txq_release(dev, i);
72579bf1e2Sjfb8856606 	} while (i-- != 0);
73579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
74579bf1e2Sjfb8856606 	return -rte_errno;
752bfe3f2eSlogwang }
762bfe3f2eSlogwang 
77579bf1e2Sjfb8856606 /**
78579bf1e2Sjfb8856606  * Stop traffic on Rx queues.
79579bf1e2Sjfb8856606  *
80579bf1e2Sjfb8856606  * @param dev
81579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
82579bf1e2Sjfb8856606  */
832bfe3f2eSlogwang static void
84579bf1e2Sjfb8856606 mlx5_rxq_stop(struct rte_eth_dev *dev)
852bfe3f2eSlogwang {
86579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
872bfe3f2eSlogwang 	unsigned int i;
882bfe3f2eSlogwang 
892bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i)
90579bf1e2Sjfb8856606 		mlx5_rxq_release(dev, i);
912bfe3f2eSlogwang }
922bfe3f2eSlogwang 
93579bf1e2Sjfb8856606 /**
94579bf1e2Sjfb8856606  * Start traffic on Rx queues.
95579bf1e2Sjfb8856606  *
96579bf1e2Sjfb8856606  * @param dev
97579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
98579bf1e2Sjfb8856606  *
99579bf1e2Sjfb8856606  * @return
100579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
101579bf1e2Sjfb8856606  */
1022bfe3f2eSlogwang static int
103579bf1e2Sjfb8856606 mlx5_rxq_start(struct rte_eth_dev *dev)
1042bfe3f2eSlogwang {
105579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
1062bfe3f2eSlogwang 	unsigned int i;
1072bfe3f2eSlogwang 	int ret = 0;
1082bfe3f2eSlogwang 
109*d30ea906Sjfb8856606 	/* Allocate/reuse/resize mempool for Multi-Packet RQ. */
110*d30ea906Sjfb8856606 	if (mlx5_mprq_alloc_mp(dev)) {
111*d30ea906Sjfb8856606 		/* Should not release Rx queues but return immediately. */
112*d30ea906Sjfb8856606 		return -rte_errno;
113*d30ea906Sjfb8856606 	}
1142bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i) {
115579bf1e2Sjfb8856606 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i);
116*d30ea906Sjfb8856606 		struct rte_mempool *mp;
1172bfe3f2eSlogwang 
1182bfe3f2eSlogwang 		if (!rxq_ctrl)
1192bfe3f2eSlogwang 			continue;
120*d30ea906Sjfb8856606 		/* Pre-register Rx mempool. */
121*d30ea906Sjfb8856606 		mp = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ?
122*d30ea906Sjfb8856606 		     rxq_ctrl->rxq.mprq_mp : rxq_ctrl->rxq.mp;
123*d30ea906Sjfb8856606 		DRV_LOG(DEBUG,
124*d30ea906Sjfb8856606 			"port %u Rx queue %u registering"
125*d30ea906Sjfb8856606 			" mp %s having %u chunks",
126*d30ea906Sjfb8856606 			dev->data->port_id, rxq_ctrl->idx,
127*d30ea906Sjfb8856606 			mp->name, mp->nb_mem_chunks);
128*d30ea906Sjfb8856606 		mlx5_mr_update_mp(dev, &rxq_ctrl->rxq.mr_ctrl, mp);
1292bfe3f2eSlogwang 		ret = rxq_alloc_elts(rxq_ctrl);
1302bfe3f2eSlogwang 		if (ret)
1312bfe3f2eSlogwang 			goto error;
132579bf1e2Sjfb8856606 		rxq_ctrl->ibv = mlx5_rxq_ibv_new(dev, i);
133579bf1e2Sjfb8856606 		if (!rxq_ctrl->ibv)
1342bfe3f2eSlogwang 			goto error;
1352bfe3f2eSlogwang 	}
136579bf1e2Sjfb8856606 	return 0;
1372bfe3f2eSlogwang error:
138579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
139579bf1e2Sjfb8856606 	do {
140579bf1e2Sjfb8856606 		mlx5_rxq_release(dev, i);
141579bf1e2Sjfb8856606 	} while (i-- != 0);
142579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
143579bf1e2Sjfb8856606 	return -rte_errno;
1442bfe3f2eSlogwang }
1452bfe3f2eSlogwang 
146a9643ea8Slogwang /**
147a9643ea8Slogwang  * DPDK callback to start the device.
148a9643ea8Slogwang  *
149a9643ea8Slogwang  * Simulate device start by attaching all configured flows.
150a9643ea8Slogwang  *
151a9643ea8Slogwang  * @param dev
152a9643ea8Slogwang  *   Pointer to Ethernet device structure.
153a9643ea8Slogwang  *
154a9643ea8Slogwang  * @return
155579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
156a9643ea8Slogwang  */
157a9643ea8Slogwang int
158a9643ea8Slogwang mlx5_dev_start(struct rte_eth_dev *dev)
159a9643ea8Slogwang {
160a9643ea8Slogwang 	struct priv *priv = dev->data->dev_private;
161579bf1e2Sjfb8856606 	int ret;
162a9643ea8Slogwang 
163579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id);
164579bf1e2Sjfb8856606 	ret = mlx5_txq_start(dev);
165579bf1e2Sjfb8856606 	if (ret) {
166579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Tx queue allocation failed: %s",
167579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
168579bf1e2Sjfb8856606 		return -rte_errno;
169a9643ea8Slogwang 	}
170579bf1e2Sjfb8856606 	ret = mlx5_rxq_start(dev);
171579bf1e2Sjfb8856606 	if (ret) {
172579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Rx queue allocation failed: %s",
173579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
174579bf1e2Sjfb8856606 		mlx5_txq_stop(dev);
175579bf1e2Sjfb8856606 		return -rte_errno;
1762bfe3f2eSlogwang 	}
177579bf1e2Sjfb8856606 	dev->data->dev_started = 1;
178579bf1e2Sjfb8856606 	ret = mlx5_rx_intr_vec_enable(dev);
179579bf1e2Sjfb8856606 	if (ret) {
180579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Rx interrupt vector creation failed",
1812bfe3f2eSlogwang 			dev->data->port_id);
1822bfe3f2eSlogwang 		goto error;
1832bfe3f2eSlogwang 	}
184579bf1e2Sjfb8856606 	mlx5_xstats_init(dev);
185579bf1e2Sjfb8856606 	ret = mlx5_traffic_enable(dev);
186579bf1e2Sjfb8856606 	if (ret) {
187579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set defaults flows",
188579bf1e2Sjfb8856606 			dev->data->port_id);
189579bf1e2Sjfb8856606 		goto error;
190579bf1e2Sjfb8856606 	}
191579bf1e2Sjfb8856606 	ret = mlx5_flow_start(dev, &priv->flows);
192579bf1e2Sjfb8856606 	if (ret) {
193579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set flows",
194579bf1e2Sjfb8856606 			dev->data->port_id);
195579bf1e2Sjfb8856606 		goto error;
196579bf1e2Sjfb8856606 	}
197579bf1e2Sjfb8856606 	dev->tx_pkt_burst = mlx5_select_tx_function(dev);
198579bf1e2Sjfb8856606 	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
199579bf1e2Sjfb8856606 	mlx5_dev_interrupt_handler_install(dev);
2002bfe3f2eSlogwang 	return 0;
2012bfe3f2eSlogwang error:
202579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
2032bfe3f2eSlogwang 	/* Rollback. */
2042bfe3f2eSlogwang 	dev->data->dev_started = 0;
205579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
206579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
207579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
208579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
209579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
210579bf1e2Sjfb8856606 	return -rte_errno;
211a9643ea8Slogwang }
212a9643ea8Slogwang 
213a9643ea8Slogwang /**
214a9643ea8Slogwang  * DPDK callback to stop the device.
215a9643ea8Slogwang  *
216a9643ea8Slogwang  * Simulate device stop by detaching all configured flows.
217a9643ea8Slogwang  *
218a9643ea8Slogwang  * @param dev
219a9643ea8Slogwang  *   Pointer to Ethernet device structure.
220a9643ea8Slogwang  */
221a9643ea8Slogwang void
222a9643ea8Slogwang mlx5_dev_stop(struct rte_eth_dev *dev)
223a9643ea8Slogwang {
224a9643ea8Slogwang 	struct priv *priv = dev->data->dev_private;
225a9643ea8Slogwang 
2262bfe3f2eSlogwang 	dev->data->dev_started = 0;
2272bfe3f2eSlogwang 	/* Prevent crashes when queues are still in use. */
2282bfe3f2eSlogwang 	dev->rx_pkt_burst = removed_rx_burst;
2292bfe3f2eSlogwang 	dev->tx_pkt_burst = removed_tx_burst;
2302bfe3f2eSlogwang 	rte_wmb();
2312bfe3f2eSlogwang 	usleep(1000 * priv->rxqs_n);
232579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id);
233579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
234579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
235579bf1e2Sjfb8856606 	mlx5_rx_intr_vec_disable(dev);
236579bf1e2Sjfb8856606 	mlx5_dev_interrupt_handler_uninstall(dev);
237579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
238579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
239a9643ea8Slogwang }
2402bfe3f2eSlogwang 
2412bfe3f2eSlogwang /**
2422bfe3f2eSlogwang  * Enable traffic flows configured by control plane
2432bfe3f2eSlogwang  *
244579bf1e2Sjfb8856606  * @param dev
2452bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
2462bfe3f2eSlogwang  * @param dev
2472bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
2482bfe3f2eSlogwang  *
2492bfe3f2eSlogwang  * @return
250579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
2512bfe3f2eSlogwang  */
2522bfe3f2eSlogwang int
253579bf1e2Sjfb8856606 mlx5_traffic_enable(struct rte_eth_dev *dev)
2542bfe3f2eSlogwang {
255579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
2562bfe3f2eSlogwang 	struct rte_flow_item_eth bcast = {
2572bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
2582bfe3f2eSlogwang 	};
2592bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_spec = {
2602bfe3f2eSlogwang 		.dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
2612bfe3f2eSlogwang 	};
2622bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_mask = {
2632bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\x00\x00\x00\x00",
2642bfe3f2eSlogwang 	};
2652bfe3f2eSlogwang 	struct rte_flow_item_eth unicast = {
2662bfe3f2eSlogwang 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
2672bfe3f2eSlogwang 	};
2682bfe3f2eSlogwang 	struct rte_flow_item_eth unicast_mask = {
2692bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
2702bfe3f2eSlogwang 	};
2712bfe3f2eSlogwang 	const unsigned int vlan_filter_n = priv->vlan_filter_n;
2722bfe3f2eSlogwang 	const struct ether_addr cmp = {
2732bfe3f2eSlogwang 		.addr_bytes = "\x00\x00\x00\x00\x00\x00",
2742bfe3f2eSlogwang 	};
2752bfe3f2eSlogwang 	unsigned int i;
2762bfe3f2eSlogwang 	unsigned int j;
2772bfe3f2eSlogwang 	int ret;
2782bfe3f2eSlogwang 
2792bfe3f2eSlogwang 	if (priv->isolated)
2802bfe3f2eSlogwang 		return 0;
2812bfe3f2eSlogwang 	if (dev->data->promiscuous) {
2822bfe3f2eSlogwang 		struct rte_flow_item_eth promisc = {
2832bfe3f2eSlogwang 			.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
2842bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
2852bfe3f2eSlogwang 			.type = 0,
2862bfe3f2eSlogwang 		};
2872bfe3f2eSlogwang 
288579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &promisc, &promisc);
289579bf1e2Sjfb8856606 		if (ret)
290579bf1e2Sjfb8856606 			goto error;
2912bfe3f2eSlogwang 	}
2922bfe3f2eSlogwang 	if (dev->data->all_multicast) {
2932bfe3f2eSlogwang 		struct rte_flow_item_eth multicast = {
2942bfe3f2eSlogwang 			.dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
2952bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
2962bfe3f2eSlogwang 			.type = 0,
2972bfe3f2eSlogwang 		};
2982bfe3f2eSlogwang 
299579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &multicast, &multicast);
300579bf1e2Sjfb8856606 		if (ret)
301579bf1e2Sjfb8856606 			goto error;
3022bfe3f2eSlogwang 	} else {
3032bfe3f2eSlogwang 		/* Add broadcast/multicast flows. */
3042bfe3f2eSlogwang 		for (i = 0; i != vlan_filter_n; ++i) {
3052bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[i];
3062bfe3f2eSlogwang 
3072bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
3082bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
3092bfe3f2eSlogwang 			};
310579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
311579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
3122bfe3f2eSlogwang 
3132bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast,
3142bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
3152bfe3f2eSlogwang 			if (ret)
3162bfe3f2eSlogwang 				goto error;
3172bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec,
3182bfe3f2eSlogwang 						  &ipv6_multi_mask,
3192bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
3202bfe3f2eSlogwang 			if (ret)
3212bfe3f2eSlogwang 				goto error;
3222bfe3f2eSlogwang 		}
3232bfe3f2eSlogwang 		if (!vlan_filter_n) {
3242bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &bcast, &bcast);
3252bfe3f2eSlogwang 			if (ret)
3262bfe3f2eSlogwang 				goto error;
3272bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec,
3282bfe3f2eSlogwang 					     &ipv6_multi_mask);
3292bfe3f2eSlogwang 			if (ret)
3302bfe3f2eSlogwang 				goto error;
3312bfe3f2eSlogwang 		}
3322bfe3f2eSlogwang 	}
3332bfe3f2eSlogwang 	/* Add MAC address flows. */
3342bfe3f2eSlogwang 	for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) {
3352bfe3f2eSlogwang 		struct ether_addr *mac = &dev->data->mac_addrs[i];
3362bfe3f2eSlogwang 
3372bfe3f2eSlogwang 		if (!memcmp(mac, &cmp, sizeof(*mac)))
3382bfe3f2eSlogwang 			continue;
3392bfe3f2eSlogwang 		memcpy(&unicast.dst.addr_bytes,
3402bfe3f2eSlogwang 		       mac->addr_bytes,
3412bfe3f2eSlogwang 		       ETHER_ADDR_LEN);
3422bfe3f2eSlogwang 		for (j = 0; j != vlan_filter_n; ++j) {
3432bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[j];
3442bfe3f2eSlogwang 
3452bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
3462bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
3472bfe3f2eSlogwang 			};
348579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
349579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
3502bfe3f2eSlogwang 
3512bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &unicast,
3522bfe3f2eSlogwang 						  &unicast_mask,
3532bfe3f2eSlogwang 						  &vlan_spec,
3542bfe3f2eSlogwang 						  &vlan_mask);
3552bfe3f2eSlogwang 			if (ret)
3562bfe3f2eSlogwang 				goto error;
3572bfe3f2eSlogwang 		}
3582bfe3f2eSlogwang 		if (!vlan_filter_n) {
359579bf1e2Sjfb8856606 			ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask);
3602bfe3f2eSlogwang 			if (ret)
3612bfe3f2eSlogwang 				goto error;
3622bfe3f2eSlogwang 		}
3632bfe3f2eSlogwang 	}
3642bfe3f2eSlogwang 	return 0;
3652bfe3f2eSlogwang error:
366579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
367579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
368579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
369579bf1e2Sjfb8856606 	return -rte_errno;
3702bfe3f2eSlogwang }
3712bfe3f2eSlogwang 
3722bfe3f2eSlogwang 
3732bfe3f2eSlogwang /**
3742bfe3f2eSlogwang  * Disable traffic flows configured by control plane
3752bfe3f2eSlogwang  *
3762bfe3f2eSlogwang  * @param dev
377579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
3782bfe3f2eSlogwang  */
379579bf1e2Sjfb8856606 void
380579bf1e2Sjfb8856606 mlx5_traffic_disable(struct rte_eth_dev *dev)
3812bfe3f2eSlogwang {
382579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
3832bfe3f2eSlogwang 
384579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
3852bfe3f2eSlogwang }
3862bfe3f2eSlogwang 
3872bfe3f2eSlogwang /**
3882bfe3f2eSlogwang  * Restart traffic flows configured by control plane
3892bfe3f2eSlogwang  *
3902bfe3f2eSlogwang  * @param dev
391579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
3922bfe3f2eSlogwang  *
3932bfe3f2eSlogwang  * @return
394579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
3952bfe3f2eSlogwang  */
3962bfe3f2eSlogwang int
3972bfe3f2eSlogwang mlx5_traffic_restart(struct rte_eth_dev *dev)
3982bfe3f2eSlogwang {
399579bf1e2Sjfb8856606 	if (dev->data->dev_started) {
400579bf1e2Sjfb8856606 		mlx5_traffic_disable(dev);
401579bf1e2Sjfb8856606 		return mlx5_traffic_enable(dev);
402579bf1e2Sjfb8856606 	}
4032bfe3f2eSlogwang 	return 0;
4042bfe3f2eSlogwang }
405