xref: /f-stack/dpdk/drivers/net/mlx5/mlx5_trigger.c (revision 0c6bd470)
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;
544418919fSjohnjiang 		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
554418919fSjohnjiang 			txq_ctrl->obj = mlx5_txq_obj_new
564418919fSjohnjiang 				(dev, i, MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN);
574418919fSjohnjiang 		} else {
582bfe3f2eSlogwang 			txq_alloc_elts(txq_ctrl);
594418919fSjohnjiang 			txq_ctrl->obj = mlx5_txq_obj_new
604418919fSjohnjiang 				(dev, i, MLX5_TXQ_OBJ_TYPE_IBV);
614418919fSjohnjiang 		}
624418919fSjohnjiang 		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;
1084418919fSjohnjiang 	enum mlx5_rxq_obj_type obj_type = MLX5_RXQ_OBJ_TYPE_IBV;
1094418919fSjohnjiang 	struct mlx5_rxq_data *rxq = NULL;
1102bfe3f2eSlogwang 
1114418919fSjohnjiang 	for (i = 0; i < priv->rxqs_n; ++i) {
1124418919fSjohnjiang 		rxq = (*priv->rxqs)[i];
1134418919fSjohnjiang 
1144418919fSjohnjiang 		if (rxq && rxq->lro) {
1154418919fSjohnjiang 			obj_type =  MLX5_RXQ_OBJ_TYPE_DEVX_RQ;
1164418919fSjohnjiang 			break;
1174418919fSjohnjiang 		}
1184418919fSjohnjiang 	}
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;
1304418919fSjohnjiang 		if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) {
1314418919fSjohnjiang 			rxq_ctrl->obj = mlx5_rxq_obj_new
1324418919fSjohnjiang 				(dev, i, MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN);
1334418919fSjohnjiang 			if (!rxq_ctrl->obj)
1344418919fSjohnjiang 				goto error;
1354418919fSjohnjiang 			continue;
1364418919fSjohnjiang 		}
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",
1434418919fSjohnjiang 			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;
1494418919fSjohnjiang 		rxq_ctrl->obj = mlx5_rxq_obj_new(dev, i, obj_type);
1504418919fSjohnjiang 		if (!rxq_ctrl->obj)
1512bfe3f2eSlogwang 			goto error;
1524418919fSjohnjiang 		if (obj_type == MLX5_RXQ_OBJ_TYPE_IBV)
1534418919fSjohnjiang 			rxq_ctrl->wqn = rxq_ctrl->obj->wq->wq_num;
1544418919fSjohnjiang 		else if (obj_type == MLX5_RXQ_OBJ_TYPE_DEVX_RQ)
1554418919fSjohnjiang 			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 /**
1684418919fSjohnjiang  * Binds Tx queues to Rx queues for hairpin.
1694418919fSjohnjiang  *
1704418919fSjohnjiang  * Binds Tx queues to the target Rx queues.
1714418919fSjohnjiang  *
1724418919fSjohnjiang  * @param dev
1734418919fSjohnjiang  *   Pointer to Ethernet device structure.
1744418919fSjohnjiang  *
1754418919fSjohnjiang  * @return
1764418919fSjohnjiang  *   0 on success, a negative errno value otherwise and rte_errno is set.
1774418919fSjohnjiang  */
1784418919fSjohnjiang static int
1794418919fSjohnjiang mlx5_hairpin_bind(struct rte_eth_dev *dev)
1804418919fSjohnjiang {
1814418919fSjohnjiang 	struct mlx5_priv *priv = dev->data->dev_private;
1824418919fSjohnjiang 	struct mlx5_devx_modify_sq_attr sq_attr = { 0 };
1834418919fSjohnjiang 	struct mlx5_devx_modify_rq_attr rq_attr = { 0 };
1844418919fSjohnjiang 	struct mlx5_txq_ctrl *txq_ctrl;
1854418919fSjohnjiang 	struct mlx5_rxq_ctrl *rxq_ctrl;
1864418919fSjohnjiang 	struct mlx5_devx_obj *sq;
1874418919fSjohnjiang 	struct mlx5_devx_obj *rq;
1884418919fSjohnjiang 	unsigned int i;
1894418919fSjohnjiang 	int ret = 0;
1904418919fSjohnjiang 
1914418919fSjohnjiang 	for (i = 0; i != priv->txqs_n; ++i) {
1924418919fSjohnjiang 		txq_ctrl = mlx5_txq_get(dev, i);
1934418919fSjohnjiang 		if (!txq_ctrl)
1944418919fSjohnjiang 			continue;
1954418919fSjohnjiang 		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
1964418919fSjohnjiang 			mlx5_txq_release(dev, i);
1974418919fSjohnjiang 			continue;
1984418919fSjohnjiang 		}
1994418919fSjohnjiang 		if (!txq_ctrl->obj) {
2004418919fSjohnjiang 			rte_errno = ENOMEM;
2014418919fSjohnjiang 			DRV_LOG(ERR, "port %u no txq object found: %d",
2024418919fSjohnjiang 				dev->data->port_id, i);
2034418919fSjohnjiang 			mlx5_txq_release(dev, i);
2044418919fSjohnjiang 			return -rte_errno;
2054418919fSjohnjiang 		}
2064418919fSjohnjiang 		sq = txq_ctrl->obj->sq;
2074418919fSjohnjiang 		rxq_ctrl = mlx5_rxq_get(dev,
2084418919fSjohnjiang 					txq_ctrl->hairpin_conf.peers[0].queue);
2094418919fSjohnjiang 		if (!rxq_ctrl) {
2104418919fSjohnjiang 			mlx5_txq_release(dev, i);
2114418919fSjohnjiang 			rte_errno = EINVAL;
2124418919fSjohnjiang 			DRV_LOG(ERR, "port %u no rxq object found: %d",
2134418919fSjohnjiang 				dev->data->port_id,
2144418919fSjohnjiang 				txq_ctrl->hairpin_conf.peers[0].queue);
2154418919fSjohnjiang 			return -rte_errno;
2164418919fSjohnjiang 		}
2174418919fSjohnjiang 		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
2184418919fSjohnjiang 		    rxq_ctrl->hairpin_conf.peers[0].queue != i) {
2194418919fSjohnjiang 			rte_errno = ENOMEM;
2204418919fSjohnjiang 			DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
2214418919fSjohnjiang 				"Rx queue %d", dev->data->port_id,
2224418919fSjohnjiang 				i, txq_ctrl->hairpin_conf.peers[0].queue);
2234418919fSjohnjiang 			goto error;
2244418919fSjohnjiang 		}
2254418919fSjohnjiang 		rq = rxq_ctrl->obj->rq;
2264418919fSjohnjiang 		if (!rq) {
2274418919fSjohnjiang 			rte_errno = ENOMEM;
2284418919fSjohnjiang 			DRV_LOG(ERR, "port %u hairpin no matching rxq: %d",
2294418919fSjohnjiang 				dev->data->port_id,
2304418919fSjohnjiang 				txq_ctrl->hairpin_conf.peers[0].queue);
2314418919fSjohnjiang 			goto error;
2324418919fSjohnjiang 		}
2334418919fSjohnjiang 		sq_attr.state = MLX5_SQC_STATE_RDY;
2344418919fSjohnjiang 		sq_attr.sq_state = MLX5_SQC_STATE_RST;
2354418919fSjohnjiang 		sq_attr.hairpin_peer_rq = rq->id;
2364418919fSjohnjiang 		sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
2374418919fSjohnjiang 		ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr);
2384418919fSjohnjiang 		if (ret)
2394418919fSjohnjiang 			goto error;
2404418919fSjohnjiang 		rq_attr.state = MLX5_SQC_STATE_RDY;
2414418919fSjohnjiang 		rq_attr.rq_state = MLX5_SQC_STATE_RST;
2424418919fSjohnjiang 		rq_attr.hairpin_peer_sq = sq->id;
2434418919fSjohnjiang 		rq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
2444418919fSjohnjiang 		ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr);
2454418919fSjohnjiang 		if (ret)
2464418919fSjohnjiang 			goto error;
2474418919fSjohnjiang 		mlx5_txq_release(dev, i);
2484418919fSjohnjiang 		mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
2494418919fSjohnjiang 	}
2504418919fSjohnjiang 	return 0;
2514418919fSjohnjiang error:
2524418919fSjohnjiang 	mlx5_txq_release(dev, i);
2534418919fSjohnjiang 	mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
2544418919fSjohnjiang 	return -rte_errno;
2554418919fSjohnjiang }
2564418919fSjohnjiang 
2574418919fSjohnjiang /**
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);
2754418919fSjohnjiang 	if (dev->data->nb_rx_queues > 0) {
2764418919fSjohnjiang 		ret = mlx5_dev_configure_rss_reta(dev);
2774418919fSjohnjiang 		if (ret) {
2784418919fSjohnjiang 			DRV_LOG(ERR, "port %u reta config failed: %s",
2794418919fSjohnjiang 				dev->data->port_id, strerror(rte_errno));
2804418919fSjohnjiang 			return -rte_errno;
2814418919fSjohnjiang 		}
2824418919fSjohnjiang 	}
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 	}
2964418919fSjohnjiang 	ret = mlx5_hairpin_bind(dev);
2974418919fSjohnjiang 	if (ret) {
2984418919fSjohnjiang 		DRV_LOG(ERR, "port %u hairpin binding failed: %s",
2994418919fSjohnjiang 			dev->data->port_id, strerror(rte_errno));
3004418919fSjohnjiang 		mlx5_txq_stop(dev);
3014418919fSjohnjiang 		return -rte_errno;
3024418919fSjohnjiang 	}
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 	}
317*0c6bd470Sfengbojiang 	/* Set a mask and offset of dynamic metadata flows into Rx queues*/
318*0c6bd470Sfengbojiang 	mlx5_flow_rxq_dynf_metadata_set(dev);
319579bf1e2Sjfb8856606 	ret = mlx5_flow_start(dev, &priv->flows);
320579bf1e2Sjfb8856606 	if (ret) {
321579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set flows",
322579bf1e2Sjfb8856606 			dev->data->port_id);
323579bf1e2Sjfb8856606 		goto error;
324579bf1e2Sjfb8856606 	}
3254418919fSjohnjiang 	rte_wmb();
326579bf1e2Sjfb8856606 	dev->tx_pkt_burst = mlx5_select_tx_function(dev);
327579bf1e2Sjfb8856606 	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
3284418919fSjohnjiang 	/* Enable datapath on secondary process. */
3294418919fSjohnjiang 	mlx5_mp_req_start_rxtx(dev);
330*0c6bd470Sfengbojiang 	if (priv->sh->intr_handle.fd >= 0) {
331*0c6bd470Sfengbojiang 		priv->sh->port[priv->ibv_port - 1].ih_port_id =
332*0c6bd470Sfengbojiang 					(uint32_t)dev->data->port_id;
333*0c6bd470Sfengbojiang 	} else {
334*0c6bd470Sfengbojiang 		DRV_LOG(INFO, "port %u starts without LSC and RMV interrupts.",
335*0c6bd470Sfengbojiang 			dev->data->port_id);
336*0c6bd470Sfengbojiang 		dev->data->dev_conf.intr_conf.lsc = 0;
337*0c6bd470Sfengbojiang 		dev->data->dev_conf.intr_conf.rmv = 0;
338*0c6bd470Sfengbojiang 	}
339*0c6bd470Sfengbojiang 	if (priv->sh->intr_handle_devx.fd >= 0)
340*0c6bd470Sfengbojiang 		priv->sh->port[priv->ibv_port - 1].devx_ih_port_id =
341*0c6bd470Sfengbojiang 					(uint32_t)dev->data->port_id;
3422bfe3f2eSlogwang 	return 0;
3432bfe3f2eSlogwang error:
344579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
3452bfe3f2eSlogwang 	/* Rollback. */
3462bfe3f2eSlogwang 	dev->data->dev_started = 0;
347579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
348579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
349579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
350579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
351579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
352579bf1e2Sjfb8856606 	return -rte_errno;
353a9643ea8Slogwang }
354a9643ea8Slogwang 
355a9643ea8Slogwang /**
356a9643ea8Slogwang  * DPDK callback to stop the device.
357a9643ea8Slogwang  *
358a9643ea8Slogwang  * Simulate device stop by detaching all configured flows.
359a9643ea8Slogwang  *
360a9643ea8Slogwang  * @param dev
361a9643ea8Slogwang  *   Pointer to Ethernet device structure.
362a9643ea8Slogwang  */
363a9643ea8Slogwang void
364a9643ea8Slogwang mlx5_dev_stop(struct rte_eth_dev *dev)
365a9643ea8Slogwang {
3661646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
367a9643ea8Slogwang 
3682bfe3f2eSlogwang 	dev->data->dev_started = 0;
3692bfe3f2eSlogwang 	/* Prevent crashes when queues are still in use. */
3702bfe3f2eSlogwang 	dev->rx_pkt_burst = removed_rx_burst;
3712bfe3f2eSlogwang 	dev->tx_pkt_burst = removed_tx_burst;
3722bfe3f2eSlogwang 	rte_wmb();
3734418919fSjohnjiang 	/* Disable datapath on secondary process. */
3744418919fSjohnjiang 	mlx5_mp_req_stop_rxtx(dev);
3752bfe3f2eSlogwang 	usleep(1000 * priv->rxqs_n);
376579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id);
377579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
378579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
379579bf1e2Sjfb8856606 	mlx5_rx_intr_vec_disable(dev);
380*0c6bd470Sfengbojiang 	priv->sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
381*0c6bd470Sfengbojiang 	priv->sh->port[priv->ibv_port - 1].devx_ih_port_id = RTE_MAX_ETHPORTS;
382579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
383579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
384a9643ea8Slogwang }
3852bfe3f2eSlogwang 
3862bfe3f2eSlogwang /**
3872bfe3f2eSlogwang  * Enable traffic flows configured by control plane
3882bfe3f2eSlogwang  *
389579bf1e2Sjfb8856606  * @param dev
3902bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
3912bfe3f2eSlogwang  * @param dev
3922bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
3932bfe3f2eSlogwang  *
3942bfe3f2eSlogwang  * @return
395579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
3962bfe3f2eSlogwang  */
3972bfe3f2eSlogwang int
398579bf1e2Sjfb8856606 mlx5_traffic_enable(struct rte_eth_dev *dev)
3992bfe3f2eSlogwang {
4001646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
4012bfe3f2eSlogwang 	struct rte_flow_item_eth bcast = {
4022bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
4032bfe3f2eSlogwang 	};
4042bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_spec = {
4052bfe3f2eSlogwang 		.dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
4062bfe3f2eSlogwang 	};
4072bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_mask = {
4082bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\x00\x00\x00\x00",
4092bfe3f2eSlogwang 	};
4102bfe3f2eSlogwang 	struct rte_flow_item_eth unicast = {
4112bfe3f2eSlogwang 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4122bfe3f2eSlogwang 	};
4132bfe3f2eSlogwang 	struct rte_flow_item_eth unicast_mask = {
4142bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
4152bfe3f2eSlogwang 	};
4162bfe3f2eSlogwang 	const unsigned int vlan_filter_n = priv->vlan_filter_n;
4174418919fSjohnjiang 	const struct rte_ether_addr cmp = {
4182bfe3f2eSlogwang 		.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4192bfe3f2eSlogwang 	};
4202bfe3f2eSlogwang 	unsigned int i;
4212bfe3f2eSlogwang 	unsigned int j;
4222bfe3f2eSlogwang 	int ret;
4232bfe3f2eSlogwang 
4244418919fSjohnjiang 	/*
4254418919fSjohnjiang 	 * Hairpin txq default flow should be created no matter if it is
4264418919fSjohnjiang 	 * isolation mode. Or else all the packets to be sent will be sent
4274418919fSjohnjiang 	 * out directly without the TX flow actions, e.g. encapsulation.
4284418919fSjohnjiang 	 */
4294418919fSjohnjiang 	for (i = 0; i != priv->txqs_n; ++i) {
4304418919fSjohnjiang 		struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i);
4314418919fSjohnjiang 		if (!txq_ctrl)
4324418919fSjohnjiang 			continue;
4334418919fSjohnjiang 		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
4344418919fSjohnjiang 			ret = mlx5_ctrl_flow_source_queue(dev, i);
4354418919fSjohnjiang 			if (ret) {
4364418919fSjohnjiang 				mlx5_txq_release(dev, i);
4374418919fSjohnjiang 				goto error;
4384418919fSjohnjiang 			}
4394418919fSjohnjiang 		}
4404418919fSjohnjiang 		mlx5_txq_release(dev, i);
4414418919fSjohnjiang 	}
4424418919fSjohnjiang 	if (priv->config.dv_esw_en && !priv->config.vf) {
4434418919fSjohnjiang 		if (mlx5_flow_create_esw_table_zero_flow(dev))
4444418919fSjohnjiang 			priv->fdb_def_rule = 1;
4454418919fSjohnjiang 		else
4464418919fSjohnjiang 			DRV_LOG(INFO, "port %u FDB default rule cannot be"
4474418919fSjohnjiang 				" configured - only Eswitch group 0 flows are"
4484418919fSjohnjiang 				" supported.", dev->data->port_id);
4494418919fSjohnjiang 	}
4502bfe3f2eSlogwang 	if (priv->isolated)
4512bfe3f2eSlogwang 		return 0;
4522bfe3f2eSlogwang 	if (dev->data->promiscuous) {
4532bfe3f2eSlogwang 		struct rte_flow_item_eth promisc = {
4542bfe3f2eSlogwang 			.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4552bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4562bfe3f2eSlogwang 			.type = 0,
4572bfe3f2eSlogwang 		};
4582bfe3f2eSlogwang 
459579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &promisc, &promisc);
460579bf1e2Sjfb8856606 		if (ret)
461579bf1e2Sjfb8856606 			goto error;
4622bfe3f2eSlogwang 	}
4632bfe3f2eSlogwang 	if (dev->data->all_multicast) {
4642bfe3f2eSlogwang 		struct rte_flow_item_eth multicast = {
4652bfe3f2eSlogwang 			.dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
4662bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
4672bfe3f2eSlogwang 			.type = 0,
4682bfe3f2eSlogwang 		};
4692bfe3f2eSlogwang 
470579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &multicast, &multicast);
471579bf1e2Sjfb8856606 		if (ret)
472579bf1e2Sjfb8856606 			goto error;
4732bfe3f2eSlogwang 	} else {
4742bfe3f2eSlogwang 		/* Add broadcast/multicast flows. */
4752bfe3f2eSlogwang 		for (i = 0; i != vlan_filter_n; ++i) {
4762bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[i];
4772bfe3f2eSlogwang 
4782bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
4792bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
4802bfe3f2eSlogwang 			};
481579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
482579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
4832bfe3f2eSlogwang 
4842bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast,
4852bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
4862bfe3f2eSlogwang 			if (ret)
4872bfe3f2eSlogwang 				goto error;
4882bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec,
4892bfe3f2eSlogwang 						  &ipv6_multi_mask,
4902bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
4912bfe3f2eSlogwang 			if (ret)
4922bfe3f2eSlogwang 				goto error;
4932bfe3f2eSlogwang 		}
4942bfe3f2eSlogwang 		if (!vlan_filter_n) {
4952bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &bcast, &bcast);
4962bfe3f2eSlogwang 			if (ret)
4972bfe3f2eSlogwang 				goto error;
4982bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec,
4992bfe3f2eSlogwang 					     &ipv6_multi_mask);
5002bfe3f2eSlogwang 			if (ret)
5012bfe3f2eSlogwang 				goto error;
5022bfe3f2eSlogwang 		}
5032bfe3f2eSlogwang 	}
5042bfe3f2eSlogwang 	/* Add MAC address flows. */
5052bfe3f2eSlogwang 	for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) {
5064418919fSjohnjiang 		struct rte_ether_addr *mac = &dev->data->mac_addrs[i];
5072bfe3f2eSlogwang 
5082bfe3f2eSlogwang 		if (!memcmp(mac, &cmp, sizeof(*mac)))
5092bfe3f2eSlogwang 			continue;
5102bfe3f2eSlogwang 		memcpy(&unicast.dst.addr_bytes,
5112bfe3f2eSlogwang 		       mac->addr_bytes,
5124418919fSjohnjiang 		       RTE_ETHER_ADDR_LEN);
5132bfe3f2eSlogwang 		for (j = 0; j != vlan_filter_n; ++j) {
5142bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[j];
5152bfe3f2eSlogwang 
5162bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
5172bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
5182bfe3f2eSlogwang 			};
519579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
520579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
5212bfe3f2eSlogwang 
5222bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &unicast,
5232bfe3f2eSlogwang 						  &unicast_mask,
5242bfe3f2eSlogwang 						  &vlan_spec,
5252bfe3f2eSlogwang 						  &vlan_mask);
5262bfe3f2eSlogwang 			if (ret)
5272bfe3f2eSlogwang 				goto error;
5282bfe3f2eSlogwang 		}
5292bfe3f2eSlogwang 		if (!vlan_filter_n) {
530579bf1e2Sjfb8856606 			ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask);
5312bfe3f2eSlogwang 			if (ret)
5322bfe3f2eSlogwang 				goto error;
5332bfe3f2eSlogwang 		}
5342bfe3f2eSlogwang 	}
5352bfe3f2eSlogwang 	return 0;
5362bfe3f2eSlogwang error:
537579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
538579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
539579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
540579bf1e2Sjfb8856606 	return -rte_errno;
5412bfe3f2eSlogwang }
5422bfe3f2eSlogwang 
5432bfe3f2eSlogwang 
5442bfe3f2eSlogwang /**
5452bfe3f2eSlogwang  * Disable traffic flows configured by control plane
5462bfe3f2eSlogwang  *
5472bfe3f2eSlogwang  * @param dev
548579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
5492bfe3f2eSlogwang  */
550579bf1e2Sjfb8856606 void
551579bf1e2Sjfb8856606 mlx5_traffic_disable(struct rte_eth_dev *dev)
5522bfe3f2eSlogwang {
5531646932aSjfb8856606 	struct mlx5_priv *priv = dev->data->dev_private;
5542bfe3f2eSlogwang 
555579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
5562bfe3f2eSlogwang }
5572bfe3f2eSlogwang 
5582bfe3f2eSlogwang /**
5592bfe3f2eSlogwang  * Restart traffic flows configured by control plane
5602bfe3f2eSlogwang  *
5612bfe3f2eSlogwang  * @param dev
562579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
5632bfe3f2eSlogwang  *
5642bfe3f2eSlogwang  * @return
565579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
5662bfe3f2eSlogwang  */
5672bfe3f2eSlogwang int
5682bfe3f2eSlogwang mlx5_traffic_restart(struct rte_eth_dev *dev)
5692bfe3f2eSlogwang {
570579bf1e2Sjfb8856606 	if (dev->data->dev_started) {
571579bf1e2Sjfb8856606 		mlx5_traffic_disable(dev);
572579bf1e2Sjfb8856606 		return mlx5_traffic_enable(dev);
573579bf1e2Sjfb8856606 	}
5742bfe3f2eSlogwang 	return 0;
5752bfe3f2eSlogwang }
576