xref: /f-stack/dpdk/drivers/net/mlx5/mlx5_trigger.c (revision 2bfe3f2e)
1a9643ea8Slogwang /*-
2a9643ea8Slogwang  *   BSD LICENSE
3a9643ea8Slogwang  *
4a9643ea8Slogwang  *   Copyright 2015 6WIND S.A.
5a9643ea8Slogwang  *   Copyright 2015 Mellanox.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  *   Redistribution and use in source and binary forms, with or without
8a9643ea8Slogwang  *   modification, are permitted provided that the following conditions
9a9643ea8Slogwang  *   are met:
10a9643ea8Slogwang  *
11a9643ea8Slogwang  *     * Redistributions of source code must retain the above copyright
12a9643ea8Slogwang  *       notice, this list of conditions and the following disclaimer.
13a9643ea8Slogwang  *     * Redistributions in binary form must reproduce the above copyright
14a9643ea8Slogwang  *       notice, this list of conditions and the following disclaimer in
15a9643ea8Slogwang  *       the documentation and/or other materials provided with the
16a9643ea8Slogwang  *       distribution.
17a9643ea8Slogwang  *     * Neither the name of 6WIND S.A. nor the names of its
18a9643ea8Slogwang  *       contributors may be used to endorse or promote products derived
19a9643ea8Slogwang  *       from this software without specific prior written permission.
20a9643ea8Slogwang  *
21a9643ea8Slogwang  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22a9643ea8Slogwang  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23a9643ea8Slogwang  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24a9643ea8Slogwang  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25a9643ea8Slogwang  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26a9643ea8Slogwang  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27a9643ea8Slogwang  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28a9643ea8Slogwang  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29a9643ea8Slogwang  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30a9643ea8Slogwang  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31a9643ea8Slogwang  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32a9643ea8Slogwang  */
33*2bfe3f2eSlogwang #include <unistd.h>
34a9643ea8Slogwang 
35a9643ea8Slogwang #include <rte_ether.h>
36a9643ea8Slogwang #include <rte_ethdev.h>
37a9643ea8Slogwang #include <rte_interrupts.h>
38a9643ea8Slogwang #include <rte_alarm.h>
39a9643ea8Slogwang 
40a9643ea8Slogwang #include "mlx5.h"
41a9643ea8Slogwang #include "mlx5_rxtx.h"
42a9643ea8Slogwang #include "mlx5_utils.h"
43a9643ea8Slogwang 
44*2bfe3f2eSlogwang static void
45*2bfe3f2eSlogwang priv_txq_stop(struct priv *priv)
46*2bfe3f2eSlogwang {
47*2bfe3f2eSlogwang 	unsigned int i;
48*2bfe3f2eSlogwang 
49*2bfe3f2eSlogwang 	for (i = 0; i != priv->txqs_n; ++i)
50*2bfe3f2eSlogwang 		mlx5_priv_txq_release(priv, i);
51*2bfe3f2eSlogwang }
52*2bfe3f2eSlogwang 
53*2bfe3f2eSlogwang static int
54*2bfe3f2eSlogwang priv_txq_start(struct priv *priv)
55*2bfe3f2eSlogwang {
56*2bfe3f2eSlogwang 	unsigned int i;
57*2bfe3f2eSlogwang 	int ret = 0;
58*2bfe3f2eSlogwang 
59*2bfe3f2eSlogwang 	/* Add memory regions to Tx queues. */
60*2bfe3f2eSlogwang 	for (i = 0; i != priv->txqs_n; ++i) {
61*2bfe3f2eSlogwang 		unsigned int idx = 0;
62*2bfe3f2eSlogwang 		struct mlx5_mr *mr;
63*2bfe3f2eSlogwang 		struct mlx5_txq_ctrl *txq_ctrl = mlx5_priv_txq_get(priv, i);
64*2bfe3f2eSlogwang 
65*2bfe3f2eSlogwang 		if (!txq_ctrl)
66*2bfe3f2eSlogwang 			continue;
67*2bfe3f2eSlogwang 		LIST_FOREACH(mr, &priv->mr, next) {
68*2bfe3f2eSlogwang 			priv_txq_mp2mr_reg(priv, &txq_ctrl->txq, mr->mp, idx++);
69*2bfe3f2eSlogwang 			if (idx == MLX5_PMD_TX_MP_CACHE)
70*2bfe3f2eSlogwang 				break;
71*2bfe3f2eSlogwang 		}
72*2bfe3f2eSlogwang 		txq_alloc_elts(txq_ctrl);
73*2bfe3f2eSlogwang 		txq_ctrl->ibv = mlx5_priv_txq_ibv_new(priv, i);
74*2bfe3f2eSlogwang 		if (!txq_ctrl->ibv) {
75*2bfe3f2eSlogwang 			ret = ENOMEM;
76*2bfe3f2eSlogwang 			goto error;
77*2bfe3f2eSlogwang 		}
78*2bfe3f2eSlogwang 	}
79*2bfe3f2eSlogwang 	return -ret;
80*2bfe3f2eSlogwang error:
81*2bfe3f2eSlogwang 	priv_txq_stop(priv);
82*2bfe3f2eSlogwang 	return -ret;
83*2bfe3f2eSlogwang }
84*2bfe3f2eSlogwang 
85*2bfe3f2eSlogwang static void
86*2bfe3f2eSlogwang priv_rxq_stop(struct priv *priv)
87*2bfe3f2eSlogwang {
88*2bfe3f2eSlogwang 	unsigned int i;
89*2bfe3f2eSlogwang 
90*2bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i)
91*2bfe3f2eSlogwang 		mlx5_priv_rxq_release(priv, i);
92*2bfe3f2eSlogwang }
93*2bfe3f2eSlogwang 
94*2bfe3f2eSlogwang static int
95*2bfe3f2eSlogwang priv_rxq_start(struct priv *priv)
96*2bfe3f2eSlogwang {
97*2bfe3f2eSlogwang 	unsigned int i;
98*2bfe3f2eSlogwang 	int ret = 0;
99*2bfe3f2eSlogwang 
100*2bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i) {
101*2bfe3f2eSlogwang 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_priv_rxq_get(priv, i);
102*2bfe3f2eSlogwang 
103*2bfe3f2eSlogwang 		if (!rxq_ctrl)
104*2bfe3f2eSlogwang 			continue;
105*2bfe3f2eSlogwang 		ret = rxq_alloc_elts(rxq_ctrl);
106*2bfe3f2eSlogwang 		if (ret)
107*2bfe3f2eSlogwang 			goto error;
108*2bfe3f2eSlogwang 		rxq_ctrl->ibv = mlx5_priv_rxq_ibv_new(priv, i);
109*2bfe3f2eSlogwang 		if (!rxq_ctrl->ibv) {
110*2bfe3f2eSlogwang 			ret = ENOMEM;
111*2bfe3f2eSlogwang 			goto error;
112*2bfe3f2eSlogwang 		}
113*2bfe3f2eSlogwang 	}
114*2bfe3f2eSlogwang 	return -ret;
115*2bfe3f2eSlogwang error:
116*2bfe3f2eSlogwang 	priv_rxq_stop(priv);
117*2bfe3f2eSlogwang 	return -ret;
118*2bfe3f2eSlogwang }
119*2bfe3f2eSlogwang 
120a9643ea8Slogwang /**
121a9643ea8Slogwang  * DPDK callback to start the device.
122a9643ea8Slogwang  *
123a9643ea8Slogwang  * Simulate device start by attaching all configured flows.
124a9643ea8Slogwang  *
125a9643ea8Slogwang  * @param dev
126a9643ea8Slogwang  *   Pointer to Ethernet device structure.
127a9643ea8Slogwang  *
128a9643ea8Slogwang  * @return
129a9643ea8Slogwang  *   0 on success, negative errno value on failure.
130a9643ea8Slogwang  */
131a9643ea8Slogwang int
132a9643ea8Slogwang mlx5_dev_start(struct rte_eth_dev *dev)
133a9643ea8Slogwang {
134a9643ea8Slogwang 	struct priv *priv = dev->data->dev_private;
135*2bfe3f2eSlogwang 	struct mlx5_mr *mr = NULL;
136a9643ea8Slogwang 	int err;
137a9643ea8Slogwang 
138*2bfe3f2eSlogwang 	dev->data->dev_started = 1;
139a9643ea8Slogwang 	priv_lock(priv);
140*2bfe3f2eSlogwang 	err = priv_flow_create_drop_queue(priv);
141*2bfe3f2eSlogwang 	if (err) {
142*2bfe3f2eSlogwang 		ERROR("%p: Drop queue allocation failed: %s",
143*2bfe3f2eSlogwang 		      (void *)dev, strerror(err));
144*2bfe3f2eSlogwang 		goto error;
145a9643ea8Slogwang 	}
146a9643ea8Slogwang 	DEBUG("%p: allocating and configuring hash RX queues", (void *)dev);
147*2bfe3f2eSlogwang 	rte_mempool_walk(mlx5_mp2mr_iter, priv);
148*2bfe3f2eSlogwang 	err = priv_txq_start(priv);
149*2bfe3f2eSlogwang 	if (err) {
150*2bfe3f2eSlogwang 		ERROR("%p: TXQ allocation failed: %s",
151*2bfe3f2eSlogwang 		      (void *)dev, strerror(err));
152*2bfe3f2eSlogwang 		goto error;
153a9643ea8Slogwang 	}
154*2bfe3f2eSlogwang 	err = priv_rxq_start(priv);
155*2bfe3f2eSlogwang 	if (err) {
156*2bfe3f2eSlogwang 		ERROR("%p: RXQ allocation failed: %s",
157*2bfe3f2eSlogwang 		      (void *)dev, strerror(err));
158*2bfe3f2eSlogwang 		goto error;
159*2bfe3f2eSlogwang 	}
160*2bfe3f2eSlogwang 	err = priv_rx_intr_vec_enable(priv);
161*2bfe3f2eSlogwang 	if (err) {
162*2bfe3f2eSlogwang 		ERROR("%p: RX interrupt vector creation failed",
163*2bfe3f2eSlogwang 		      (void *)priv);
164*2bfe3f2eSlogwang 		goto error;
165*2bfe3f2eSlogwang 	}
166*2bfe3f2eSlogwang 	priv_xstats_init(priv);
167*2bfe3f2eSlogwang 	/* Update link status and Tx/Rx callbacks for the first time. */
168*2bfe3f2eSlogwang 	memset(&dev->data->dev_link, 0, sizeof(struct rte_eth_link));
169*2bfe3f2eSlogwang 	INFO("Forcing port %u link to be up", dev->data->port_id);
170*2bfe3f2eSlogwang 	err = priv_force_link_status_change(priv, ETH_LINK_UP);
171*2bfe3f2eSlogwang 	if (err) {
172*2bfe3f2eSlogwang 		DEBUG("Failed to set port %u link to be up",
173*2bfe3f2eSlogwang 		      dev->data->port_id);
174*2bfe3f2eSlogwang 		goto error;
175*2bfe3f2eSlogwang 	}
176a9643ea8Slogwang 	priv_dev_interrupt_handler_install(priv, dev);
177a9643ea8Slogwang 	priv_unlock(priv);
178*2bfe3f2eSlogwang 	return 0;
179*2bfe3f2eSlogwang error:
180*2bfe3f2eSlogwang 	/* Rollback. */
181*2bfe3f2eSlogwang 	dev->data->dev_started = 0;
182*2bfe3f2eSlogwang 	for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr))
183*2bfe3f2eSlogwang 		priv_mr_release(priv, mr);
184*2bfe3f2eSlogwang 	priv_flow_stop(priv, &priv->flows);
185*2bfe3f2eSlogwang 	priv_dev_traffic_disable(priv, dev);
186*2bfe3f2eSlogwang 	priv_txq_stop(priv);
187*2bfe3f2eSlogwang 	priv_rxq_stop(priv);
188*2bfe3f2eSlogwang 	priv_flow_delete_drop_queue(priv);
189*2bfe3f2eSlogwang 	priv_unlock(priv);
190*2bfe3f2eSlogwang 	return err;
191a9643ea8Slogwang }
192a9643ea8Slogwang 
193a9643ea8Slogwang /**
194a9643ea8Slogwang  * DPDK callback to stop the device.
195a9643ea8Slogwang  *
196a9643ea8Slogwang  * Simulate device stop by detaching all configured flows.
197a9643ea8Slogwang  *
198a9643ea8Slogwang  * @param dev
199a9643ea8Slogwang  *   Pointer to Ethernet device structure.
200a9643ea8Slogwang  */
201a9643ea8Slogwang void
202a9643ea8Slogwang mlx5_dev_stop(struct rte_eth_dev *dev)
203a9643ea8Slogwang {
204a9643ea8Slogwang 	struct priv *priv = dev->data->dev_private;
205*2bfe3f2eSlogwang 	struct mlx5_mr *mr;
206a9643ea8Slogwang 
207a9643ea8Slogwang 	priv_lock(priv);
208*2bfe3f2eSlogwang 	dev->data->dev_started = 0;
209*2bfe3f2eSlogwang 	/* Prevent crashes when queues are still in use. */
210*2bfe3f2eSlogwang 	dev->rx_pkt_burst = removed_rx_burst;
211*2bfe3f2eSlogwang 	dev->tx_pkt_burst = removed_tx_burst;
212*2bfe3f2eSlogwang 	rte_wmb();
213*2bfe3f2eSlogwang 	usleep(1000 * priv->rxqs_n);
214a9643ea8Slogwang 	DEBUG("%p: cleaning up and destroying hash RX queues", (void *)dev);
215*2bfe3f2eSlogwang 	priv_flow_stop(priv, &priv->flows);
216*2bfe3f2eSlogwang 	priv_dev_traffic_disable(priv, dev);
217*2bfe3f2eSlogwang 	priv_rx_intr_vec_disable(priv);
218a9643ea8Slogwang 	priv_dev_interrupt_handler_uninstall(priv, dev);
219*2bfe3f2eSlogwang 	priv_txq_stop(priv);
220*2bfe3f2eSlogwang 	priv_rxq_stop(priv);
221*2bfe3f2eSlogwang 	for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr))
222*2bfe3f2eSlogwang 		priv_mr_release(priv, mr);
223*2bfe3f2eSlogwang 	priv_flow_delete_drop_queue(priv);
224a9643ea8Slogwang 	priv_unlock(priv);
225a9643ea8Slogwang }
226*2bfe3f2eSlogwang 
227*2bfe3f2eSlogwang /**
228*2bfe3f2eSlogwang  * Enable traffic flows configured by control plane
229*2bfe3f2eSlogwang  *
230*2bfe3f2eSlogwang  * @param priv
231*2bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
232*2bfe3f2eSlogwang  * @param dev
233*2bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
234*2bfe3f2eSlogwang  *
235*2bfe3f2eSlogwang  * @return
236*2bfe3f2eSlogwang  *   0 on success.
237*2bfe3f2eSlogwang  */
238*2bfe3f2eSlogwang int
239*2bfe3f2eSlogwang priv_dev_traffic_enable(struct priv *priv, struct rte_eth_dev *dev)
240*2bfe3f2eSlogwang {
241*2bfe3f2eSlogwang 	struct rte_flow_item_eth bcast = {
242*2bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
243*2bfe3f2eSlogwang 	};
244*2bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_spec = {
245*2bfe3f2eSlogwang 		.dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
246*2bfe3f2eSlogwang 	};
247*2bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_mask = {
248*2bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\x00\x00\x00\x00",
249*2bfe3f2eSlogwang 	};
250*2bfe3f2eSlogwang 	struct rte_flow_item_eth unicast = {
251*2bfe3f2eSlogwang 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
252*2bfe3f2eSlogwang 	};
253*2bfe3f2eSlogwang 	struct rte_flow_item_eth unicast_mask = {
254*2bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
255*2bfe3f2eSlogwang 	};
256*2bfe3f2eSlogwang 	const unsigned int vlan_filter_n = priv->vlan_filter_n;
257*2bfe3f2eSlogwang 	const struct ether_addr cmp = {
258*2bfe3f2eSlogwang 		.addr_bytes = "\x00\x00\x00\x00\x00\x00",
259*2bfe3f2eSlogwang 	};
260*2bfe3f2eSlogwang 	unsigned int i;
261*2bfe3f2eSlogwang 	unsigned int j;
262*2bfe3f2eSlogwang 	int ret;
263*2bfe3f2eSlogwang 
264*2bfe3f2eSlogwang 	if (priv->isolated)
265*2bfe3f2eSlogwang 		return 0;
266*2bfe3f2eSlogwang 	if (dev->data->promiscuous) {
267*2bfe3f2eSlogwang 		struct rte_flow_item_eth promisc = {
268*2bfe3f2eSlogwang 			.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
269*2bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
270*2bfe3f2eSlogwang 			.type = 0,
271*2bfe3f2eSlogwang 		};
272*2bfe3f2eSlogwang 
273*2bfe3f2eSlogwang 		claim_zero(mlx5_ctrl_flow(dev, &promisc, &promisc));
274*2bfe3f2eSlogwang 		return 0;
275*2bfe3f2eSlogwang 	}
276*2bfe3f2eSlogwang 	if (dev->data->all_multicast) {
277*2bfe3f2eSlogwang 		struct rte_flow_item_eth multicast = {
278*2bfe3f2eSlogwang 			.dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
279*2bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
280*2bfe3f2eSlogwang 			.type = 0,
281*2bfe3f2eSlogwang 		};
282*2bfe3f2eSlogwang 
283*2bfe3f2eSlogwang 		claim_zero(mlx5_ctrl_flow(dev, &multicast, &multicast));
284*2bfe3f2eSlogwang 	} else {
285*2bfe3f2eSlogwang 		/* Add broadcast/multicast flows. */
286*2bfe3f2eSlogwang 		for (i = 0; i != vlan_filter_n; ++i) {
287*2bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[i];
288*2bfe3f2eSlogwang 
289*2bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
290*2bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
291*2bfe3f2eSlogwang 			};
292*2bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_mask = {
293*2bfe3f2eSlogwang 				.tci = 0xffff,
294*2bfe3f2eSlogwang 			};
295*2bfe3f2eSlogwang 
296*2bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast,
297*2bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
298*2bfe3f2eSlogwang 			if (ret)
299*2bfe3f2eSlogwang 				goto error;
300*2bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec,
301*2bfe3f2eSlogwang 						  &ipv6_multi_mask,
302*2bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
303*2bfe3f2eSlogwang 			if (ret)
304*2bfe3f2eSlogwang 				goto error;
305*2bfe3f2eSlogwang 		}
306*2bfe3f2eSlogwang 		if (!vlan_filter_n) {
307*2bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &bcast, &bcast);
308*2bfe3f2eSlogwang 			if (ret)
309*2bfe3f2eSlogwang 				goto error;
310*2bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec,
311*2bfe3f2eSlogwang 					     &ipv6_multi_mask);
312*2bfe3f2eSlogwang 			if (ret)
313*2bfe3f2eSlogwang 				goto error;
314*2bfe3f2eSlogwang 		}
315*2bfe3f2eSlogwang 	}
316*2bfe3f2eSlogwang 	/* Add MAC address flows. */
317*2bfe3f2eSlogwang 	for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) {
318*2bfe3f2eSlogwang 		struct ether_addr *mac = &dev->data->mac_addrs[i];
319*2bfe3f2eSlogwang 
320*2bfe3f2eSlogwang 		if (!memcmp(mac, &cmp, sizeof(*mac)))
321*2bfe3f2eSlogwang 			continue;
322*2bfe3f2eSlogwang 		memcpy(&unicast.dst.addr_bytes,
323*2bfe3f2eSlogwang 		       mac->addr_bytes,
324*2bfe3f2eSlogwang 		       ETHER_ADDR_LEN);
325*2bfe3f2eSlogwang 		for (j = 0; j != vlan_filter_n; ++j) {
326*2bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[j];
327*2bfe3f2eSlogwang 
328*2bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
329*2bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
330*2bfe3f2eSlogwang 			};
331*2bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_mask = {
332*2bfe3f2eSlogwang 				.tci = 0xffff,
333*2bfe3f2eSlogwang 			};
334*2bfe3f2eSlogwang 
335*2bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &unicast,
336*2bfe3f2eSlogwang 						  &unicast_mask,
337*2bfe3f2eSlogwang 						  &vlan_spec,
338*2bfe3f2eSlogwang 						  &vlan_mask);
339*2bfe3f2eSlogwang 			if (ret)
340*2bfe3f2eSlogwang 				goto error;
341*2bfe3f2eSlogwang 		}
342*2bfe3f2eSlogwang 		if (!vlan_filter_n) {
343*2bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &unicast,
344*2bfe3f2eSlogwang 					     &unicast_mask);
345*2bfe3f2eSlogwang 			if (ret)
346*2bfe3f2eSlogwang 				goto error;
347*2bfe3f2eSlogwang 		}
348*2bfe3f2eSlogwang 	}
349*2bfe3f2eSlogwang 	return 0;
350*2bfe3f2eSlogwang error:
351*2bfe3f2eSlogwang 	return rte_errno;
352*2bfe3f2eSlogwang }
353*2bfe3f2eSlogwang 
354*2bfe3f2eSlogwang 
355*2bfe3f2eSlogwang /**
356*2bfe3f2eSlogwang  * Disable traffic flows configured by control plane
357*2bfe3f2eSlogwang  *
358*2bfe3f2eSlogwang  * @param priv
359*2bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
360*2bfe3f2eSlogwang  * @param dev
361*2bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
362*2bfe3f2eSlogwang  *
363*2bfe3f2eSlogwang  * @return
364*2bfe3f2eSlogwang  *   0 on success.
365*2bfe3f2eSlogwang  */
366*2bfe3f2eSlogwang int
367*2bfe3f2eSlogwang priv_dev_traffic_disable(struct priv *priv, struct rte_eth_dev *dev)
368*2bfe3f2eSlogwang {
369*2bfe3f2eSlogwang 	(void)dev;
370*2bfe3f2eSlogwang 	priv_flow_flush(priv, &priv->ctrl_flows);
371*2bfe3f2eSlogwang 	return 0;
372*2bfe3f2eSlogwang }
373*2bfe3f2eSlogwang 
374*2bfe3f2eSlogwang /**
375*2bfe3f2eSlogwang  * Restart traffic flows configured by control plane
376*2bfe3f2eSlogwang  *
377*2bfe3f2eSlogwang  * @param priv
378*2bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
379*2bfe3f2eSlogwang  * @param dev
380*2bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
381*2bfe3f2eSlogwang  *
382*2bfe3f2eSlogwang  * @return
383*2bfe3f2eSlogwang  *   0 on success.
384*2bfe3f2eSlogwang  */
385*2bfe3f2eSlogwang int
386*2bfe3f2eSlogwang priv_dev_traffic_restart(struct priv *priv, struct rte_eth_dev *dev)
387*2bfe3f2eSlogwang {
388*2bfe3f2eSlogwang 	if (dev->data->dev_started) {
389*2bfe3f2eSlogwang 		priv_dev_traffic_disable(priv, dev);
390*2bfe3f2eSlogwang 		priv_dev_traffic_enable(priv, dev);
391*2bfe3f2eSlogwang 	}
392*2bfe3f2eSlogwang 	return 0;
393*2bfe3f2eSlogwang }
394*2bfe3f2eSlogwang 
395*2bfe3f2eSlogwang /**
396*2bfe3f2eSlogwang  * Restart traffic flows configured by control plane
397*2bfe3f2eSlogwang  *
398*2bfe3f2eSlogwang  * @param dev
399*2bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
400*2bfe3f2eSlogwang  *
401*2bfe3f2eSlogwang  * @return
402*2bfe3f2eSlogwang  *   0 on success.
403*2bfe3f2eSlogwang  */
404*2bfe3f2eSlogwang int
405*2bfe3f2eSlogwang mlx5_traffic_restart(struct rte_eth_dev *dev)
406*2bfe3f2eSlogwang {
407*2bfe3f2eSlogwang 	struct priv *priv = dev->data->dev_private;
408*2bfe3f2eSlogwang 
409*2bfe3f2eSlogwang 	priv_lock(priv);
410*2bfe3f2eSlogwang 	priv_dev_traffic_restart(priv, dev);
411*2bfe3f2eSlogwang 	priv_unlock(priv);
412*2bfe3f2eSlogwang 	return 0;
413*2bfe3f2eSlogwang }
414