xref: /f-stack/dpdk/drivers/net/mlx5/mlx5_trigger.c (revision 4418919f)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2a9643ea8Slogwang  * Copyright 2015 6WIND S.A.
3d30ea906Sjfb8856606  * Copyright 2015 Mellanox Technologies, Ltd
4a9643ea8Slogwang  */
5d30ea906Sjfb8856606 
62bfe3f2eSlogwang #include <unistd.h>
7a9643ea8Slogwang 
8a9643ea8Slogwang #include <rte_ether.h>
9d30ea906Sjfb8856606 #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 {
261646932aSjfb8856606 	struct mlx5_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 {
451646932aSjfb8856606 	struct mlx5_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;
54*4418919fSjohnjiang 		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
55*4418919fSjohnjiang 			txq_ctrl->obj = mlx5_txq_obj_new
56*4418919fSjohnjiang 				(dev, i, MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN);
57*4418919fSjohnjiang 		} else {
582bfe3f2eSlogwang 			txq_alloc_elts(txq_ctrl);
59*4418919fSjohnjiang 			txq_ctrl->obj = mlx5_txq_obj_new
60*4418919fSjohnjiang 				(dev, i, MLX5_TXQ_OBJ_TYPE_IBV);
61*4418919fSjohnjiang 		}
62*4418919fSjohnjiang 		if (!txq_ctrl->obj) {
63579bf1e2Sjfb8856606 			rte_errno = ENOMEM;
642bfe3f2eSlogwang 			goto error;
652bfe3f2eSlogwang 		}
662bfe3f2eSlogwang 	}
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 {
861646932aSjfb8856606 	struct mlx5_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 {
1051646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
1062bfe3f2eSlogwang 	unsigned int i;
1072bfe3f2eSlogwang 	int ret = 0;
108*4418919fSjohnjiang 	enum mlx5_rxq_obj_type obj_type = MLX5_RXQ_OBJ_TYPE_IBV;
109*4418919fSjohnjiang 	struct mlx5_rxq_data *rxq = NULL;
1102bfe3f2eSlogwang 
111*4418919fSjohnjiang 	for (i = 0; i < priv->rxqs_n; ++i) {
112*4418919fSjohnjiang 		rxq = (*priv->rxqs)[i];
113*4418919fSjohnjiang 
114*4418919fSjohnjiang 		if (rxq && rxq->lro) {
115*4418919fSjohnjiang 			obj_type =  MLX5_RXQ_OBJ_TYPE_DEVX_RQ;
116*4418919fSjohnjiang 			break;
117*4418919fSjohnjiang 		}
118*4418919fSjohnjiang 	}
119d30ea906Sjfb8856606 	/* Allocate/reuse/resize mempool for Multi-Packet RQ. */
120d30ea906Sjfb8856606 	if (mlx5_mprq_alloc_mp(dev)) {
121d30ea906Sjfb8856606 		/* Should not release Rx queues but return immediately. */
122d30ea906Sjfb8856606 		return -rte_errno;
123d30ea906Sjfb8856606 	}
1242bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i) {
125579bf1e2Sjfb8856606 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i);
126d30ea906Sjfb8856606 		struct rte_mempool *mp;
1272bfe3f2eSlogwang 
1282bfe3f2eSlogwang 		if (!rxq_ctrl)
1292bfe3f2eSlogwang 			continue;
130*4418919fSjohnjiang 		if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) {
131*4418919fSjohnjiang 			rxq_ctrl->obj = mlx5_rxq_obj_new
132*4418919fSjohnjiang 				(dev, i, MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN);
133*4418919fSjohnjiang 			if (!rxq_ctrl->obj)
134*4418919fSjohnjiang 				goto error;
135*4418919fSjohnjiang 			continue;
136*4418919fSjohnjiang 		}
137d30ea906Sjfb8856606 		/* Pre-register Rx mempool. */
138d30ea906Sjfb8856606 		mp = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ?
139d30ea906Sjfb8856606 		     rxq_ctrl->rxq.mprq_mp : rxq_ctrl->rxq.mp;
140d30ea906Sjfb8856606 		DRV_LOG(DEBUG,
141d30ea906Sjfb8856606 			"port %u Rx queue %u registering"
142d30ea906Sjfb8856606 			" mp %s having %u chunks",
143*4418919fSjohnjiang 			dev->data->port_id, rxq_ctrl->rxq.idx,
144d30ea906Sjfb8856606 			mp->name, mp->nb_mem_chunks);
145d30ea906Sjfb8856606 		mlx5_mr_update_mp(dev, &rxq_ctrl->rxq.mr_ctrl, mp);
1462bfe3f2eSlogwang 		ret = rxq_alloc_elts(rxq_ctrl);
1472bfe3f2eSlogwang 		if (ret)
1482bfe3f2eSlogwang 			goto error;
149*4418919fSjohnjiang 		rxq_ctrl->obj = mlx5_rxq_obj_new(dev, i, obj_type);
150*4418919fSjohnjiang 		if (!rxq_ctrl->obj)
1512bfe3f2eSlogwang 			goto error;
152*4418919fSjohnjiang 		if (obj_type == MLX5_RXQ_OBJ_TYPE_IBV)
153*4418919fSjohnjiang 			rxq_ctrl->wqn = rxq_ctrl->obj->wq->wq_num;
154*4418919fSjohnjiang 		else if (obj_type == MLX5_RXQ_OBJ_TYPE_DEVX_RQ)
155*4418919fSjohnjiang 			rxq_ctrl->wqn = rxq_ctrl->obj->rq->id;
1562bfe3f2eSlogwang 	}
157579bf1e2Sjfb8856606 	return 0;
1582bfe3f2eSlogwang error:
159579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
160579bf1e2Sjfb8856606 	do {
161579bf1e2Sjfb8856606 		mlx5_rxq_release(dev, i);
162579bf1e2Sjfb8856606 	} while (i-- != 0);
163579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
164579bf1e2Sjfb8856606 	return -rte_errno;
1652bfe3f2eSlogwang }
1662bfe3f2eSlogwang 
167a9643ea8Slogwang /**
168*4418919fSjohnjiang  * Binds Tx queues to Rx queues for hairpin.
169*4418919fSjohnjiang  *
170*4418919fSjohnjiang  * Binds Tx queues to the target Rx queues.
171*4418919fSjohnjiang  *
172*4418919fSjohnjiang  * @param dev
173*4418919fSjohnjiang  *   Pointer to Ethernet device structure.
174*4418919fSjohnjiang  *
175*4418919fSjohnjiang  * @return
176*4418919fSjohnjiang  *   0 on success, a negative errno value otherwise and rte_errno is set.
177*4418919fSjohnjiang  */
178*4418919fSjohnjiang static int
179*4418919fSjohnjiang mlx5_hairpin_bind(struct rte_eth_dev *dev)
180*4418919fSjohnjiang {
181*4418919fSjohnjiang 	struct mlx5_priv *priv = dev->data->dev_private;
182*4418919fSjohnjiang 	struct mlx5_devx_modify_sq_attr sq_attr = { 0 };
183*4418919fSjohnjiang 	struct mlx5_devx_modify_rq_attr rq_attr = { 0 };
184*4418919fSjohnjiang 	struct mlx5_txq_ctrl *txq_ctrl;
185*4418919fSjohnjiang 	struct mlx5_rxq_ctrl *rxq_ctrl;
186*4418919fSjohnjiang 	struct mlx5_devx_obj *sq;
187*4418919fSjohnjiang 	struct mlx5_devx_obj *rq;
188*4418919fSjohnjiang 	unsigned int i;
189*4418919fSjohnjiang 	int ret = 0;
190*4418919fSjohnjiang 
191*4418919fSjohnjiang 	for (i = 0; i != priv->txqs_n; ++i) {
192*4418919fSjohnjiang 		txq_ctrl = mlx5_txq_get(dev, i);
193*4418919fSjohnjiang 		if (!txq_ctrl)
194*4418919fSjohnjiang 			continue;
195*4418919fSjohnjiang 		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
196*4418919fSjohnjiang 			mlx5_txq_release(dev, i);
197*4418919fSjohnjiang 			continue;
198*4418919fSjohnjiang 		}
199*4418919fSjohnjiang 		if (!txq_ctrl->obj) {
200*4418919fSjohnjiang 			rte_errno = ENOMEM;
201*4418919fSjohnjiang 			DRV_LOG(ERR, "port %u no txq object found: %d",
202*4418919fSjohnjiang 				dev->data->port_id, i);
203*4418919fSjohnjiang 			mlx5_txq_release(dev, i);
204*4418919fSjohnjiang 			return -rte_errno;
205*4418919fSjohnjiang 		}
206*4418919fSjohnjiang 		sq = txq_ctrl->obj->sq;
207*4418919fSjohnjiang 		rxq_ctrl = mlx5_rxq_get(dev,
208*4418919fSjohnjiang 					txq_ctrl->hairpin_conf.peers[0].queue);
209*4418919fSjohnjiang 		if (!rxq_ctrl) {
210*4418919fSjohnjiang 			mlx5_txq_release(dev, i);
211*4418919fSjohnjiang 			rte_errno = EINVAL;
212*4418919fSjohnjiang 			DRV_LOG(ERR, "port %u no rxq object found: %d",
213*4418919fSjohnjiang 				dev->data->port_id,
214*4418919fSjohnjiang 				txq_ctrl->hairpin_conf.peers[0].queue);
215*4418919fSjohnjiang 			return -rte_errno;
216*4418919fSjohnjiang 		}
217*4418919fSjohnjiang 		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
218*4418919fSjohnjiang 		    rxq_ctrl->hairpin_conf.peers[0].queue != i) {
219*4418919fSjohnjiang 			rte_errno = ENOMEM;
220*4418919fSjohnjiang 			DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
221*4418919fSjohnjiang 				"Rx queue %d", dev->data->port_id,
222*4418919fSjohnjiang 				i, txq_ctrl->hairpin_conf.peers[0].queue);
223*4418919fSjohnjiang 			goto error;
224*4418919fSjohnjiang 		}
225*4418919fSjohnjiang 		rq = rxq_ctrl->obj->rq;
226*4418919fSjohnjiang 		if (!rq) {
227*4418919fSjohnjiang 			rte_errno = ENOMEM;
228*4418919fSjohnjiang 			DRV_LOG(ERR, "port %u hairpin no matching rxq: %d",
229*4418919fSjohnjiang 				dev->data->port_id,
230*4418919fSjohnjiang 				txq_ctrl->hairpin_conf.peers[0].queue);
231*4418919fSjohnjiang 			goto error;
232*4418919fSjohnjiang 		}
233*4418919fSjohnjiang 		sq_attr.state = MLX5_SQC_STATE_RDY;
234*4418919fSjohnjiang 		sq_attr.sq_state = MLX5_SQC_STATE_RST;
235*4418919fSjohnjiang 		sq_attr.hairpin_peer_rq = rq->id;
236*4418919fSjohnjiang 		sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
237*4418919fSjohnjiang 		ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr);
238*4418919fSjohnjiang 		if (ret)
239*4418919fSjohnjiang 			goto error;
240*4418919fSjohnjiang 		rq_attr.state = MLX5_SQC_STATE_RDY;
241*4418919fSjohnjiang 		rq_attr.rq_state = MLX5_SQC_STATE_RST;
242*4418919fSjohnjiang 		rq_attr.hairpin_peer_sq = sq->id;
243*4418919fSjohnjiang 		rq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
244*4418919fSjohnjiang 		ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr);
245*4418919fSjohnjiang 		if (ret)
246*4418919fSjohnjiang 			goto error;
247*4418919fSjohnjiang 		mlx5_txq_release(dev, i);
248*4418919fSjohnjiang 		mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
249*4418919fSjohnjiang 	}
250*4418919fSjohnjiang 	return 0;
251*4418919fSjohnjiang error:
252*4418919fSjohnjiang 	mlx5_txq_release(dev, i);
253*4418919fSjohnjiang 	mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
254*4418919fSjohnjiang 	return -rte_errno;
255*4418919fSjohnjiang }
256*4418919fSjohnjiang 
257*4418919fSjohnjiang /**
258a9643ea8Slogwang  * DPDK callback to start the device.
259a9643ea8Slogwang  *
260a9643ea8Slogwang  * Simulate device start by attaching all configured flows.
261a9643ea8Slogwang  *
262a9643ea8Slogwang  * @param dev
263a9643ea8Slogwang  *   Pointer to Ethernet device structure.
264a9643ea8Slogwang  *
265a9643ea8Slogwang  * @return
266579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
267a9643ea8Slogwang  */
268a9643ea8Slogwang int
269a9643ea8Slogwang mlx5_dev_start(struct rte_eth_dev *dev)
270a9643ea8Slogwang {
2711646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
272579bf1e2Sjfb8856606 	int ret;
273a9643ea8Slogwang 
274579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id);
275*4418919fSjohnjiang 	if (dev->data->nb_rx_queues > 0) {
276*4418919fSjohnjiang 		ret = mlx5_dev_configure_rss_reta(dev);
277*4418919fSjohnjiang 		if (ret) {
278*4418919fSjohnjiang 			DRV_LOG(ERR, "port %u reta config failed: %s",
279*4418919fSjohnjiang 				dev->data->port_id, strerror(rte_errno));
280*4418919fSjohnjiang 			return -rte_errno;
281*4418919fSjohnjiang 		}
282*4418919fSjohnjiang 	}
283579bf1e2Sjfb8856606 	ret = mlx5_txq_start(dev);
284579bf1e2Sjfb8856606 	if (ret) {
285579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Tx queue allocation failed: %s",
286579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
287579bf1e2Sjfb8856606 		return -rte_errno;
288a9643ea8Slogwang 	}
289579bf1e2Sjfb8856606 	ret = mlx5_rxq_start(dev);
290579bf1e2Sjfb8856606 	if (ret) {
291579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Rx queue allocation failed: %s",
292579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
293579bf1e2Sjfb8856606 		mlx5_txq_stop(dev);
294579bf1e2Sjfb8856606 		return -rte_errno;
2952bfe3f2eSlogwang 	}
296*4418919fSjohnjiang 	ret = mlx5_hairpin_bind(dev);
297*4418919fSjohnjiang 	if (ret) {
298*4418919fSjohnjiang 		DRV_LOG(ERR, "port %u hairpin binding failed: %s",
299*4418919fSjohnjiang 			dev->data->port_id, strerror(rte_errno));
300*4418919fSjohnjiang 		mlx5_txq_stop(dev);
301*4418919fSjohnjiang 		return -rte_errno;
302*4418919fSjohnjiang 	}
303579bf1e2Sjfb8856606 	dev->data->dev_started = 1;
304579bf1e2Sjfb8856606 	ret = mlx5_rx_intr_vec_enable(dev);
305579bf1e2Sjfb8856606 	if (ret) {
306579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Rx interrupt vector creation failed",
3072bfe3f2eSlogwang 			dev->data->port_id);
3082bfe3f2eSlogwang 		goto error;
3092bfe3f2eSlogwang 	}
3104b05018fSfengbojiang 	mlx5_stats_init(dev);
311579bf1e2Sjfb8856606 	ret = mlx5_traffic_enable(dev);
312579bf1e2Sjfb8856606 	if (ret) {
313579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set defaults flows",
314579bf1e2Sjfb8856606 			dev->data->port_id);
315579bf1e2Sjfb8856606 		goto error;
316579bf1e2Sjfb8856606 	}
317579bf1e2Sjfb8856606 	ret = mlx5_flow_start(dev, &priv->flows);
318579bf1e2Sjfb8856606 	if (ret) {
319579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set flows",
320579bf1e2Sjfb8856606 			dev->data->port_id);
321579bf1e2Sjfb8856606 		goto error;
322579bf1e2Sjfb8856606 	}
323*4418919fSjohnjiang 	rte_wmb();
324579bf1e2Sjfb8856606 	dev->tx_pkt_burst = mlx5_select_tx_function(dev);
325579bf1e2Sjfb8856606 	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
326*4418919fSjohnjiang 	/* Enable datapath on secondary process. */
327*4418919fSjohnjiang 	mlx5_mp_req_start_rxtx(dev);
328579bf1e2Sjfb8856606 	mlx5_dev_interrupt_handler_install(dev);
3292bfe3f2eSlogwang 	return 0;
3302bfe3f2eSlogwang error:
331579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
3322bfe3f2eSlogwang 	/* Rollback. */
3332bfe3f2eSlogwang 	dev->data->dev_started = 0;
334579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
335579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
336579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
337579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
338579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
339579bf1e2Sjfb8856606 	return -rte_errno;
340a9643ea8Slogwang }
341a9643ea8Slogwang 
342a9643ea8Slogwang /**
343a9643ea8Slogwang  * DPDK callback to stop the device.
344a9643ea8Slogwang  *
345a9643ea8Slogwang  * Simulate device stop by detaching all configured flows.
346a9643ea8Slogwang  *
347a9643ea8Slogwang  * @param dev
348a9643ea8Slogwang  *   Pointer to Ethernet device structure.
349a9643ea8Slogwang  */
350a9643ea8Slogwang void
351a9643ea8Slogwang mlx5_dev_stop(struct rte_eth_dev *dev)
352a9643ea8Slogwang {
3531646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
354a9643ea8Slogwang 
3552bfe3f2eSlogwang 	dev->data->dev_started = 0;
3562bfe3f2eSlogwang 	/* Prevent crashes when queues are still in use. */
3572bfe3f2eSlogwang 	dev->rx_pkt_burst = removed_rx_burst;
3582bfe3f2eSlogwang 	dev->tx_pkt_burst = removed_tx_burst;
3592bfe3f2eSlogwang 	rte_wmb();
360*4418919fSjohnjiang 	/* Disable datapath on secondary process. */
361*4418919fSjohnjiang 	mlx5_mp_req_stop_rxtx(dev);
3622bfe3f2eSlogwang 	usleep(1000 * priv->rxqs_n);
363579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id);
364579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
365579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
366579bf1e2Sjfb8856606 	mlx5_rx_intr_vec_disable(dev);
367579bf1e2Sjfb8856606 	mlx5_dev_interrupt_handler_uninstall(dev);
368579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
369579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
370a9643ea8Slogwang }
3712bfe3f2eSlogwang 
3722bfe3f2eSlogwang /**
3732bfe3f2eSlogwang  * Enable traffic flows configured by control plane
3742bfe3f2eSlogwang  *
375579bf1e2Sjfb8856606  * @param dev
3762bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
3772bfe3f2eSlogwang  * @param dev
3782bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
3792bfe3f2eSlogwang  *
3802bfe3f2eSlogwang  * @return
381579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
3822bfe3f2eSlogwang  */
3832bfe3f2eSlogwang int
384579bf1e2Sjfb8856606 mlx5_traffic_enable(struct rte_eth_dev *dev)
3852bfe3f2eSlogwang {
3861646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
3872bfe3f2eSlogwang 	struct rte_flow_item_eth bcast = {
3882bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
3892bfe3f2eSlogwang 	};
3902bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_spec = {
3912bfe3f2eSlogwang 		.dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
3922bfe3f2eSlogwang 	};
3932bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_mask = {
3942bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\x00\x00\x00\x00",
3952bfe3f2eSlogwang 	};
3962bfe3f2eSlogwang 	struct rte_flow_item_eth unicast = {
3972bfe3f2eSlogwang 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
3982bfe3f2eSlogwang 	};
3992bfe3f2eSlogwang 	struct rte_flow_item_eth unicast_mask = {
4002bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
4012bfe3f2eSlogwang 	};
4022bfe3f2eSlogwang 	const unsigned int vlan_filter_n = priv->vlan_filter_n;
403*4418919fSjohnjiang 	const struct rte_ether_addr cmp = {
4042bfe3f2eSlogwang 		.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4052bfe3f2eSlogwang 	};
4062bfe3f2eSlogwang 	unsigned int i;
4072bfe3f2eSlogwang 	unsigned int j;
4082bfe3f2eSlogwang 	int ret;
4092bfe3f2eSlogwang 
410*4418919fSjohnjiang 	/*
411*4418919fSjohnjiang 	 * Hairpin txq default flow should be created no matter if it is
412*4418919fSjohnjiang 	 * isolation mode. Or else all the packets to be sent will be sent
413*4418919fSjohnjiang 	 * out directly without the TX flow actions, e.g. encapsulation.
414*4418919fSjohnjiang 	 */
415*4418919fSjohnjiang 	for (i = 0; i != priv->txqs_n; ++i) {
416*4418919fSjohnjiang 		struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i);
417*4418919fSjohnjiang 		if (!txq_ctrl)
418*4418919fSjohnjiang 			continue;
419*4418919fSjohnjiang 		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
420*4418919fSjohnjiang 			ret = mlx5_ctrl_flow_source_queue(dev, i);
421*4418919fSjohnjiang 			if (ret) {
422*4418919fSjohnjiang 				mlx5_txq_release(dev, i);
423*4418919fSjohnjiang 				goto error;
424*4418919fSjohnjiang 			}
425*4418919fSjohnjiang 		}
426*4418919fSjohnjiang 		mlx5_txq_release(dev, i);
427*4418919fSjohnjiang 	}
428*4418919fSjohnjiang 	if (priv->config.dv_esw_en && !priv->config.vf) {
429*4418919fSjohnjiang 		if (mlx5_flow_create_esw_table_zero_flow(dev))
430*4418919fSjohnjiang 			priv->fdb_def_rule = 1;
431*4418919fSjohnjiang 		else
432*4418919fSjohnjiang 			DRV_LOG(INFO, "port %u FDB default rule cannot be"
433*4418919fSjohnjiang 				" configured - only Eswitch group 0 flows are"
434*4418919fSjohnjiang 				" supported.", dev->data->port_id);
435*4418919fSjohnjiang 	}
4362bfe3f2eSlogwang 	if (priv->isolated)
4372bfe3f2eSlogwang 		return 0;
4382bfe3f2eSlogwang 	if (dev->data->promiscuous) {
4392bfe3f2eSlogwang 		struct rte_flow_item_eth promisc = {
4402bfe3f2eSlogwang 			.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4412bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4422bfe3f2eSlogwang 			.type = 0,
4432bfe3f2eSlogwang 		};
4442bfe3f2eSlogwang 
445579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &promisc, &promisc);
446579bf1e2Sjfb8856606 		if (ret)
447579bf1e2Sjfb8856606 			goto error;
4482bfe3f2eSlogwang 	}
4492bfe3f2eSlogwang 	if (dev->data->all_multicast) {
4502bfe3f2eSlogwang 		struct rte_flow_item_eth multicast = {
4512bfe3f2eSlogwang 			.dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
4522bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4532bfe3f2eSlogwang 			.type = 0,
4542bfe3f2eSlogwang 		};
4552bfe3f2eSlogwang 
456579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &multicast, &multicast);
457579bf1e2Sjfb8856606 		if (ret)
458579bf1e2Sjfb8856606 			goto error;
4592bfe3f2eSlogwang 	} else {
4602bfe3f2eSlogwang 		/* Add broadcast/multicast flows. */
4612bfe3f2eSlogwang 		for (i = 0; i != vlan_filter_n; ++i) {
4622bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[i];
4632bfe3f2eSlogwang 
4642bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
4652bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
4662bfe3f2eSlogwang 			};
467579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
468579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
4692bfe3f2eSlogwang 
4702bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast,
4712bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
4722bfe3f2eSlogwang 			if (ret)
4732bfe3f2eSlogwang 				goto error;
4742bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec,
4752bfe3f2eSlogwang 						  &ipv6_multi_mask,
4762bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
4772bfe3f2eSlogwang 			if (ret)
4782bfe3f2eSlogwang 				goto error;
4792bfe3f2eSlogwang 		}
4802bfe3f2eSlogwang 		if (!vlan_filter_n) {
4812bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &bcast, &bcast);
4822bfe3f2eSlogwang 			if (ret)
4832bfe3f2eSlogwang 				goto error;
4842bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec,
4852bfe3f2eSlogwang 					     &ipv6_multi_mask);
4862bfe3f2eSlogwang 			if (ret)
4872bfe3f2eSlogwang 				goto error;
4882bfe3f2eSlogwang 		}
4892bfe3f2eSlogwang 	}
4902bfe3f2eSlogwang 	/* Add MAC address flows. */
4912bfe3f2eSlogwang 	for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) {
492*4418919fSjohnjiang 		struct rte_ether_addr *mac = &dev->data->mac_addrs[i];
4932bfe3f2eSlogwang 
4942bfe3f2eSlogwang 		if (!memcmp(mac, &cmp, sizeof(*mac)))
4952bfe3f2eSlogwang 			continue;
4962bfe3f2eSlogwang 		memcpy(&unicast.dst.addr_bytes,
4972bfe3f2eSlogwang 		       mac->addr_bytes,
498*4418919fSjohnjiang 		       RTE_ETHER_ADDR_LEN);
4992bfe3f2eSlogwang 		for (j = 0; j != vlan_filter_n; ++j) {
5002bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[j];
5012bfe3f2eSlogwang 
5022bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
5032bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
5042bfe3f2eSlogwang 			};
505579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
506579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
5072bfe3f2eSlogwang 
5082bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &unicast,
5092bfe3f2eSlogwang 						  &unicast_mask,
5102bfe3f2eSlogwang 						  &vlan_spec,
5112bfe3f2eSlogwang 						  &vlan_mask);
5122bfe3f2eSlogwang 			if (ret)
5132bfe3f2eSlogwang 				goto error;
5142bfe3f2eSlogwang 		}
5152bfe3f2eSlogwang 		if (!vlan_filter_n) {
516579bf1e2Sjfb8856606 			ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask);
5172bfe3f2eSlogwang 			if (ret)
5182bfe3f2eSlogwang 				goto error;
5192bfe3f2eSlogwang 		}
5202bfe3f2eSlogwang 	}
5212bfe3f2eSlogwang 	return 0;
5222bfe3f2eSlogwang error:
523579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
524579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
525579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
526579bf1e2Sjfb8856606 	return -rte_errno;
5272bfe3f2eSlogwang }
5282bfe3f2eSlogwang 
5292bfe3f2eSlogwang 
5302bfe3f2eSlogwang /**
5312bfe3f2eSlogwang  * Disable traffic flows configured by control plane
5322bfe3f2eSlogwang  *
5332bfe3f2eSlogwang  * @param dev
534579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
5352bfe3f2eSlogwang  */
536579bf1e2Sjfb8856606 void
537579bf1e2Sjfb8856606 mlx5_traffic_disable(struct rte_eth_dev *dev)
5382bfe3f2eSlogwang {
5391646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
5402bfe3f2eSlogwang 
541579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
5422bfe3f2eSlogwang }
5432bfe3f2eSlogwang 
5442bfe3f2eSlogwang /**
5452bfe3f2eSlogwang  * Restart traffic flows configured by control plane
5462bfe3f2eSlogwang  *
5472bfe3f2eSlogwang  * @param dev
548579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
5492bfe3f2eSlogwang  *
5502bfe3f2eSlogwang  * @return
551579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
5522bfe3f2eSlogwang  */
5532bfe3f2eSlogwang int
5542bfe3f2eSlogwang mlx5_traffic_restart(struct rte_eth_dev *dev)
5552bfe3f2eSlogwang {
556579bf1e2Sjfb8856606 	if (dev->data->dev_started) {
557579bf1e2Sjfb8856606 		mlx5_traffic_disable(dev);
558579bf1e2Sjfb8856606 		return mlx5_traffic_enable(dev);
559579bf1e2Sjfb8856606 	}
5602bfe3f2eSlogwang 	return 0;
5612bfe3f2eSlogwang }
562