1e60fbd5bSAdrien Mazarguil /*- 2e60fbd5bSAdrien Mazarguil * BSD LICENSE 3e60fbd5bSAdrien Mazarguil * 4e60fbd5bSAdrien Mazarguil * Copyright 2015 6WIND S.A. 5e60fbd5bSAdrien Mazarguil * Copyright 2015 Mellanox. 6e60fbd5bSAdrien Mazarguil * 7e60fbd5bSAdrien Mazarguil * Redistribution and use in source and binary forms, with or without 8e60fbd5bSAdrien Mazarguil * modification, are permitted provided that the following conditions 9e60fbd5bSAdrien Mazarguil * are met: 10e60fbd5bSAdrien Mazarguil * 11e60fbd5bSAdrien Mazarguil * * Redistributions of source code must retain the above copyright 12e60fbd5bSAdrien Mazarguil * notice, this list of conditions and the following disclaimer. 13e60fbd5bSAdrien Mazarguil * * Redistributions in binary form must reproduce the above copyright 14e60fbd5bSAdrien Mazarguil * notice, this list of conditions and the following disclaimer in 15e60fbd5bSAdrien Mazarguil * the documentation and/or other materials provided with the 16e60fbd5bSAdrien Mazarguil * distribution. 17e60fbd5bSAdrien Mazarguil * * Neither the name of 6WIND S.A. nor the names of its 18e60fbd5bSAdrien Mazarguil * contributors may be used to endorse or promote products derived 19e60fbd5bSAdrien Mazarguil * from this software without specific prior written permission. 20e60fbd5bSAdrien Mazarguil * 21e60fbd5bSAdrien Mazarguil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22e60fbd5bSAdrien Mazarguil * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23e60fbd5bSAdrien Mazarguil * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24e60fbd5bSAdrien Mazarguil * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25e60fbd5bSAdrien Mazarguil * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26e60fbd5bSAdrien Mazarguil * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27e60fbd5bSAdrien Mazarguil * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28e60fbd5bSAdrien Mazarguil * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29e60fbd5bSAdrien Mazarguil * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30e60fbd5bSAdrien Mazarguil * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31e60fbd5bSAdrien Mazarguil * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32e60fbd5bSAdrien Mazarguil */ 333f2fe392SNélio Laranjeiro #include <unistd.h> 34e60fbd5bSAdrien Mazarguil 35e60fbd5bSAdrien Mazarguil #include <rte_ether.h> 36e60fbd5bSAdrien Mazarguil #include <rte_ethdev.h> 37198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 38198a3c33SNelio Laranjeiro #include <rte_alarm.h> 39e60fbd5bSAdrien Mazarguil 40e60fbd5bSAdrien Mazarguil #include "mlx5.h" 41e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 42e60fbd5bSAdrien Mazarguil #include "mlx5_utils.h" 43e60fbd5bSAdrien Mazarguil 446e78005aSNélio Laranjeiro static void 456e78005aSNélio Laranjeiro priv_txq_stop(struct priv *priv) 466e78005aSNélio Laranjeiro { 476e78005aSNélio Laranjeiro unsigned int i; 486e78005aSNélio Laranjeiro 496e78005aSNélio Laranjeiro for (i = 0; i != priv->txqs_n; ++i) 506e78005aSNélio Laranjeiro mlx5_priv_txq_release(priv, i); 516e78005aSNélio Laranjeiro } 526e78005aSNélio Laranjeiro 536e78005aSNélio Laranjeiro static int 546e78005aSNélio Laranjeiro priv_txq_start(struct priv *priv) 556e78005aSNélio Laranjeiro { 566e78005aSNélio Laranjeiro unsigned int i; 576e78005aSNélio Laranjeiro int ret = 0; 586e78005aSNélio Laranjeiro 596e78005aSNélio Laranjeiro /* Add memory regions to Tx queues. */ 606e78005aSNélio Laranjeiro for (i = 0; i != priv->txqs_n; ++i) { 616e78005aSNélio Laranjeiro unsigned int idx = 0; 626e78005aSNélio Laranjeiro struct mlx5_mr *mr; 636e78005aSNélio Laranjeiro struct mlx5_txq_ctrl *txq_ctrl = mlx5_priv_txq_get(priv, i); 646e78005aSNélio Laranjeiro 656e78005aSNélio Laranjeiro if (!txq_ctrl) 666e78005aSNélio Laranjeiro continue; 676e78005aSNélio Laranjeiro LIST_FOREACH(mr, &priv->mr, next) 686e78005aSNélio Laranjeiro priv_txq_mp2mr_reg(priv, &txq_ctrl->txq, mr->mp, idx++); 696e78005aSNélio Laranjeiro txq_alloc_elts(txq_ctrl); 706e78005aSNélio Laranjeiro txq_ctrl->ibv = mlx5_priv_txq_ibv_new(priv, i); 716e78005aSNélio Laranjeiro if (!txq_ctrl->ibv) { 726e78005aSNélio Laranjeiro ret = ENOMEM; 736e78005aSNélio Laranjeiro goto error; 746e78005aSNélio Laranjeiro } 756e78005aSNélio Laranjeiro } 766e78005aSNélio Laranjeiro return -ret; 776e78005aSNélio Laranjeiro error: 786e78005aSNélio Laranjeiro priv_txq_stop(priv); 796e78005aSNélio Laranjeiro return -ret; 806e78005aSNélio Laranjeiro } 816e78005aSNélio Laranjeiro 82a1366b1aSNélio Laranjeiro static void 83a1366b1aSNélio Laranjeiro priv_rxq_stop(struct priv *priv) 84a1366b1aSNélio Laranjeiro { 85a1366b1aSNélio Laranjeiro unsigned int i; 86a1366b1aSNélio Laranjeiro 87a1366b1aSNélio Laranjeiro for (i = 0; i != priv->rxqs_n; ++i) 88a1366b1aSNélio Laranjeiro mlx5_priv_rxq_release(priv, i); 89a1366b1aSNélio Laranjeiro } 90a1366b1aSNélio Laranjeiro 91a1366b1aSNélio Laranjeiro static int 92a1366b1aSNélio Laranjeiro priv_rxq_start(struct priv *priv) 93a1366b1aSNélio Laranjeiro { 94a1366b1aSNélio Laranjeiro unsigned int i; 95a1366b1aSNélio Laranjeiro int ret = 0; 96a1366b1aSNélio Laranjeiro 97a1366b1aSNélio Laranjeiro for (i = 0; i != priv->rxqs_n; ++i) { 98a1366b1aSNélio Laranjeiro struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_priv_rxq_get(priv, i); 99a1366b1aSNélio Laranjeiro 100a1366b1aSNélio Laranjeiro if (!rxq_ctrl) 101a1366b1aSNélio Laranjeiro continue; 102a1366b1aSNélio Laranjeiro ret = rxq_alloc_elts(rxq_ctrl); 103a1366b1aSNélio Laranjeiro if (ret) 104a1366b1aSNélio Laranjeiro goto error; 105a1366b1aSNélio Laranjeiro rxq_ctrl->ibv = mlx5_priv_rxq_ibv_new(priv, i); 106a1366b1aSNélio Laranjeiro if (!rxq_ctrl->ibv) { 107a1366b1aSNélio Laranjeiro ret = ENOMEM; 108a1366b1aSNélio Laranjeiro goto error; 109a1366b1aSNélio Laranjeiro } 110a1366b1aSNélio Laranjeiro } 111a1366b1aSNélio Laranjeiro return -ret; 112a1366b1aSNélio Laranjeiro error: 113a1366b1aSNélio Laranjeiro priv_rxq_stop(priv); 114a1366b1aSNélio Laranjeiro return -ret; 115a1366b1aSNélio Laranjeiro } 116a1366b1aSNélio Laranjeiro 117e60fbd5bSAdrien Mazarguil /** 118e60fbd5bSAdrien Mazarguil * DPDK callback to start the device. 119e60fbd5bSAdrien Mazarguil * 120e60fbd5bSAdrien Mazarguil * Simulate device start by attaching all configured flows. 121e60fbd5bSAdrien Mazarguil * 122e60fbd5bSAdrien Mazarguil * @param dev 123e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 124e60fbd5bSAdrien Mazarguil * 125e60fbd5bSAdrien Mazarguil * @return 126e60fbd5bSAdrien Mazarguil * 0 on success, negative errno value on failure. 127e60fbd5bSAdrien Mazarguil */ 128e60fbd5bSAdrien Mazarguil int 129e60fbd5bSAdrien Mazarguil mlx5_dev_start(struct rte_eth_dev *dev) 130e60fbd5bSAdrien Mazarguil { 131e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 1326e78005aSNélio Laranjeiro struct mlx5_mr *mr = NULL; 133ecc1c29dSAdrien Mazarguil int err; 134e60fbd5bSAdrien Mazarguil 135a48deadaSOr Ami if (mlx5_is_secondary()) 136a48deadaSOr Ami return -E_RTE_SECONDARY; 137a48deadaSOr Ami 138e60fbd5bSAdrien Mazarguil priv_lock(priv); 139ecc1c29dSAdrien Mazarguil DEBUG("%p: allocating and configuring hash RX queues", (void *)dev); 1406e78005aSNélio Laranjeiro rte_mempool_walk(mlx5_mp2mr_iter, priv); 1416e78005aSNélio Laranjeiro err = priv_txq_start(priv); 1426e78005aSNélio Laranjeiro if (err) { 1436e78005aSNélio Laranjeiro ERROR("%p: TXQ allocation failed: %s", 1446e78005aSNélio Laranjeiro (void *)dev, strerror(err)); 1456e78005aSNélio Laranjeiro goto error; 1466e78005aSNélio Laranjeiro } 1476e78005aSNélio Laranjeiro /* Update send callback. */ 1486e78005aSNélio Laranjeiro priv_dev_select_tx_function(priv, dev); 149a1366b1aSNélio Laranjeiro err = priv_rxq_start(priv); 150a1366b1aSNélio Laranjeiro if (err) { 151a1366b1aSNélio Laranjeiro ERROR("%p: RXQ allocation failed: %s", 152a1366b1aSNélio Laranjeiro (void *)dev, strerror(err)); 153a1366b1aSNélio Laranjeiro goto error; 154a1366b1aSNélio Laranjeiro } 155a1366b1aSNélio Laranjeiro /* Update receive callback. */ 156a1366b1aSNélio Laranjeiro priv_dev_select_rx_function(priv, dev); 157ecc1c29dSAdrien Mazarguil err = priv_create_hash_rxqs(priv); 158ecc1c29dSAdrien Mazarguil if (!err) 159083c2dd3SYaacov Hazan err = priv_rehash_flows(priv); 160ecc1c29dSAdrien Mazarguil else { 161ecc1c29dSAdrien Mazarguil ERROR("%p: an error occurred while configuring hash RX queues:" 162ecc1c29dSAdrien Mazarguil " %s", 163ecc1c29dSAdrien Mazarguil (void *)priv, strerror(err)); 164c8d4ee50SNélio Laranjeiro goto error; 165c8d4ee50SNélio Laranjeiro } 166*1b37f5d8SNélio Laranjeiro if (dev->data->promiscuous) 167*1b37f5d8SNélio Laranjeiro mlx5_promiscuous_enable(dev); 168*1b37f5d8SNélio Laranjeiro err = priv_flow_start(priv, &priv->ctrl_flows); 169*1b37f5d8SNélio Laranjeiro if (err) { 170*1b37f5d8SNélio Laranjeiro ERROR("%p: an error occurred while configuring control flows:" 171*1b37f5d8SNélio Laranjeiro " %s", 172*1b37f5d8SNélio Laranjeiro (void *)priv, strerror(err)); 173*1b37f5d8SNélio Laranjeiro goto error; 174*1b37f5d8SNélio Laranjeiro } 175*1b37f5d8SNélio Laranjeiro err = priv_flow_start(priv, &priv->flows); 176c8d4ee50SNélio Laranjeiro if (err) { 177c8d4ee50SNélio Laranjeiro ERROR("%p: an error occurred while configuring flows:" 178c8d4ee50SNélio Laranjeiro " %s", 179c8d4ee50SNélio Laranjeiro (void *)priv, strerror(err)); 180c8d4ee50SNélio Laranjeiro goto error; 181c8d4ee50SNélio Laranjeiro } 182e1016cb7SAdrien Mazarguil err = priv_rx_intr_vec_enable(priv); 183e1016cb7SAdrien Mazarguil if (err) { 184e1016cb7SAdrien Mazarguil ERROR("%p: RX interrupt vector creation failed", 185e1016cb7SAdrien Mazarguil (void *)priv); 186e1016cb7SAdrien Mazarguil goto error; 1873c7d44afSShahaf Shuler } 188e1016cb7SAdrien Mazarguil priv_dev_interrupt_handler_install(priv, dev); 189c8d4ee50SNélio Laranjeiro priv_xstats_init(priv); 190c8d4ee50SNélio Laranjeiro priv_unlock(priv); 191c8d4ee50SNélio Laranjeiro return 0; 192c8d4ee50SNélio Laranjeiro error: 193e60fbd5bSAdrien Mazarguil /* Rollback. */ 1946e78005aSNélio Laranjeiro LIST_FOREACH(mr, &priv->mr, next) 1956e78005aSNélio Laranjeiro priv_mr_release(priv, mr); 1960d218674SAdrien Mazarguil priv_special_flow_disable_all(priv); 197ecc1c29dSAdrien Mazarguil priv_mac_addrs_disable(priv); 198ecc1c29dSAdrien Mazarguil priv_destroy_hash_rxqs(priv); 199*1b37f5d8SNélio Laranjeiro priv_flow_stop(priv, &priv->flows); 200*1b37f5d8SNélio Laranjeiro priv_flow_flush(priv, &priv->ctrl_flows); 201a1366b1aSNélio Laranjeiro priv_rxq_stop(priv); 2026e78005aSNélio Laranjeiro priv_txq_stop(priv); 2035e0fbcf9SYongseok Koh priv_unlock(priv); 204ecc1c29dSAdrien Mazarguil return -err; 205e60fbd5bSAdrien Mazarguil } 206e60fbd5bSAdrien Mazarguil 207e60fbd5bSAdrien Mazarguil /** 208e60fbd5bSAdrien Mazarguil * DPDK callback to stop the device. 209e60fbd5bSAdrien Mazarguil * 210e60fbd5bSAdrien Mazarguil * Simulate device stop by detaching all configured flows. 211e60fbd5bSAdrien Mazarguil * 212e60fbd5bSAdrien Mazarguil * @param dev 213e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 214e60fbd5bSAdrien Mazarguil */ 215e60fbd5bSAdrien Mazarguil void 216e60fbd5bSAdrien Mazarguil mlx5_dev_stop(struct rte_eth_dev *dev) 217e60fbd5bSAdrien Mazarguil { 218e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 2196e78005aSNélio Laranjeiro struct mlx5_mr *mr; 220e60fbd5bSAdrien Mazarguil 221a48deadaSOr Ami if (mlx5_is_secondary()) 222a48deadaSOr Ami return; 223a48deadaSOr Ami 224e60fbd5bSAdrien Mazarguil priv_lock(priv); 2253f2fe392SNélio Laranjeiro dev->data->dev_started = 0; 2263f2fe392SNélio Laranjeiro /* Prevent crashes when queues are still in use. */ 2273f2fe392SNélio Laranjeiro dev->rx_pkt_burst = removed_rx_burst; 2283f2fe392SNélio Laranjeiro dev->tx_pkt_burst = removed_tx_burst; 2293f2fe392SNélio Laranjeiro rte_wmb(); 2303f2fe392SNélio Laranjeiro usleep(1000 * priv->rxqs_n); 231ecc1c29dSAdrien Mazarguil DEBUG("%p: cleaning up and destroying hash RX queues", (void *)dev); 2320d218674SAdrien Mazarguil priv_special_flow_disable_all(priv); 233ecc1c29dSAdrien Mazarguil priv_mac_addrs_disable(priv); 234ecc1c29dSAdrien Mazarguil priv_destroy_hash_rxqs(priv); 235*1b37f5d8SNélio Laranjeiro priv_flow_stop(priv, &priv->flows); 236*1b37f5d8SNélio Laranjeiro priv_flow_flush(priv, &priv->ctrl_flows); 237e1016cb7SAdrien Mazarguil priv_rx_intr_vec_disable(priv); 238*1b37f5d8SNélio Laranjeiro priv_dev_interrupt_handler_uninstall(priv, dev); 2396e78005aSNélio Laranjeiro priv_txq_stop(priv); 240a1366b1aSNélio Laranjeiro priv_rxq_stop(priv); 2416e78005aSNélio Laranjeiro LIST_FOREACH(mr, &priv->mr, next) { 2426e78005aSNélio Laranjeiro priv_mr_release(priv, mr); 2436e78005aSNélio Laranjeiro } 244e60fbd5bSAdrien Mazarguil priv_unlock(priv); 245e60fbd5bSAdrien Mazarguil } 246