18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2e60fbd5bSAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 4e60fbd5bSAdrien Mazarguil */ 58fd92a66SOlivier Matz 63f2fe392SNélio Laranjeiro #include <unistd.h> 7e60fbd5bSAdrien Mazarguil 8e60fbd5bSAdrien Mazarguil #include <rte_ether.h> 9ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 10198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 11198a3c33SNelio Laranjeiro #include <rte_alarm.h> 12e60fbd5bSAdrien Mazarguil 13e60fbd5bSAdrien Mazarguil #include "mlx5.h" 14e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 15e60fbd5bSAdrien Mazarguil #include "mlx5_utils.h" 16e60fbd5bSAdrien Mazarguil 17fb732b0aSNélio Laranjeiro /** 18fb732b0aSNélio Laranjeiro * Stop traffic on Tx queues. 19fb732b0aSNélio Laranjeiro * 20fb732b0aSNélio Laranjeiro * @param dev 21fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 22fb732b0aSNélio Laranjeiro */ 236e78005aSNélio Laranjeiro static void 24af4f09f2SNélio Laranjeiro mlx5_txq_stop(struct rte_eth_dev *dev) 256e78005aSNélio Laranjeiro { 26dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 276e78005aSNélio Laranjeiro unsigned int i; 286e78005aSNélio Laranjeiro 296e78005aSNélio Laranjeiro for (i = 0; i != priv->txqs_n; ++i) 30af4f09f2SNélio Laranjeiro mlx5_txq_release(dev, i); 316e78005aSNélio Laranjeiro } 326e78005aSNélio Laranjeiro 33fb732b0aSNélio Laranjeiro /** 34fb732b0aSNélio Laranjeiro * Start traffic on Tx queues. 35fb732b0aSNélio Laranjeiro * 36fb732b0aSNélio Laranjeiro * @param dev 37fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 38fb732b0aSNélio Laranjeiro * 39fb732b0aSNélio Laranjeiro * @return 40a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 41fb732b0aSNélio Laranjeiro */ 426e78005aSNélio Laranjeiro static int 43af4f09f2SNélio Laranjeiro mlx5_txq_start(struct rte_eth_dev *dev) 446e78005aSNélio Laranjeiro { 45dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 466e78005aSNélio Laranjeiro unsigned int i; 47a6d83b6aSNélio Laranjeiro int ret; 486e78005aSNélio Laranjeiro 496e78005aSNélio Laranjeiro for (i = 0; i != priv->txqs_n; ++i) { 50af4f09f2SNélio Laranjeiro struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i); 516e78005aSNélio Laranjeiro 526e78005aSNélio Laranjeiro if (!txq_ctrl) 536e78005aSNélio Laranjeiro continue; 54ae18a1aeSOri Kam if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) { 55ae18a1aeSOri Kam txq_ctrl->obj = mlx5_txq_obj_new 56ae18a1aeSOri Kam (dev, i, MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN); 57ae18a1aeSOri Kam } else { 586e78005aSNélio Laranjeiro txq_alloc_elts(txq_ctrl); 59ae18a1aeSOri Kam txq_ctrl->obj = mlx5_txq_obj_new 60ae18a1aeSOri Kam (dev, i, MLX5_TXQ_OBJ_TYPE_IBV); 61ae18a1aeSOri Kam } 62894c4a8eSOri Kam if (!txq_ctrl->obj) { 63a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 646e78005aSNélio Laranjeiro goto error; 656e78005aSNélio Laranjeiro } 666e78005aSNélio Laranjeiro } 67a6d83b6aSNélio Laranjeiro return 0; 686e78005aSNélio Laranjeiro error: 69a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 7024f653a7SYongseok Koh do { 7124f653a7SYongseok Koh mlx5_txq_release(dev, i); 7224f653a7SYongseok Koh } while (i-- != 0); 73a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 74a6d83b6aSNélio Laranjeiro return -rte_errno; 756e78005aSNélio Laranjeiro } 766e78005aSNélio Laranjeiro 77fb732b0aSNélio Laranjeiro /** 78fb732b0aSNélio Laranjeiro * Stop traffic on Rx queues. 79fb732b0aSNélio Laranjeiro * 80fb732b0aSNélio Laranjeiro * @param dev 81fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 82fb732b0aSNélio Laranjeiro */ 83a1366b1aSNélio Laranjeiro static void 84af4f09f2SNélio Laranjeiro mlx5_rxq_stop(struct rte_eth_dev *dev) 85a1366b1aSNélio Laranjeiro { 86dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 87a1366b1aSNélio Laranjeiro unsigned int i; 88a1366b1aSNélio Laranjeiro 89a1366b1aSNélio Laranjeiro for (i = 0; i != priv->rxqs_n; ++i) 90af4f09f2SNélio Laranjeiro mlx5_rxq_release(dev, i); 91a1366b1aSNélio Laranjeiro } 92a1366b1aSNélio Laranjeiro 93fb732b0aSNélio Laranjeiro /** 94fb732b0aSNélio Laranjeiro * Start traffic on Rx queues. 95fb732b0aSNélio Laranjeiro * 96fb732b0aSNélio Laranjeiro * @param dev 97fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 98fb732b0aSNélio Laranjeiro * 99fb732b0aSNélio Laranjeiro * @return 100a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 101fb732b0aSNélio Laranjeiro */ 102a1366b1aSNélio Laranjeiro static int 103af4f09f2SNélio Laranjeiro mlx5_rxq_start(struct rte_eth_dev *dev) 104a1366b1aSNélio Laranjeiro { 105dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 106a1366b1aSNélio Laranjeiro unsigned int i; 107a1366b1aSNélio Laranjeiro int ret = 0; 10817ed314cSMatan Azrad enum mlx5_rxq_obj_type obj_type = MLX5_RXQ_OBJ_TYPE_IBV; 109bf864e82STonghao Zhang struct mlx5_rxq_data *rxq = NULL; 110a1366b1aSNélio Laranjeiro 11117ed314cSMatan Azrad for (i = 0; i < priv->rxqs_n; ++i) { 112bf864e82STonghao Zhang rxq = (*priv->rxqs)[i]; 113bf864e82STonghao Zhang 114bf864e82STonghao Zhang if (rxq && rxq->lro) { 11517ed314cSMatan Azrad obj_type = MLX5_RXQ_OBJ_TYPE_DEVX_RQ; 11617ed314cSMatan Azrad break; 11717ed314cSMatan Azrad } 11817ed314cSMatan Azrad } 1197d6bf6b8SYongseok Koh /* Allocate/reuse/resize mempool for Multi-Packet RQ. */ 12024f653a7SYongseok Koh if (mlx5_mprq_alloc_mp(dev)) { 12124f653a7SYongseok Koh /* Should not release Rx queues but return immediately. */ 12224f653a7SYongseok Koh return -rte_errno; 12324f653a7SYongseok Koh } 124a1366b1aSNélio Laranjeiro for (i = 0; i != priv->rxqs_n; ++i) { 125af4f09f2SNélio Laranjeiro struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i); 126974f1e7eSYongseok Koh struct rte_mempool *mp; 127a1366b1aSNélio Laranjeiro 128a1366b1aSNélio Laranjeiro if (!rxq_ctrl) 129a1366b1aSNélio Laranjeiro continue; 130e79c9be9SOri Kam if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) { 131e79c9be9SOri Kam rxq_ctrl->obj = mlx5_rxq_obj_new 132e79c9be9SOri Kam (dev, i, MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN); 133e79c9be9SOri Kam if (!rxq_ctrl->obj) 134e79c9be9SOri Kam goto error; 135e79c9be9SOri Kam continue; 136e79c9be9SOri Kam } 137974f1e7eSYongseok Koh /* Pre-register Rx mempool. */ 1387d6bf6b8SYongseok Koh mp = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ? 1397d6bf6b8SYongseok Koh rxq_ctrl->rxq.mprq_mp : rxq_ctrl->rxq.mp; 140974f1e7eSYongseok Koh DRV_LOG(DEBUG, 141974f1e7eSYongseok Koh "port %u Rx queue %u registering" 142974f1e7eSYongseok Koh " mp %s having %u chunks", 143d5c900d1SYongseok Koh dev->data->port_id, rxq_ctrl->rxq.idx, 144974f1e7eSYongseok Koh mp->name, mp->nb_mem_chunks); 145974f1e7eSYongseok Koh mlx5_mr_update_mp(dev, &rxq_ctrl->rxq.mr_ctrl, mp); 146a1366b1aSNélio Laranjeiro ret = rxq_alloc_elts(rxq_ctrl); 147a1366b1aSNélio Laranjeiro if (ret) 148a1366b1aSNélio Laranjeiro goto error; 149940f0a1dSDekel Peled rxq_ctrl->obj = mlx5_rxq_obj_new(dev, i, obj_type); 15093403560SDekel Peled if (!rxq_ctrl->obj) 151a1366b1aSNélio Laranjeiro goto error; 152940f0a1dSDekel Peled if (obj_type == MLX5_RXQ_OBJ_TYPE_IBV) 15393403560SDekel Peled rxq_ctrl->wqn = rxq_ctrl->obj->wq->wq_num; 154940f0a1dSDekel Peled else if (obj_type == MLX5_RXQ_OBJ_TYPE_DEVX_RQ) 155940f0a1dSDekel Peled rxq_ctrl->wqn = rxq_ctrl->obj->rq->id; 156a1366b1aSNélio Laranjeiro } 157a6d83b6aSNélio Laranjeiro return 0; 158a1366b1aSNélio Laranjeiro error: 159a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 16024f653a7SYongseok Koh do { 16124f653a7SYongseok Koh mlx5_rxq_release(dev, i); 16224f653a7SYongseok Koh } while (i-- != 0); 163a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 164a6d83b6aSNélio Laranjeiro return -rte_errno; 165a1366b1aSNélio Laranjeiro } 166a1366b1aSNélio Laranjeiro 167e60fbd5bSAdrien Mazarguil /** 1686a338ad4SOri Kam * Binds Tx queues to Rx queues for hairpin. 1696a338ad4SOri Kam * 1706a338ad4SOri Kam * Binds Tx queues to the target Rx queues. 1716a338ad4SOri Kam * 1726a338ad4SOri Kam * @param dev 1736a338ad4SOri Kam * Pointer to Ethernet device structure. 1746a338ad4SOri Kam * 1756a338ad4SOri Kam * @return 1766a338ad4SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 1776a338ad4SOri Kam */ 1786a338ad4SOri Kam static int 1796a338ad4SOri Kam mlx5_hairpin_bind(struct rte_eth_dev *dev) 1806a338ad4SOri Kam { 1816a338ad4SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 1826a338ad4SOri Kam struct mlx5_devx_modify_sq_attr sq_attr = { 0 }; 1836a338ad4SOri Kam struct mlx5_devx_modify_rq_attr rq_attr = { 0 }; 1846a338ad4SOri Kam struct mlx5_txq_ctrl *txq_ctrl; 1856a338ad4SOri Kam struct mlx5_rxq_ctrl *rxq_ctrl; 1866a338ad4SOri Kam struct mlx5_devx_obj *sq; 1876a338ad4SOri Kam struct mlx5_devx_obj *rq; 1886a338ad4SOri Kam unsigned int i; 1896a338ad4SOri Kam int ret = 0; 1906a338ad4SOri Kam 1916a338ad4SOri Kam for (i = 0; i != priv->txqs_n; ++i) { 1926a338ad4SOri Kam txq_ctrl = mlx5_txq_get(dev, i); 1936a338ad4SOri Kam if (!txq_ctrl) 1946a338ad4SOri Kam continue; 1956a338ad4SOri Kam if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) { 1966a338ad4SOri Kam mlx5_txq_release(dev, i); 1976a338ad4SOri Kam continue; 1986a338ad4SOri Kam } 1996a338ad4SOri Kam if (!txq_ctrl->obj) { 2006a338ad4SOri Kam rte_errno = ENOMEM; 2016a338ad4SOri Kam DRV_LOG(ERR, "port %u no txq object found: %d", 2026a338ad4SOri Kam dev->data->port_id, i); 2036a338ad4SOri Kam mlx5_txq_release(dev, i); 2046a338ad4SOri Kam return -rte_errno; 2056a338ad4SOri Kam } 2066a338ad4SOri Kam sq = txq_ctrl->obj->sq; 2076a338ad4SOri Kam rxq_ctrl = mlx5_rxq_get(dev, 2086a338ad4SOri Kam txq_ctrl->hairpin_conf.peers[0].queue); 2096a338ad4SOri Kam if (!rxq_ctrl) { 2106a338ad4SOri Kam mlx5_txq_release(dev, i); 2116a338ad4SOri Kam rte_errno = EINVAL; 2126a338ad4SOri Kam DRV_LOG(ERR, "port %u no rxq object found: %d", 2136a338ad4SOri Kam dev->data->port_id, 2146a338ad4SOri Kam txq_ctrl->hairpin_conf.peers[0].queue); 2156a338ad4SOri Kam return -rte_errno; 2166a338ad4SOri Kam } 2176a338ad4SOri Kam if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN || 2186a338ad4SOri Kam rxq_ctrl->hairpin_conf.peers[0].queue != i) { 2196a338ad4SOri Kam rte_errno = ENOMEM; 2206a338ad4SOri Kam DRV_LOG(ERR, "port %u Tx queue %d can't be binded to " 2216a338ad4SOri Kam "Rx queue %d", dev->data->port_id, 2226a338ad4SOri Kam i, txq_ctrl->hairpin_conf.peers[0].queue); 2236a338ad4SOri Kam goto error; 2246a338ad4SOri Kam } 2256a338ad4SOri Kam rq = rxq_ctrl->obj->rq; 2266a338ad4SOri Kam if (!rq) { 2276a338ad4SOri Kam rte_errno = ENOMEM; 2286a338ad4SOri Kam DRV_LOG(ERR, "port %u hairpin no matching rxq: %d", 2296a338ad4SOri Kam dev->data->port_id, 2306a338ad4SOri Kam txq_ctrl->hairpin_conf.peers[0].queue); 2316a338ad4SOri Kam goto error; 2326a338ad4SOri Kam } 2336a338ad4SOri Kam sq_attr.state = MLX5_SQC_STATE_RDY; 2346a338ad4SOri Kam sq_attr.sq_state = MLX5_SQC_STATE_RST; 2356a338ad4SOri Kam sq_attr.hairpin_peer_rq = rq->id; 2366a338ad4SOri Kam sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id; 2376a338ad4SOri Kam ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr); 2386a338ad4SOri Kam if (ret) 2396a338ad4SOri Kam goto error; 2406a338ad4SOri Kam rq_attr.state = MLX5_SQC_STATE_RDY; 2416a338ad4SOri Kam rq_attr.rq_state = MLX5_SQC_STATE_RST; 2426a338ad4SOri Kam rq_attr.hairpin_peer_sq = sq->id; 2436a338ad4SOri Kam rq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id; 2446a338ad4SOri Kam ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr); 2456a338ad4SOri Kam if (ret) 2466a338ad4SOri Kam goto error; 2476a338ad4SOri Kam mlx5_txq_release(dev, i); 2486a338ad4SOri Kam mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue); 2496a338ad4SOri Kam } 2506a338ad4SOri Kam return 0; 2516a338ad4SOri Kam error: 2526a338ad4SOri Kam mlx5_txq_release(dev, i); 2536a338ad4SOri Kam mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue); 2546a338ad4SOri Kam return -rte_errno; 2556a338ad4SOri Kam } 2566a338ad4SOri Kam 2576a338ad4SOri Kam /** 258e60fbd5bSAdrien Mazarguil * DPDK callback to start the device. 259e60fbd5bSAdrien Mazarguil * 260e60fbd5bSAdrien Mazarguil * Simulate device start by attaching all configured flows. 261e60fbd5bSAdrien Mazarguil * 262e60fbd5bSAdrien Mazarguil * @param dev 263e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 264e60fbd5bSAdrien Mazarguil * 265e60fbd5bSAdrien Mazarguil * @return 266a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 267e60fbd5bSAdrien Mazarguil */ 268e60fbd5bSAdrien Mazarguil int 269e60fbd5bSAdrien Mazarguil mlx5_dev_start(struct rte_eth_dev *dev) 270e60fbd5bSAdrien Mazarguil { 271dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 272a6d83b6aSNélio Laranjeiro int ret; 273e60fbd5bSAdrien Mazarguil 27424f653a7SYongseok Koh DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id); 27563bd1629SOri Kam ret = mlx5_dev_configure_rss_reta(dev); 27663bd1629SOri Kam if (ret) { 27763bd1629SOri Kam DRV_LOG(ERR, "port %u reta config failed: %s", 27863bd1629SOri Kam dev->data->port_id, strerror(rte_errno)); 27963bd1629SOri Kam return -rte_errno; 28063bd1629SOri Kam } 281a6d83b6aSNélio Laranjeiro ret = mlx5_txq_start(dev); 282a6d83b6aSNélio Laranjeiro if (ret) { 283a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u Tx queue allocation failed: %s", 2840f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 28524f653a7SYongseok Koh return -rte_errno; 2866e78005aSNélio Laranjeiro } 287a6d83b6aSNélio Laranjeiro ret = mlx5_rxq_start(dev); 288a6d83b6aSNélio Laranjeiro if (ret) { 289a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u Rx queue allocation failed: %s", 2900f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 29124f653a7SYongseok Koh mlx5_txq_stop(dev); 29224f653a7SYongseok Koh return -rte_errno; 293a1366b1aSNélio Laranjeiro } 2946a338ad4SOri Kam ret = mlx5_hairpin_bind(dev); 2956a338ad4SOri Kam if (ret) { 2966a338ad4SOri Kam DRV_LOG(ERR, "port %u hairpin binding failed: %s", 2976a338ad4SOri Kam dev->data->port_id, strerror(rte_errno)); 2986a338ad4SOri Kam mlx5_txq_stop(dev); 2996a338ad4SOri Kam return -rte_errno; 3006a338ad4SOri Kam } 30124f653a7SYongseok Koh dev->data->dev_started = 1; 302a6d83b6aSNélio Laranjeiro ret = mlx5_rx_intr_vec_enable(dev); 303a6d83b6aSNélio Laranjeiro if (ret) { 304a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u Rx interrupt vector creation failed", 3050f99970bSNélio Laranjeiro dev->data->port_id); 306e1016cb7SAdrien Mazarguil goto error; 3073c7d44afSShahaf Shuler } 308ce9494d7STom Barbette mlx5_stats_init(dev); 3097ba5320bSNélio Laranjeiro ret = mlx5_traffic_enable(dev); 310a6d83b6aSNélio Laranjeiro if (ret) { 3117ba5320bSNélio Laranjeiro DRV_LOG(DEBUG, "port %u failed to set defaults flows", 312e313ef4cSShahaf Shuler dev->data->port_id); 313e313ef4cSShahaf Shuler goto error; 314e313ef4cSShahaf Shuler } 3157ba5320bSNélio Laranjeiro ret = mlx5_flow_start(dev, &priv->flows); 3167ba5320bSNélio Laranjeiro if (ret) { 3177ba5320bSNélio Laranjeiro DRV_LOG(DEBUG, "port %u failed to set flows", 3187ba5320bSNélio Laranjeiro dev->data->port_id); 3197ba5320bSNélio Laranjeiro goto error; 3207ba5320bSNélio Laranjeiro } 3212aac5b5dSYongseok Koh rte_wmb(); 3227ba5320bSNélio Laranjeiro dev->tx_pkt_burst = mlx5_select_tx_function(dev); 3237ba5320bSNélio Laranjeiro dev->rx_pkt_burst = mlx5_select_rx_function(dev); 3242aac5b5dSYongseok Koh /* Enable datapath on secondary process. */ 3252aac5b5dSYongseok Koh mlx5_mp_req_start_rxtx(dev); 326af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(dev); 327c8d4ee50SNélio Laranjeiro return 0; 328c8d4ee50SNélio Laranjeiro error: 329a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 330e60fbd5bSAdrien Mazarguil /* Rollback. */ 331272733b5SNélio Laranjeiro dev->data->dev_started = 0; 332af4f09f2SNélio Laranjeiro mlx5_flow_stop(dev, &priv->flows); 333af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 334af4f09f2SNélio Laranjeiro mlx5_txq_stop(dev); 335af4f09f2SNélio Laranjeiro mlx5_rxq_stop(dev); 336a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 337a6d83b6aSNélio Laranjeiro return -rte_errno; 338e60fbd5bSAdrien Mazarguil } 339e60fbd5bSAdrien Mazarguil 340e60fbd5bSAdrien Mazarguil /** 341e60fbd5bSAdrien Mazarguil * DPDK callback to stop the device. 342e60fbd5bSAdrien Mazarguil * 343e60fbd5bSAdrien Mazarguil * Simulate device stop by detaching all configured flows. 344e60fbd5bSAdrien Mazarguil * 345e60fbd5bSAdrien Mazarguil * @param dev 346e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 347e60fbd5bSAdrien Mazarguil */ 348e60fbd5bSAdrien Mazarguil void 349e60fbd5bSAdrien Mazarguil mlx5_dev_stop(struct rte_eth_dev *dev) 350e60fbd5bSAdrien Mazarguil { 351dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 352e60fbd5bSAdrien Mazarguil 3533f2fe392SNélio Laranjeiro dev->data->dev_started = 0; 3543f2fe392SNélio Laranjeiro /* Prevent crashes when queues are still in use. */ 3553f2fe392SNélio Laranjeiro dev->rx_pkt_burst = removed_rx_burst; 3563f2fe392SNélio Laranjeiro dev->tx_pkt_burst = removed_tx_burst; 3573f2fe392SNélio Laranjeiro rte_wmb(); 3582aac5b5dSYongseok Koh /* Disable datapath on secondary process. */ 3592aac5b5dSYongseok Koh mlx5_mp_req_stop_rxtx(dev); 3603f2fe392SNélio Laranjeiro usleep(1000 * priv->rxqs_n); 36124f653a7SYongseok Koh DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id); 362af4f09f2SNélio Laranjeiro mlx5_flow_stop(dev, &priv->flows); 363af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 364af4f09f2SNélio Laranjeiro mlx5_rx_intr_vec_disable(dev); 365af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(dev); 366af4f09f2SNélio Laranjeiro mlx5_txq_stop(dev); 367af4f09f2SNélio Laranjeiro mlx5_rxq_stop(dev); 368e60fbd5bSAdrien Mazarguil } 369272733b5SNélio Laranjeiro 370272733b5SNélio Laranjeiro /** 371272733b5SNélio Laranjeiro * Enable traffic flows configured by control plane 372272733b5SNélio Laranjeiro * 373af4f09f2SNélio Laranjeiro * @param dev 374272733b5SNélio Laranjeiro * Pointer to Ethernet device private data. 375272733b5SNélio Laranjeiro * @param dev 376272733b5SNélio Laranjeiro * Pointer to Ethernet device structure. 377272733b5SNélio Laranjeiro * 378272733b5SNélio Laranjeiro * @return 379a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 380272733b5SNélio Laranjeiro */ 381272733b5SNélio Laranjeiro int 382af4f09f2SNélio Laranjeiro mlx5_traffic_enable(struct rte_eth_dev *dev) 383272733b5SNélio Laranjeiro { 384dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 385272733b5SNélio Laranjeiro struct rte_flow_item_eth bcast = { 386272733b5SNélio Laranjeiro .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 387272733b5SNélio Laranjeiro }; 388272733b5SNélio Laranjeiro struct rte_flow_item_eth ipv6_multi_spec = { 389272733b5SNélio Laranjeiro .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00", 390272733b5SNélio Laranjeiro }; 391272733b5SNélio Laranjeiro struct rte_flow_item_eth ipv6_multi_mask = { 392272733b5SNélio Laranjeiro .dst.addr_bytes = "\xff\xff\x00\x00\x00\x00", 393272733b5SNélio Laranjeiro }; 394272733b5SNélio Laranjeiro struct rte_flow_item_eth unicast = { 395272733b5SNélio Laranjeiro .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 396272733b5SNélio Laranjeiro }; 397272733b5SNélio Laranjeiro struct rte_flow_item_eth unicast_mask = { 398272733b5SNélio Laranjeiro .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 399272733b5SNélio Laranjeiro }; 400272733b5SNélio Laranjeiro const unsigned int vlan_filter_n = priv->vlan_filter_n; 4016d13ea8eSOlivier Matz const struct rte_ether_addr cmp = { 402272733b5SNélio Laranjeiro .addr_bytes = "\x00\x00\x00\x00\x00\x00", 403272733b5SNélio Laranjeiro }; 404272733b5SNélio Laranjeiro unsigned int i; 405272733b5SNélio Laranjeiro unsigned int j; 406272733b5SNélio Laranjeiro int ret; 407272733b5SNélio Laranjeiro 4083c84f34eSOri Kam /* 4093c84f34eSOri Kam * Hairpin txq default flow should be created no matter if it is 4103c84f34eSOri Kam * isolation mode. Or else all the packets to be sent will be sent 4113c84f34eSOri Kam * out directly without the TX flow actions, e.g. encapsulation. 4123c84f34eSOri Kam */ 4133c84f34eSOri Kam for (i = 0; i != priv->txqs_n; ++i) { 4143c84f34eSOri Kam struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i); 4153c84f34eSOri Kam if (!txq_ctrl) 4163c84f34eSOri Kam continue; 4173c84f34eSOri Kam if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) { 4183c84f34eSOri Kam ret = mlx5_ctrl_flow_source_queue(dev, i); 4193c84f34eSOri Kam if (ret) { 4203c84f34eSOri Kam mlx5_txq_release(dev, i); 4213c84f34eSOri Kam goto error; 4223c84f34eSOri Kam } 4233c84f34eSOri Kam } 4243c84f34eSOri Kam mlx5_txq_release(dev, i); 4253c84f34eSOri Kam } 426*fbde4331SMatan Azrad if (priv->config.dv_esw_en && !priv->config.vf) { 427*fbde4331SMatan Azrad if (mlx5_flow_create_esw_table_zero_flow(dev)) 428*fbde4331SMatan Azrad priv->fdb_def_rule = 1; 429*fbde4331SMatan Azrad else 430*fbde4331SMatan Azrad DRV_LOG(INFO, "port %u FDB default rule cannot be" 431*fbde4331SMatan Azrad " configured - only Eswitch group 0 flows are" 432*fbde4331SMatan Azrad " supported.", dev->data->port_id); 433*fbde4331SMatan Azrad } 434f8cb4b57SNélio Laranjeiro if (priv->isolated) 435f8cb4b57SNélio Laranjeiro return 0; 436f8cb4b57SNélio Laranjeiro if (dev->data->promiscuous) { 437f8cb4b57SNélio Laranjeiro struct rte_flow_item_eth promisc = { 438f8cb4b57SNélio Laranjeiro .dst.addr_bytes = "\x00\x00\x00\x00\x00\x00", 439f8cb4b57SNélio Laranjeiro .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 440f8cb4b57SNélio Laranjeiro .type = 0, 441f8cb4b57SNélio Laranjeiro }; 442f8cb4b57SNélio Laranjeiro 443a6d83b6aSNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &promisc, &promisc); 444a6d83b6aSNélio Laranjeiro if (ret) 445a6d83b6aSNélio Laranjeiro goto error; 446f8cb4b57SNélio Laranjeiro } 447f8cb4b57SNélio Laranjeiro if (dev->data->all_multicast) { 448f8cb4b57SNélio Laranjeiro struct rte_flow_item_eth multicast = { 449f8cb4b57SNélio Laranjeiro .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00", 450f8cb4b57SNélio Laranjeiro .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 451f8cb4b57SNélio Laranjeiro .type = 0, 452f8cb4b57SNélio Laranjeiro }; 453f8cb4b57SNélio Laranjeiro 454a6d83b6aSNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &multicast, &multicast); 455a6d83b6aSNélio Laranjeiro if (ret) 456a6d83b6aSNélio Laranjeiro goto error; 457f8cb4b57SNélio Laranjeiro } else { 458f8cb4b57SNélio Laranjeiro /* Add broadcast/multicast flows. */ 459f8cb4b57SNélio Laranjeiro for (i = 0; i != vlan_filter_n; ++i) { 460f8cb4b57SNélio Laranjeiro uint16_t vlan = priv->vlan_filter[i]; 461f8cb4b57SNélio Laranjeiro 462f8cb4b57SNélio Laranjeiro struct rte_flow_item_vlan vlan_spec = { 463f8cb4b57SNélio Laranjeiro .tci = rte_cpu_to_be_16(vlan), 464f8cb4b57SNélio Laranjeiro }; 4652bc98393SNelio Laranjeiro struct rte_flow_item_vlan vlan_mask = 4662bc98393SNelio Laranjeiro rte_flow_item_vlan_mask; 467f8cb4b57SNélio Laranjeiro 468f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast, 469f8cb4b57SNélio Laranjeiro &vlan_spec, &vlan_mask); 470f8cb4b57SNélio Laranjeiro if (ret) 471f8cb4b57SNélio Laranjeiro goto error; 472f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec, 473f8cb4b57SNélio Laranjeiro &ipv6_multi_mask, 474f8cb4b57SNélio Laranjeiro &vlan_spec, &vlan_mask); 475f8cb4b57SNélio Laranjeiro if (ret) 476f8cb4b57SNélio Laranjeiro goto error; 477f8cb4b57SNélio Laranjeiro } 478f8cb4b57SNélio Laranjeiro if (!vlan_filter_n) { 479f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &bcast, &bcast); 480f8cb4b57SNélio Laranjeiro if (ret) 481f8cb4b57SNélio Laranjeiro goto error; 482f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec, 483f8cb4b57SNélio Laranjeiro &ipv6_multi_mask); 484f8cb4b57SNélio Laranjeiro if (ret) 485f8cb4b57SNélio Laranjeiro goto error; 486f8cb4b57SNélio Laranjeiro } 487f8cb4b57SNélio Laranjeiro } 488f8cb4b57SNélio Laranjeiro /* Add MAC address flows. */ 489272733b5SNélio Laranjeiro for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) { 4906d13ea8eSOlivier Matz struct rte_ether_addr *mac = &dev->data->mac_addrs[i]; 491272733b5SNélio Laranjeiro 492272733b5SNélio Laranjeiro if (!memcmp(mac, &cmp, sizeof(*mac))) 493272733b5SNélio Laranjeiro continue; 494272733b5SNélio Laranjeiro memcpy(&unicast.dst.addr_bytes, 495272733b5SNélio Laranjeiro mac->addr_bytes, 49635b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 497272733b5SNélio Laranjeiro for (j = 0; j != vlan_filter_n; ++j) { 498272733b5SNélio Laranjeiro uint16_t vlan = priv->vlan_filter[j]; 499272733b5SNélio Laranjeiro 500272733b5SNélio Laranjeiro struct rte_flow_item_vlan vlan_spec = { 501272733b5SNélio Laranjeiro .tci = rte_cpu_to_be_16(vlan), 502272733b5SNélio Laranjeiro }; 5032bc98393SNelio Laranjeiro struct rte_flow_item_vlan vlan_mask = 5042bc98393SNelio Laranjeiro rte_flow_item_vlan_mask; 505272733b5SNélio Laranjeiro 506272733b5SNélio Laranjeiro ret = mlx5_ctrl_flow_vlan(dev, &unicast, 507272733b5SNélio Laranjeiro &unicast_mask, 508272733b5SNélio Laranjeiro &vlan_spec, 509272733b5SNélio Laranjeiro &vlan_mask); 510272733b5SNélio Laranjeiro if (ret) 511272733b5SNélio Laranjeiro goto error; 512272733b5SNélio Laranjeiro } 513272733b5SNélio Laranjeiro if (!vlan_filter_n) { 514a6d83b6aSNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask); 515272733b5SNélio Laranjeiro if (ret) 516272733b5SNélio Laranjeiro goto error; 517272733b5SNélio Laranjeiro } 518272733b5SNélio Laranjeiro } 519272733b5SNélio Laranjeiro return 0; 520272733b5SNélio Laranjeiro error: 521a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 522a6d83b6aSNélio Laranjeiro mlx5_flow_list_flush(dev, &priv->ctrl_flows); 523a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 524a6d83b6aSNélio Laranjeiro return -rte_errno; 525272733b5SNélio Laranjeiro } 526272733b5SNélio Laranjeiro 527272733b5SNélio Laranjeiro 528272733b5SNélio Laranjeiro /** 529272733b5SNélio Laranjeiro * Disable traffic flows configured by control plane 530272733b5SNélio Laranjeiro * 531272733b5SNélio Laranjeiro * @param dev 532af4f09f2SNélio Laranjeiro * Pointer to Ethernet device private data. 533272733b5SNélio Laranjeiro */ 534925061b5SNélio Laranjeiro void 535af4f09f2SNélio Laranjeiro mlx5_traffic_disable(struct rte_eth_dev *dev) 536272733b5SNélio Laranjeiro { 537dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 538272733b5SNélio Laranjeiro 539af4f09f2SNélio Laranjeiro mlx5_flow_list_flush(dev, &priv->ctrl_flows); 540272733b5SNélio Laranjeiro } 541272733b5SNélio Laranjeiro 542272733b5SNélio Laranjeiro /** 543272733b5SNélio Laranjeiro * Restart traffic flows configured by control plane 544272733b5SNélio Laranjeiro * 545272733b5SNélio Laranjeiro * @param dev 546af4f09f2SNélio Laranjeiro * Pointer to Ethernet device private data. 547272733b5SNélio Laranjeiro * 548272733b5SNélio Laranjeiro * @return 549a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 550272733b5SNélio Laranjeiro */ 551272733b5SNélio Laranjeiro int 552272733b5SNélio Laranjeiro mlx5_traffic_restart(struct rte_eth_dev *dev) 553272733b5SNélio Laranjeiro { 554af4f09f2SNélio Laranjeiro if (dev->data->dev_started) { 555af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 556a6d83b6aSNélio Laranjeiro return mlx5_traffic_enable(dev); 557af4f09f2SNélio Laranjeiro } 558272733b5SNélio Laranjeiro return 0; 559272733b5SNélio Laranjeiro } 560