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" 14*b8dc6b0eSVu Pham #include "mlx5_mr.h" 15e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 16e60fbd5bSAdrien Mazarguil #include "mlx5_utils.h" 17efa79e68SOri Kam #include "rte_pmd_mlx5.h" 18e60fbd5bSAdrien Mazarguil 19fb732b0aSNélio Laranjeiro /** 20fb732b0aSNélio Laranjeiro * Stop traffic on Tx queues. 21fb732b0aSNélio Laranjeiro * 22fb732b0aSNélio Laranjeiro * @param dev 23fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 24fb732b0aSNélio Laranjeiro */ 256e78005aSNélio Laranjeiro static void 26af4f09f2SNélio Laranjeiro mlx5_txq_stop(struct rte_eth_dev *dev) 276e78005aSNélio Laranjeiro { 28dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 296e78005aSNélio Laranjeiro unsigned int i; 306e78005aSNélio Laranjeiro 316e78005aSNélio Laranjeiro for (i = 0; i != priv->txqs_n; ++i) 32af4f09f2SNélio Laranjeiro mlx5_txq_release(dev, i); 336e78005aSNélio Laranjeiro } 346e78005aSNélio Laranjeiro 35fb732b0aSNélio Laranjeiro /** 36fb732b0aSNélio Laranjeiro * Start traffic on Tx queues. 37fb732b0aSNélio Laranjeiro * 38fb732b0aSNélio Laranjeiro * @param dev 39fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 40fb732b0aSNélio Laranjeiro * 41fb732b0aSNélio Laranjeiro * @return 42a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 43fb732b0aSNélio Laranjeiro */ 446e78005aSNélio Laranjeiro static int 45af4f09f2SNélio Laranjeiro mlx5_txq_start(struct rte_eth_dev *dev) 466e78005aSNélio Laranjeiro { 47dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 486e78005aSNélio Laranjeiro unsigned int i; 49a6d83b6aSNélio Laranjeiro int ret; 506e78005aSNélio Laranjeiro 516e78005aSNélio Laranjeiro for (i = 0; i != priv->txqs_n; ++i) { 52af4f09f2SNélio Laranjeiro struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i); 536e78005aSNélio Laranjeiro 546e78005aSNélio Laranjeiro if (!txq_ctrl) 556e78005aSNélio Laranjeiro continue; 56ae18a1aeSOri Kam if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) { 57ae18a1aeSOri Kam txq_ctrl->obj = mlx5_txq_obj_new 58ae18a1aeSOri Kam (dev, i, MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN); 59ae18a1aeSOri Kam } else { 606e78005aSNélio Laranjeiro txq_alloc_elts(txq_ctrl); 61ae18a1aeSOri Kam txq_ctrl->obj = mlx5_txq_obj_new 62ae18a1aeSOri Kam (dev, i, MLX5_TXQ_OBJ_TYPE_IBV); 63ae18a1aeSOri Kam } 64894c4a8eSOri Kam if (!txq_ctrl->obj) { 65a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 666e78005aSNélio Laranjeiro goto error; 676e78005aSNélio Laranjeiro } 686e78005aSNélio Laranjeiro } 69a6d83b6aSNélio Laranjeiro return 0; 706e78005aSNélio Laranjeiro error: 71a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 7224f653a7SYongseok Koh do { 7324f653a7SYongseok Koh mlx5_txq_release(dev, i); 7424f653a7SYongseok Koh } while (i-- != 0); 75a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 76a6d83b6aSNélio Laranjeiro return -rte_errno; 776e78005aSNélio Laranjeiro } 786e78005aSNélio Laranjeiro 79fb732b0aSNélio Laranjeiro /** 80fb732b0aSNélio Laranjeiro * Stop traffic on Rx queues. 81fb732b0aSNélio Laranjeiro * 82fb732b0aSNélio Laranjeiro * @param dev 83fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 84fb732b0aSNélio Laranjeiro */ 85a1366b1aSNélio Laranjeiro static void 86af4f09f2SNélio Laranjeiro mlx5_rxq_stop(struct rte_eth_dev *dev) 87a1366b1aSNélio Laranjeiro { 88dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 89a1366b1aSNélio Laranjeiro unsigned int i; 90a1366b1aSNélio Laranjeiro 91a1366b1aSNélio Laranjeiro for (i = 0; i != priv->rxqs_n; ++i) 92af4f09f2SNélio Laranjeiro mlx5_rxq_release(dev, i); 93a1366b1aSNélio Laranjeiro } 94a1366b1aSNélio Laranjeiro 95fb732b0aSNélio Laranjeiro /** 96fb732b0aSNélio Laranjeiro * Start traffic on Rx queues. 97fb732b0aSNélio Laranjeiro * 98fb732b0aSNélio Laranjeiro * @param dev 99fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 100fb732b0aSNélio Laranjeiro * 101fb732b0aSNélio Laranjeiro * @return 102a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 103fb732b0aSNélio Laranjeiro */ 104a1366b1aSNélio Laranjeiro static int 105af4f09f2SNélio Laranjeiro mlx5_rxq_start(struct rte_eth_dev *dev) 106a1366b1aSNélio Laranjeiro { 107dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 108a1366b1aSNélio Laranjeiro unsigned int i; 109a1366b1aSNélio Laranjeiro int ret = 0; 11017ed314cSMatan Azrad enum mlx5_rxq_obj_type obj_type = MLX5_RXQ_OBJ_TYPE_IBV; 111bf864e82STonghao Zhang struct mlx5_rxq_data *rxq = NULL; 112a1366b1aSNélio Laranjeiro 11317ed314cSMatan Azrad for (i = 0; i < priv->rxqs_n; ++i) { 114bf864e82STonghao Zhang rxq = (*priv->rxqs)[i]; 115bf864e82STonghao Zhang 116bf864e82STonghao Zhang if (rxq && rxq->lro) { 11717ed314cSMatan Azrad obj_type = MLX5_RXQ_OBJ_TYPE_DEVX_RQ; 11817ed314cSMatan Azrad break; 11917ed314cSMatan Azrad } 12017ed314cSMatan Azrad } 1217d6bf6b8SYongseok Koh /* Allocate/reuse/resize mempool for Multi-Packet RQ. */ 12224f653a7SYongseok Koh if (mlx5_mprq_alloc_mp(dev)) { 12324f653a7SYongseok Koh /* Should not release Rx queues but return immediately. */ 12424f653a7SYongseok Koh return -rte_errno; 12524f653a7SYongseok Koh } 126a1366b1aSNélio Laranjeiro for (i = 0; i != priv->rxqs_n; ++i) { 127af4f09f2SNélio Laranjeiro struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i); 128974f1e7eSYongseok Koh struct rte_mempool *mp; 129a1366b1aSNélio Laranjeiro 130a1366b1aSNélio Laranjeiro if (!rxq_ctrl) 131a1366b1aSNélio Laranjeiro continue; 132e79c9be9SOri Kam if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) { 133e79c9be9SOri Kam rxq_ctrl->obj = mlx5_rxq_obj_new 134e79c9be9SOri Kam (dev, i, MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN); 135e79c9be9SOri Kam if (!rxq_ctrl->obj) 136e79c9be9SOri Kam goto error; 137e79c9be9SOri Kam continue; 138e79c9be9SOri Kam } 139974f1e7eSYongseok Koh /* Pre-register Rx mempool. */ 1407d6bf6b8SYongseok Koh mp = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ? 1417d6bf6b8SYongseok Koh rxq_ctrl->rxq.mprq_mp : rxq_ctrl->rxq.mp; 142974f1e7eSYongseok Koh DRV_LOG(DEBUG, 143974f1e7eSYongseok Koh "port %u Rx queue %u registering" 144974f1e7eSYongseok Koh " mp %s having %u chunks", 145d5c900d1SYongseok Koh dev->data->port_id, rxq_ctrl->rxq.idx, 146974f1e7eSYongseok Koh mp->name, mp->nb_mem_chunks); 147974f1e7eSYongseok Koh mlx5_mr_update_mp(dev, &rxq_ctrl->rxq.mr_ctrl, mp); 148a1366b1aSNélio Laranjeiro ret = rxq_alloc_elts(rxq_ctrl); 149a1366b1aSNélio Laranjeiro if (ret) 150a1366b1aSNélio Laranjeiro goto error; 151940f0a1dSDekel Peled rxq_ctrl->obj = mlx5_rxq_obj_new(dev, i, obj_type); 15293403560SDekel Peled if (!rxq_ctrl->obj) 153a1366b1aSNélio Laranjeiro goto error; 154940f0a1dSDekel Peled if (obj_type == MLX5_RXQ_OBJ_TYPE_IBV) 15593403560SDekel Peled rxq_ctrl->wqn = rxq_ctrl->obj->wq->wq_num; 156940f0a1dSDekel Peled else if (obj_type == MLX5_RXQ_OBJ_TYPE_DEVX_RQ) 157940f0a1dSDekel Peled rxq_ctrl->wqn = rxq_ctrl->obj->rq->id; 158a1366b1aSNélio Laranjeiro } 159a6d83b6aSNélio Laranjeiro return 0; 160a1366b1aSNélio Laranjeiro error: 161a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 16224f653a7SYongseok Koh do { 16324f653a7SYongseok Koh mlx5_rxq_release(dev, i); 16424f653a7SYongseok Koh } while (i-- != 0); 165a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 166a6d83b6aSNélio Laranjeiro return -rte_errno; 167a1366b1aSNélio Laranjeiro } 168a1366b1aSNélio Laranjeiro 169e60fbd5bSAdrien Mazarguil /** 1706a338ad4SOri Kam * Binds Tx queues to Rx queues for hairpin. 1716a338ad4SOri Kam * 1726a338ad4SOri Kam * Binds Tx queues to the target Rx queues. 1736a338ad4SOri Kam * 1746a338ad4SOri Kam * @param dev 1756a338ad4SOri Kam * Pointer to Ethernet device structure. 1766a338ad4SOri Kam * 1776a338ad4SOri Kam * @return 1786a338ad4SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 1796a338ad4SOri Kam */ 1806a338ad4SOri Kam static int 1816a338ad4SOri Kam mlx5_hairpin_bind(struct rte_eth_dev *dev) 1826a338ad4SOri Kam { 1836a338ad4SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 1846a338ad4SOri Kam struct mlx5_devx_modify_sq_attr sq_attr = { 0 }; 1856a338ad4SOri Kam struct mlx5_devx_modify_rq_attr rq_attr = { 0 }; 1866a338ad4SOri Kam struct mlx5_txq_ctrl *txq_ctrl; 1876a338ad4SOri Kam struct mlx5_rxq_ctrl *rxq_ctrl; 1886a338ad4SOri Kam struct mlx5_devx_obj *sq; 1896a338ad4SOri Kam struct mlx5_devx_obj *rq; 1906a338ad4SOri Kam unsigned int i; 1916a338ad4SOri Kam int ret = 0; 1926a338ad4SOri Kam 1936a338ad4SOri Kam for (i = 0; i != priv->txqs_n; ++i) { 1946a338ad4SOri Kam txq_ctrl = mlx5_txq_get(dev, i); 1956a338ad4SOri Kam if (!txq_ctrl) 1966a338ad4SOri Kam continue; 1976a338ad4SOri Kam if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) { 1986a338ad4SOri Kam mlx5_txq_release(dev, i); 1996a338ad4SOri Kam continue; 2006a338ad4SOri Kam } 2016a338ad4SOri Kam if (!txq_ctrl->obj) { 2026a338ad4SOri Kam rte_errno = ENOMEM; 2036a338ad4SOri Kam DRV_LOG(ERR, "port %u no txq object found: %d", 2046a338ad4SOri Kam dev->data->port_id, i); 2056a338ad4SOri Kam mlx5_txq_release(dev, i); 2066a338ad4SOri Kam return -rte_errno; 2076a338ad4SOri Kam } 2086a338ad4SOri Kam sq = txq_ctrl->obj->sq; 2096a338ad4SOri Kam rxq_ctrl = mlx5_rxq_get(dev, 2106a338ad4SOri Kam txq_ctrl->hairpin_conf.peers[0].queue); 2116a338ad4SOri Kam if (!rxq_ctrl) { 2126a338ad4SOri Kam mlx5_txq_release(dev, i); 2136a338ad4SOri Kam rte_errno = EINVAL; 2146a338ad4SOri Kam DRV_LOG(ERR, "port %u no rxq object found: %d", 2156a338ad4SOri Kam dev->data->port_id, 2166a338ad4SOri Kam txq_ctrl->hairpin_conf.peers[0].queue); 2176a338ad4SOri Kam return -rte_errno; 2186a338ad4SOri Kam } 2196a338ad4SOri Kam if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN || 2206a338ad4SOri Kam rxq_ctrl->hairpin_conf.peers[0].queue != i) { 2216a338ad4SOri Kam rte_errno = ENOMEM; 2226a338ad4SOri Kam DRV_LOG(ERR, "port %u Tx queue %d can't be binded to " 2236a338ad4SOri Kam "Rx queue %d", dev->data->port_id, 2246a338ad4SOri Kam i, txq_ctrl->hairpin_conf.peers[0].queue); 2256a338ad4SOri Kam goto error; 2266a338ad4SOri Kam } 2276a338ad4SOri Kam rq = rxq_ctrl->obj->rq; 2286a338ad4SOri Kam if (!rq) { 2296a338ad4SOri Kam rte_errno = ENOMEM; 2306a338ad4SOri Kam DRV_LOG(ERR, "port %u hairpin no matching rxq: %d", 2316a338ad4SOri Kam dev->data->port_id, 2326a338ad4SOri Kam txq_ctrl->hairpin_conf.peers[0].queue); 2336a338ad4SOri Kam goto error; 2346a338ad4SOri Kam } 2356a338ad4SOri Kam sq_attr.state = MLX5_SQC_STATE_RDY; 2366a338ad4SOri Kam sq_attr.sq_state = MLX5_SQC_STATE_RST; 2376a338ad4SOri Kam sq_attr.hairpin_peer_rq = rq->id; 2386a338ad4SOri Kam sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id; 2396a338ad4SOri Kam ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr); 2406a338ad4SOri Kam if (ret) 2416a338ad4SOri Kam goto error; 2426a338ad4SOri Kam rq_attr.state = MLX5_SQC_STATE_RDY; 2436a338ad4SOri Kam rq_attr.rq_state = MLX5_SQC_STATE_RST; 2446a338ad4SOri Kam rq_attr.hairpin_peer_sq = sq->id; 2456a338ad4SOri Kam rq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id; 2466a338ad4SOri Kam ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr); 2476a338ad4SOri Kam if (ret) 2486a338ad4SOri Kam goto error; 2496a338ad4SOri Kam mlx5_txq_release(dev, i); 2506a338ad4SOri Kam mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue); 2516a338ad4SOri Kam } 2526a338ad4SOri Kam return 0; 2536a338ad4SOri Kam error: 2546a338ad4SOri Kam mlx5_txq_release(dev, i); 2556a338ad4SOri Kam mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue); 2566a338ad4SOri Kam return -rte_errno; 2576a338ad4SOri Kam } 2586a338ad4SOri Kam 2596a338ad4SOri Kam /** 260e60fbd5bSAdrien Mazarguil * DPDK callback to start the device. 261e60fbd5bSAdrien Mazarguil * 262e60fbd5bSAdrien Mazarguil * Simulate device start by attaching all configured flows. 263e60fbd5bSAdrien Mazarguil * 264e60fbd5bSAdrien Mazarguil * @param dev 265e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 266e60fbd5bSAdrien Mazarguil * 267e60fbd5bSAdrien Mazarguil * @return 268a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 269e60fbd5bSAdrien Mazarguil */ 270e60fbd5bSAdrien Mazarguil int 271e60fbd5bSAdrien Mazarguil mlx5_dev_start(struct rte_eth_dev *dev) 272e60fbd5bSAdrien Mazarguil { 273a6d83b6aSNélio Laranjeiro int ret; 274efa79e68SOri Kam int fine_inline; 275e60fbd5bSAdrien Mazarguil 27624f653a7SYongseok Koh DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id); 277efa79e68SOri Kam fine_inline = rte_mbuf_dynflag_lookup 278efa79e68SOri Kam (RTE_PMD_MLX5_FINE_GRANULARITY_INLINE, NULL); 279efa79e68SOri Kam if (fine_inline > 0) 280efa79e68SOri Kam rte_net_mlx5_dynf_inline_mask = 1UL << fine_inline; 281efa79e68SOri Kam else 282efa79e68SOri Kam rte_net_mlx5_dynf_inline_mask = 0; 283606d6905SShiri Kuzin if (dev->data->nb_rx_queues > 0) { 28463bd1629SOri Kam ret = mlx5_dev_configure_rss_reta(dev); 28563bd1629SOri Kam if (ret) { 28663bd1629SOri Kam DRV_LOG(ERR, "port %u reta config failed: %s", 28763bd1629SOri Kam dev->data->port_id, strerror(rte_errno)); 28863bd1629SOri Kam return -rte_errno; 28963bd1629SOri Kam } 290606d6905SShiri Kuzin } 291a6d83b6aSNélio Laranjeiro ret = mlx5_txq_start(dev); 292a6d83b6aSNélio Laranjeiro if (ret) { 293a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u Tx queue allocation failed: %s", 2940f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 29524f653a7SYongseok Koh return -rte_errno; 2966e78005aSNélio Laranjeiro } 297a6d83b6aSNélio Laranjeiro ret = mlx5_rxq_start(dev); 298a6d83b6aSNélio Laranjeiro if (ret) { 299a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u Rx queue allocation failed: %s", 3000f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 30124f653a7SYongseok Koh mlx5_txq_stop(dev); 30224f653a7SYongseok Koh return -rte_errno; 303a1366b1aSNélio Laranjeiro } 3046a338ad4SOri Kam ret = mlx5_hairpin_bind(dev); 3056a338ad4SOri Kam if (ret) { 3066a338ad4SOri Kam DRV_LOG(ERR, "port %u hairpin binding failed: %s", 3076a338ad4SOri Kam dev->data->port_id, strerror(rte_errno)); 3086a338ad4SOri Kam mlx5_txq_stop(dev); 3096a338ad4SOri Kam return -rte_errno; 3106a338ad4SOri Kam } 311e7bfa359SBing Zhao /* Set started flag here for the following steps like control flow. */ 31224f653a7SYongseok Koh dev->data->dev_started = 1; 313a6d83b6aSNélio Laranjeiro ret = mlx5_rx_intr_vec_enable(dev); 314a6d83b6aSNélio Laranjeiro if (ret) { 315a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u Rx interrupt vector creation failed", 3160f99970bSNélio Laranjeiro dev->data->port_id); 317e1016cb7SAdrien Mazarguil goto error; 3183c7d44afSShahaf Shuler } 319ce9494d7STom Barbette mlx5_stats_init(dev); 3207ba5320bSNélio Laranjeiro ret = mlx5_traffic_enable(dev); 321a6d83b6aSNélio Laranjeiro if (ret) { 3228db7e3b6SBing Zhao DRV_LOG(ERR, "port %u failed to set defaults flows", 323e313ef4cSShahaf Shuler dev->data->port_id); 324e313ef4cSShahaf Shuler goto error; 325e313ef4cSShahaf Shuler } 3268db7e3b6SBing Zhao /* 3278db7e3b6SBing Zhao * In non-cached mode, it only needs to start the default mreg copy 3288db7e3b6SBing Zhao * action and no flow created by application exists anymore. 3298db7e3b6SBing Zhao * But it is worth wrapping the interface for further usage. 3308db7e3b6SBing Zhao */ 3318db7e3b6SBing Zhao ret = mlx5_flow_start_default(dev); 3327ba5320bSNélio Laranjeiro if (ret) { 3338db7e3b6SBing Zhao DRV_LOG(DEBUG, "port %u failed to start default actions: %s", 3348db7e3b6SBing Zhao dev->data->port_id, strerror(rte_errno)); 3357ba5320bSNélio Laranjeiro goto error; 3367ba5320bSNélio Laranjeiro } 3372aac5b5dSYongseok Koh rte_wmb(); 3387ba5320bSNélio Laranjeiro dev->tx_pkt_burst = mlx5_select_tx_function(dev); 3397ba5320bSNélio Laranjeiro dev->rx_pkt_burst = mlx5_select_rx_function(dev); 3402aac5b5dSYongseok Koh /* Enable datapath on secondary process. */ 3412aac5b5dSYongseok Koh mlx5_mp_req_start_rxtx(dev); 342af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(dev); 343c8d4ee50SNélio Laranjeiro return 0; 344c8d4ee50SNélio Laranjeiro error: 345a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 346e60fbd5bSAdrien Mazarguil /* Rollback. */ 347272733b5SNélio Laranjeiro dev->data->dev_started = 0; 3488db7e3b6SBing Zhao mlx5_flow_stop_default(dev); 349af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 350af4f09f2SNélio Laranjeiro mlx5_txq_stop(dev); 351af4f09f2SNélio Laranjeiro mlx5_rxq_stop(dev); 352a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 353a6d83b6aSNélio Laranjeiro return -rte_errno; 354e60fbd5bSAdrien Mazarguil } 355e60fbd5bSAdrien Mazarguil 356e60fbd5bSAdrien Mazarguil /** 357e60fbd5bSAdrien Mazarguil * DPDK callback to stop the device. 358e60fbd5bSAdrien Mazarguil * 359e60fbd5bSAdrien Mazarguil * Simulate device stop by detaching all configured flows. 360e60fbd5bSAdrien Mazarguil * 361e60fbd5bSAdrien Mazarguil * @param dev 362e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 363e60fbd5bSAdrien Mazarguil */ 364e60fbd5bSAdrien Mazarguil void 365e60fbd5bSAdrien Mazarguil mlx5_dev_stop(struct rte_eth_dev *dev) 366e60fbd5bSAdrien Mazarguil { 367dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 368e60fbd5bSAdrien Mazarguil 3693f2fe392SNélio Laranjeiro dev->data->dev_started = 0; 3703f2fe392SNélio Laranjeiro /* Prevent crashes when queues are still in use. */ 3713f2fe392SNélio Laranjeiro dev->rx_pkt_burst = removed_rx_burst; 3723f2fe392SNélio Laranjeiro dev->tx_pkt_burst = removed_tx_burst; 3733f2fe392SNélio Laranjeiro rte_wmb(); 3742aac5b5dSYongseok Koh /* Disable datapath on secondary process. */ 3752aac5b5dSYongseok Koh mlx5_mp_req_stop_rxtx(dev); 3763f2fe392SNélio Laranjeiro usleep(1000 * priv->rxqs_n); 37724f653a7SYongseok Koh DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id); 3788db7e3b6SBing Zhao mlx5_flow_stop_default(dev); 3798db7e3b6SBing Zhao /* Control flows for default traffic can be removed firstly. */ 380af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 3818db7e3b6SBing Zhao /* All RX queue flags will be cleared in the flush interface. */ 3828db7e3b6SBing Zhao mlx5_flow_list_flush(dev, &priv->flows, true); 383af4f09f2SNélio Laranjeiro mlx5_rx_intr_vec_disable(dev); 384af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(dev); 385af4f09f2SNélio Laranjeiro mlx5_txq_stop(dev); 386af4f09f2SNélio Laranjeiro mlx5_rxq_stop(dev); 387e60fbd5bSAdrien Mazarguil } 388272733b5SNélio Laranjeiro 389272733b5SNélio Laranjeiro /** 390272733b5SNélio Laranjeiro * Enable traffic flows configured by control plane 391272733b5SNélio Laranjeiro * 392af4f09f2SNélio Laranjeiro * @param dev 393272733b5SNélio Laranjeiro * Pointer to Ethernet device private data. 394272733b5SNélio Laranjeiro * @param dev 395272733b5SNélio Laranjeiro * Pointer to Ethernet device structure. 396272733b5SNélio Laranjeiro * 397272733b5SNélio Laranjeiro * @return 398a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 399272733b5SNélio Laranjeiro */ 400272733b5SNélio Laranjeiro int 401af4f09f2SNélio Laranjeiro mlx5_traffic_enable(struct rte_eth_dev *dev) 402272733b5SNélio Laranjeiro { 403dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 404272733b5SNélio Laranjeiro struct rte_flow_item_eth bcast = { 405272733b5SNélio Laranjeiro .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 406272733b5SNélio Laranjeiro }; 407272733b5SNélio Laranjeiro struct rte_flow_item_eth ipv6_multi_spec = { 408272733b5SNélio Laranjeiro .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00", 409272733b5SNélio Laranjeiro }; 410272733b5SNélio Laranjeiro struct rte_flow_item_eth ipv6_multi_mask = { 411272733b5SNélio Laranjeiro .dst.addr_bytes = "\xff\xff\x00\x00\x00\x00", 412272733b5SNélio Laranjeiro }; 413272733b5SNélio Laranjeiro struct rte_flow_item_eth unicast = { 414272733b5SNélio Laranjeiro .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 415272733b5SNélio Laranjeiro }; 416272733b5SNélio Laranjeiro struct rte_flow_item_eth unicast_mask = { 417272733b5SNélio Laranjeiro .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 418272733b5SNélio Laranjeiro }; 419272733b5SNélio Laranjeiro const unsigned int vlan_filter_n = priv->vlan_filter_n; 4206d13ea8eSOlivier Matz const struct rte_ether_addr cmp = { 421272733b5SNélio Laranjeiro .addr_bytes = "\x00\x00\x00\x00\x00\x00", 422272733b5SNélio Laranjeiro }; 423272733b5SNélio Laranjeiro unsigned int i; 424272733b5SNélio Laranjeiro unsigned int j; 425272733b5SNélio Laranjeiro int ret; 426272733b5SNélio Laranjeiro 4273c84f34eSOri Kam /* 4283c84f34eSOri Kam * Hairpin txq default flow should be created no matter if it is 4293c84f34eSOri Kam * isolation mode. Or else all the packets to be sent will be sent 4303c84f34eSOri Kam * out directly without the TX flow actions, e.g. encapsulation. 4313c84f34eSOri Kam */ 4323c84f34eSOri Kam for (i = 0; i != priv->txqs_n; ++i) { 4333c84f34eSOri Kam struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i); 4343c84f34eSOri Kam if (!txq_ctrl) 4353c84f34eSOri Kam continue; 4363c84f34eSOri Kam if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) { 4373c84f34eSOri Kam ret = mlx5_ctrl_flow_source_queue(dev, i); 4383c84f34eSOri Kam if (ret) { 4393c84f34eSOri Kam mlx5_txq_release(dev, i); 4403c84f34eSOri Kam goto error; 4413c84f34eSOri Kam } 4423c84f34eSOri Kam } 4433c84f34eSOri Kam mlx5_txq_release(dev, i); 4443c84f34eSOri Kam } 445fbde4331SMatan Azrad if (priv->config.dv_esw_en && !priv->config.vf) { 446fbde4331SMatan Azrad if (mlx5_flow_create_esw_table_zero_flow(dev)) 447fbde4331SMatan Azrad priv->fdb_def_rule = 1; 448fbde4331SMatan Azrad else 449fbde4331SMatan Azrad DRV_LOG(INFO, "port %u FDB default rule cannot be" 450fbde4331SMatan Azrad " configured - only Eswitch group 0 flows are" 451fbde4331SMatan Azrad " supported.", dev->data->port_id); 452fbde4331SMatan Azrad } 453f8cb4b57SNélio Laranjeiro if (priv->isolated) 454f8cb4b57SNélio Laranjeiro return 0; 455f8cb4b57SNélio Laranjeiro if (dev->data->promiscuous) { 456f8cb4b57SNélio Laranjeiro struct rte_flow_item_eth promisc = { 457f8cb4b57SNélio Laranjeiro .dst.addr_bytes = "\x00\x00\x00\x00\x00\x00", 458f8cb4b57SNélio Laranjeiro .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 459f8cb4b57SNélio Laranjeiro .type = 0, 460f8cb4b57SNélio Laranjeiro }; 461f8cb4b57SNélio Laranjeiro 462a6d83b6aSNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &promisc, &promisc); 463a6d83b6aSNélio Laranjeiro if (ret) 464a6d83b6aSNélio Laranjeiro goto error; 465f8cb4b57SNélio Laranjeiro } 466f8cb4b57SNélio Laranjeiro if (dev->data->all_multicast) { 467f8cb4b57SNélio Laranjeiro struct rte_flow_item_eth multicast = { 468f8cb4b57SNélio Laranjeiro .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00", 469f8cb4b57SNélio Laranjeiro .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 470f8cb4b57SNélio Laranjeiro .type = 0, 471f8cb4b57SNélio Laranjeiro }; 472f8cb4b57SNélio Laranjeiro 473a6d83b6aSNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &multicast, &multicast); 474a6d83b6aSNélio Laranjeiro if (ret) 475a6d83b6aSNélio Laranjeiro goto error; 476f8cb4b57SNélio Laranjeiro } else { 477f8cb4b57SNélio Laranjeiro /* Add broadcast/multicast flows. */ 478f8cb4b57SNélio Laranjeiro for (i = 0; i != vlan_filter_n; ++i) { 479f8cb4b57SNélio Laranjeiro uint16_t vlan = priv->vlan_filter[i]; 480f8cb4b57SNélio Laranjeiro 481f8cb4b57SNélio Laranjeiro struct rte_flow_item_vlan vlan_spec = { 482f8cb4b57SNélio Laranjeiro .tci = rte_cpu_to_be_16(vlan), 483f8cb4b57SNélio Laranjeiro }; 4842bc98393SNelio Laranjeiro struct rte_flow_item_vlan vlan_mask = 4852bc98393SNelio Laranjeiro rte_flow_item_vlan_mask; 486f8cb4b57SNélio Laranjeiro 487f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast, 488f8cb4b57SNélio Laranjeiro &vlan_spec, &vlan_mask); 489f8cb4b57SNélio Laranjeiro if (ret) 490f8cb4b57SNélio Laranjeiro goto error; 491f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec, 492f8cb4b57SNélio Laranjeiro &ipv6_multi_mask, 493f8cb4b57SNélio Laranjeiro &vlan_spec, &vlan_mask); 494f8cb4b57SNélio Laranjeiro if (ret) 495f8cb4b57SNélio Laranjeiro goto error; 496f8cb4b57SNélio Laranjeiro } 497f8cb4b57SNélio Laranjeiro if (!vlan_filter_n) { 498f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &bcast, &bcast); 499f8cb4b57SNélio Laranjeiro if (ret) 500f8cb4b57SNélio Laranjeiro goto error; 501f8cb4b57SNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec, 502f8cb4b57SNélio Laranjeiro &ipv6_multi_mask); 503f8cb4b57SNélio Laranjeiro if (ret) 504f8cb4b57SNélio Laranjeiro goto error; 505f8cb4b57SNélio Laranjeiro } 506f8cb4b57SNélio Laranjeiro } 507f8cb4b57SNélio Laranjeiro /* Add MAC address flows. */ 508272733b5SNélio Laranjeiro for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) { 5096d13ea8eSOlivier Matz struct rte_ether_addr *mac = &dev->data->mac_addrs[i]; 510272733b5SNélio Laranjeiro 511272733b5SNélio Laranjeiro if (!memcmp(mac, &cmp, sizeof(*mac))) 512272733b5SNélio Laranjeiro continue; 513272733b5SNélio Laranjeiro memcpy(&unicast.dst.addr_bytes, 514272733b5SNélio Laranjeiro mac->addr_bytes, 51535b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 516272733b5SNélio Laranjeiro for (j = 0; j != vlan_filter_n; ++j) { 517272733b5SNélio Laranjeiro uint16_t vlan = priv->vlan_filter[j]; 518272733b5SNélio Laranjeiro 519272733b5SNélio Laranjeiro struct rte_flow_item_vlan vlan_spec = { 520272733b5SNélio Laranjeiro .tci = rte_cpu_to_be_16(vlan), 521272733b5SNélio Laranjeiro }; 5222bc98393SNelio Laranjeiro struct rte_flow_item_vlan vlan_mask = 5232bc98393SNelio Laranjeiro rte_flow_item_vlan_mask; 524272733b5SNélio Laranjeiro 525272733b5SNélio Laranjeiro ret = mlx5_ctrl_flow_vlan(dev, &unicast, 526272733b5SNélio Laranjeiro &unicast_mask, 527272733b5SNélio Laranjeiro &vlan_spec, 528272733b5SNélio Laranjeiro &vlan_mask); 529272733b5SNélio Laranjeiro if (ret) 530272733b5SNélio Laranjeiro goto error; 531272733b5SNélio Laranjeiro } 532272733b5SNélio Laranjeiro if (!vlan_filter_n) { 533a6d83b6aSNélio Laranjeiro ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask); 534272733b5SNélio Laranjeiro if (ret) 535272733b5SNélio Laranjeiro goto error; 536272733b5SNélio Laranjeiro } 537272733b5SNélio Laranjeiro } 538272733b5SNélio Laranjeiro return 0; 539272733b5SNélio Laranjeiro error: 540a6d83b6aSNélio Laranjeiro ret = rte_errno; /* Save rte_errno before cleanup. */ 5418db7e3b6SBing Zhao mlx5_flow_list_flush(dev, &priv->ctrl_flows, false); 542a6d83b6aSNélio Laranjeiro rte_errno = ret; /* Restore rte_errno. */ 543a6d83b6aSNélio Laranjeiro return -rte_errno; 544272733b5SNélio Laranjeiro } 545272733b5SNélio Laranjeiro 546272733b5SNélio Laranjeiro 547272733b5SNélio Laranjeiro /** 548272733b5SNélio Laranjeiro * Disable traffic flows configured by control plane 549272733b5SNélio Laranjeiro * 550272733b5SNélio Laranjeiro * @param dev 551af4f09f2SNélio Laranjeiro * Pointer to Ethernet device private data. 552272733b5SNélio Laranjeiro */ 553925061b5SNélio Laranjeiro void 554af4f09f2SNélio Laranjeiro mlx5_traffic_disable(struct rte_eth_dev *dev) 555272733b5SNélio Laranjeiro { 556dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 557272733b5SNélio Laranjeiro 5588db7e3b6SBing Zhao mlx5_flow_list_flush(dev, &priv->ctrl_flows, false); 559272733b5SNélio Laranjeiro } 560272733b5SNélio Laranjeiro 561272733b5SNélio Laranjeiro /** 562272733b5SNélio Laranjeiro * Restart traffic flows configured by control plane 563272733b5SNélio Laranjeiro * 564272733b5SNélio Laranjeiro * @param dev 565af4f09f2SNélio Laranjeiro * Pointer to Ethernet device private data. 566272733b5SNélio Laranjeiro * 567272733b5SNélio Laranjeiro * @return 568a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 569272733b5SNélio Laranjeiro */ 570272733b5SNélio Laranjeiro int 571272733b5SNélio Laranjeiro mlx5_traffic_restart(struct rte_eth_dev *dev) 572272733b5SNélio Laranjeiro { 573af4f09f2SNélio Laranjeiro if (dev->data->dev_started) { 574af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 575a6d83b6aSNélio Laranjeiro return mlx5_traffic_enable(dev); 576af4f09f2SNélio Laranjeiro } 577272733b5SNélio Laranjeiro return 0; 578272733b5SNélio Laranjeiro } 579