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