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