144c0947bSAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause 2244cfa79SAndrew Rybchenko * 344c0947bSAndrew Rybchenko * Copyright (c) 2016-2018 Solarflare Communications Inc. 463d588ffSAndrew Rybchenko * All rights reserved. 563d588ffSAndrew Rybchenko * 663d588ffSAndrew Rybchenko * This software was jointly developed between OKTET Labs (under contract 763d588ffSAndrew Rybchenko * for Solarflare) and Solarflare Communications, Inc. 863d588ffSAndrew Rybchenko */ 963d588ffSAndrew Rybchenko 1063d588ffSAndrew Rybchenko #include <rte_dev.h> 11ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 12fdf91e0fSJan Blunck #include <rte_ethdev_pci.h> 1363d588ffSAndrew Rybchenko #include <rte_pci.h> 14c752998bSGaetan Rivet #include <rte_bus_pci.h> 15df1bfde4SAndrew Rybchenko #include <rte_errno.h> 16ed5b9848SAndy Green #include <rte_string_fns.h> 1763d588ffSAndrew Rybchenko 18ba641f20SAndrew Rybchenko #include "efx.h" 19ba641f20SAndrew Rybchenko 2063d588ffSAndrew Rybchenko #include "sfc.h" 2163d588ffSAndrew Rybchenko #include "sfc_debug.h" 2263d588ffSAndrew Rybchenko #include "sfc_log.h" 2363d588ffSAndrew Rybchenko #include "sfc_kvargs.h" 24886f8d8aSArtem Andreev #include "sfc_ev.h" 25ce35b05cSAndrew Rybchenko #include "sfc_rx.h" 26b1b7ad93SIvan Malov #include "sfc_tx.h" 27a9825ccfSRoman Zhukov #include "sfc_flow.h" 28df1bfde4SAndrew Rybchenko #include "sfc_dp.h" 29df1bfde4SAndrew Rybchenko #include "sfc_dp_rx.h" 30df1bfde4SAndrew Rybchenko 31fdceb100SIvan Malov uint32_t sfc_logtype_driver; 32fdceb100SIvan Malov 33df1bfde4SAndrew Rybchenko static struct sfc_dp_list sfc_dp_head = 34df1bfde4SAndrew Rybchenko TAILQ_HEAD_INITIALIZER(sfc_dp_head); 3563d588ffSAndrew Rybchenko 3683fef46aSIvan Malov static int 3783fef46aSIvan Malov sfc_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) 3883fef46aSIvan Malov { 395313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 4083fef46aSIvan Malov efx_nic_fw_info_t enfi; 4183fef46aSIvan Malov int ret; 4283fef46aSIvan Malov int rc; 4383fef46aSIvan Malov 4483fef46aSIvan Malov /* 4583fef46aSIvan Malov * Return value of the callback is likely supposed to be 4683fef46aSIvan Malov * equal to or greater than 0, nevertheless, if an error 4783fef46aSIvan Malov * occurs, it will be desirable to pass it to the caller 4883fef46aSIvan Malov */ 4983fef46aSIvan Malov if ((fw_version == NULL) || (fw_size == 0)) 5083fef46aSIvan Malov return -EINVAL; 5183fef46aSIvan Malov 5283fef46aSIvan Malov rc = efx_nic_get_fw_version(sa->nic, &enfi); 5383fef46aSIvan Malov if (rc != 0) 5483fef46aSIvan Malov return -rc; 5583fef46aSIvan Malov 5683fef46aSIvan Malov ret = snprintf(fw_version, fw_size, 5783fef46aSIvan Malov "%" PRIu16 ".%" PRIu16 ".%" PRIu16 ".%" PRIu16, 5883fef46aSIvan Malov enfi.enfi_mc_fw_version[0], enfi.enfi_mc_fw_version[1], 5983fef46aSIvan Malov enfi.enfi_mc_fw_version[2], enfi.enfi_mc_fw_version[3]); 6083fef46aSIvan Malov if (ret < 0) 6183fef46aSIvan Malov return ret; 6283fef46aSIvan Malov 6383fef46aSIvan Malov if (enfi.enfi_dpcpu_fw_ids_valid) { 6483fef46aSIvan Malov size_t dpcpu_fw_ids_offset = MIN(fw_size - 1, (size_t)ret); 6583fef46aSIvan Malov int ret_extra; 6683fef46aSIvan Malov 6783fef46aSIvan Malov ret_extra = snprintf(fw_version + dpcpu_fw_ids_offset, 6883fef46aSIvan Malov fw_size - dpcpu_fw_ids_offset, 6983fef46aSIvan Malov " rx%" PRIx16 " tx%" PRIx16, 7083fef46aSIvan Malov enfi.enfi_rx_dpcpu_fw_id, 7183fef46aSIvan Malov enfi.enfi_tx_dpcpu_fw_id); 7283fef46aSIvan Malov if (ret_extra < 0) 7383fef46aSIvan Malov return ret_extra; 7483fef46aSIvan Malov 7583fef46aSIvan Malov ret += ret_extra; 7683fef46aSIvan Malov } 7783fef46aSIvan Malov 7883fef46aSIvan Malov if (fw_size < (size_t)(++ret)) 7983fef46aSIvan Malov return ret; 8083fef46aSIvan Malov else 8183fef46aSIvan Malov return 0; 8283fef46aSIvan Malov } 8383fef46aSIvan Malov 8463d588ffSAndrew Rybchenko static void 8563d588ffSAndrew Rybchenko sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) 8663d588ffSAndrew Rybchenko { 875dec95e3SAndrew Rybchenko const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev); 88e295f175SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 895313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 90e295f175SAndrew Rybchenko struct sfc_rss *rss = &sas->rss; 91c78d280eSIvan Malov uint64_t txq_offloads_def = 0; 9263d588ffSAndrew Rybchenko 9363d588ffSAndrew Rybchenko sfc_log_init(sa, "entry"); 9463d588ffSAndrew Rybchenko 9503ed2119SAndrew Rybchenko dev_info->max_rx_pktlen = EFX_MAC_PDU_MAX; 96a8e64c6bSAndrew Rybchenko 97d23f3a89SAndrew Rybchenko /* Autonegotiation may be disabled */ 98d23f3a89SAndrew Rybchenko dev_info->speed_capa = ETH_LINK_SPEED_FIXED; 99*cf6a73fcSAndrew Rybchenko if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_1000FDX)) 100d23f3a89SAndrew Rybchenko dev_info->speed_capa |= ETH_LINK_SPEED_1G; 101*cf6a73fcSAndrew Rybchenko if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_10000FDX)) 102d23f3a89SAndrew Rybchenko dev_info->speed_capa |= ETH_LINK_SPEED_10G; 103*cf6a73fcSAndrew Rybchenko if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_25000FDX)) 104f82e33afSAndrew Rybchenko dev_info->speed_capa |= ETH_LINK_SPEED_25G; 105*cf6a73fcSAndrew Rybchenko if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_40000FDX)) 106d23f3a89SAndrew Rybchenko dev_info->speed_capa |= ETH_LINK_SPEED_40G; 107*cf6a73fcSAndrew Rybchenko if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_50000FDX)) 108f82e33afSAndrew Rybchenko dev_info->speed_capa |= ETH_LINK_SPEED_50G; 109*cf6a73fcSAndrew Rybchenko if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_100000FDX)) 110f82e33afSAndrew Rybchenko dev_info->speed_capa |= ETH_LINK_SPEED_100G; 111d23f3a89SAndrew Rybchenko 112ce35b05cSAndrew Rybchenko dev_info->max_rx_queues = sa->rxq_max; 113a8ad8cf8SIvan Malov dev_info->max_tx_queues = sa->txq_max; 114ce35b05cSAndrew Rybchenko 115a8e64c6bSAndrew Rybchenko /* By default packets are dropped if no descriptors are available */ 116a8e64c6bSAndrew Rybchenko dev_info->default_rxconf.rx_drop_en = 1; 117a8e64c6bSAndrew Rybchenko 118ff6a1197SIvan Malov dev_info->rx_queue_offload_capa = sfc_rx_get_queue_offload_caps(sa); 119ff6a1197SIvan Malov 120ff6a1197SIvan Malov /* 121ff6a1197SIvan Malov * rx_offload_capa includes both device and queue offloads since 122ff6a1197SIvan Malov * the latter may be requested on a per device basis which makes 123ff6a1197SIvan Malov * sense when some offloads are needed to be set on all queues. 124ff6a1197SIvan Malov */ 125ff6a1197SIvan Malov dev_info->rx_offload_capa = sfc_rx_get_dev_offload_caps(sa) | 126ff6a1197SIvan Malov dev_info->rx_queue_offload_capa; 127591cbbb1SAndrew Rybchenko 128c78d280eSIvan Malov dev_info->tx_queue_offload_capa = sfc_tx_get_queue_offload_caps(sa); 129c78d280eSIvan Malov 130c78d280eSIvan Malov /* 131c78d280eSIvan Malov * tx_offload_capa includes both device and queue offloads since 132c78d280eSIvan Malov * the latter may be requested on a per device basis which makes 133c78d280eSIvan Malov * sense when some offloads are needed to be set on all queues. 134c78d280eSIvan Malov */ 135c78d280eSIvan Malov dev_info->tx_offload_capa = sfc_tx_get_dev_offload_caps(sa) | 136c78d280eSIvan Malov dev_info->tx_queue_offload_capa; 137c78d280eSIvan Malov 138c78d280eSIvan Malov if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 139c78d280eSIvan Malov txq_offloads_def |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; 140c78d280eSIvan Malov 141c78d280eSIvan Malov dev_info->default_txconf.offloads |= txq_offloads_def; 142c1767d93SAndrew Rybchenko 143d1482e21SIvan Malov if (rss->context_type != EFX_RX_SCALE_UNAVAILABLE) { 14401764b20SIvan Malov uint64_t rte_hf = 0; 14501764b20SIvan Malov unsigned int i; 14601764b20SIvan Malov 14701764b20SIvan Malov for (i = 0; i < rss->hf_map_nb_entries; ++i) 14801764b20SIvan Malov rte_hf |= rss->hf_map[i].rte; 14901764b20SIvan Malov 1504ec1fc3bSIvan Malov dev_info->reta_size = EFX_RSS_TBL_SIZE; 15137a42c61SAndrew Rybchenko dev_info->hash_key_size = EFX_RSS_KEY_SIZE; 15201764b20SIvan Malov dev_info->flow_type_rss_offloads = rte_hf; 1534ec1fc3bSIvan Malov } 1544ec1fc3bSIvan Malov 1553c335b7fSAndrew Rybchenko /* Initialize to hardware limits */ 156048a0d1aSIgor Romanov dev_info->rx_desc_lim.nb_max = sa->rxq_max_entries; 157048a0d1aSIgor Romanov dev_info->rx_desc_lim.nb_min = sa->rxq_min_entries; 158a8e64c6bSAndrew Rybchenko /* The RXQ hardware requires that the descriptor count is a power 159a8e64c6bSAndrew Rybchenko * of 2, but rx_desc_lim cannot properly describe that constraint. 160a8e64c6bSAndrew Rybchenko */ 161048a0d1aSIgor Romanov dev_info->rx_desc_lim.nb_align = sa->rxq_min_entries; 162a8ad8cf8SIvan Malov 163c7dadc9fSAndrew Rybchenko /* Initialize to hardware limits */ 164a8ad8cf8SIvan Malov dev_info->tx_desc_lim.nb_max = sa->txq_max_entries; 1659dbd28dfSIgor Romanov dev_info->tx_desc_lim.nb_min = sa->txq_min_entries; 166a8ad8cf8SIvan Malov /* 167a8ad8cf8SIvan Malov * The TXQ hardware requires that the descriptor count is a power 168a8ad8cf8SIvan Malov * of 2, but tx_desc_lim cannot properly describe that constraint 169a8ad8cf8SIvan Malov */ 1709dbd28dfSIgor Romanov dev_info->tx_desc_lim.nb_align = sa->txq_min_entries; 1713c335b7fSAndrew Rybchenko 1725dec95e3SAndrew Rybchenko if (sap->dp_rx->get_dev_info != NULL) 1735dec95e3SAndrew Rybchenko sap->dp_rx->get_dev_info(dev_info); 1745dec95e3SAndrew Rybchenko if (sap->dp_tx->get_dev_info != NULL) 1755dec95e3SAndrew Rybchenko sap->dp_tx->get_dev_info(dev_info); 1760668a27aSIgor Romanov 177862b35afSIgor Romanov dev_info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP | 178862b35afSIgor Romanov RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP; 17963d588ffSAndrew Rybchenko } 18063d588ffSAndrew Rybchenko 18156349dc9SAndrew Rybchenko static const uint32_t * 18256349dc9SAndrew Rybchenko sfc_dev_supported_ptypes_get(struct rte_eth_dev *dev) 18356349dc9SAndrew Rybchenko { 1845dec95e3SAndrew Rybchenko const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev); 18556349dc9SAndrew Rybchenko 1862646d42fSAndrew Rybchenko return sap->dp_rx->supported_ptypes_get(sap->shared->tunnel_encaps); 18756349dc9SAndrew Rybchenko } 18856349dc9SAndrew Rybchenko 189aaa3f5f0SAndrew Rybchenko static int 190aaa3f5f0SAndrew Rybchenko sfc_dev_configure(struct rte_eth_dev *dev) 191aaa3f5f0SAndrew Rybchenko { 192aaa3f5f0SAndrew Rybchenko struct rte_eth_dev_data *dev_data = dev->data; 1935313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 194aaa3f5f0SAndrew Rybchenko int rc; 195aaa3f5f0SAndrew Rybchenko 196aaa3f5f0SAndrew Rybchenko sfc_log_init(sa, "entry n_rxq=%u n_txq=%u", 197aaa3f5f0SAndrew Rybchenko dev_data->nb_rx_queues, dev_data->nb_tx_queues); 198aaa3f5f0SAndrew Rybchenko 199aaa3f5f0SAndrew Rybchenko sfc_adapter_lock(sa); 200aaa3f5f0SAndrew Rybchenko switch (sa->state) { 201aaa3f5f0SAndrew Rybchenko case SFC_ADAPTER_CONFIGURED: 202aaa3f5f0SAndrew Rybchenko /* FALLTHROUGH */ 203aaa3f5f0SAndrew Rybchenko case SFC_ADAPTER_INITIALIZED: 204aaa3f5f0SAndrew Rybchenko rc = sfc_configure(sa); 205aaa3f5f0SAndrew Rybchenko break; 206aaa3f5f0SAndrew Rybchenko default: 207aaa3f5f0SAndrew Rybchenko sfc_err(sa, "unexpected adapter state %u to configure", 208aaa3f5f0SAndrew Rybchenko sa->state); 209aaa3f5f0SAndrew Rybchenko rc = EINVAL; 210aaa3f5f0SAndrew Rybchenko break; 211aaa3f5f0SAndrew Rybchenko } 212aaa3f5f0SAndrew Rybchenko sfc_adapter_unlock(sa); 213aaa3f5f0SAndrew Rybchenko 214aaa3f5f0SAndrew Rybchenko sfc_log_init(sa, "done %d", rc); 215aaa3f5f0SAndrew Rybchenko SFC_ASSERT(rc >= 0); 216aaa3f5f0SAndrew Rybchenko return -rc; 217aaa3f5f0SAndrew Rybchenko } 218aaa3f5f0SAndrew Rybchenko 21993fcf09bSAndrew Rybchenko static int 22093fcf09bSAndrew Rybchenko sfc_dev_start(struct rte_eth_dev *dev) 22193fcf09bSAndrew Rybchenko { 2225313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 22393fcf09bSAndrew Rybchenko int rc; 22493fcf09bSAndrew Rybchenko 22593fcf09bSAndrew Rybchenko sfc_log_init(sa, "entry"); 22693fcf09bSAndrew Rybchenko 22793fcf09bSAndrew Rybchenko sfc_adapter_lock(sa); 22893fcf09bSAndrew Rybchenko rc = sfc_start(sa); 22993fcf09bSAndrew Rybchenko sfc_adapter_unlock(sa); 23093fcf09bSAndrew Rybchenko 23193fcf09bSAndrew Rybchenko sfc_log_init(sa, "done %d", rc); 23293fcf09bSAndrew Rybchenko SFC_ASSERT(rc >= 0); 23393fcf09bSAndrew Rybchenko return -rc; 23493fcf09bSAndrew Rybchenko } 23593fcf09bSAndrew Rybchenko 236886f8d8aSArtem Andreev static int 237886f8d8aSArtem Andreev sfc_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) 238886f8d8aSArtem Andreev { 2395313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 240886f8d8aSArtem Andreev struct rte_eth_link current_link; 2414abe903eSStephen Hemminger int ret; 242886f8d8aSArtem Andreev 243886f8d8aSArtem Andreev sfc_log_init(sa, "entry"); 244886f8d8aSArtem Andreev 2459b098c52SAndrew Rybchenko if (sa->state != SFC_ADAPTER_STARTED) { 2469b098c52SAndrew Rybchenko sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, ¤t_link); 2479b098c52SAndrew Rybchenko } else if (wait_to_complete) { 248886f8d8aSArtem Andreev efx_link_mode_t link_mode; 249886f8d8aSArtem Andreev 250c7c915e1SAndrew Rybchenko if (efx_port_poll(sa->nic, &link_mode) != 0) 251c7c915e1SAndrew Rybchenko link_mode = EFX_LINK_UNKNOWN; 252886f8d8aSArtem Andreev sfc_port_link_mode_to_info(link_mode, ¤t_link); 253886f8d8aSArtem Andreev 254886f8d8aSArtem Andreev } else { 255886f8d8aSArtem Andreev sfc_ev_mgmt_qpoll(sa); 2564abe903eSStephen Hemminger rte_eth_linkstatus_get(dev, ¤t_link); 257886f8d8aSArtem Andreev } 258886f8d8aSArtem Andreev 2594abe903eSStephen Hemminger ret = rte_eth_linkstatus_set(dev, ¤t_link); 2604abe903eSStephen Hemminger if (ret == 0) 26191d16276SIvan Malov sfc_notice(sa, "Link status is %s", 262886f8d8aSArtem Andreev current_link.link_status ? "UP" : "DOWN"); 26391d16276SIvan Malov 2644abe903eSStephen Hemminger return ret; 265886f8d8aSArtem Andreev } 266886f8d8aSArtem Andreev 26793fcf09bSAndrew Rybchenko static void 26893fcf09bSAndrew Rybchenko sfc_dev_stop(struct rte_eth_dev *dev) 26993fcf09bSAndrew Rybchenko { 2705313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 27193fcf09bSAndrew Rybchenko 27293fcf09bSAndrew Rybchenko sfc_log_init(sa, "entry"); 27393fcf09bSAndrew Rybchenko 27493fcf09bSAndrew Rybchenko sfc_adapter_lock(sa); 27593fcf09bSAndrew Rybchenko sfc_stop(sa); 27693fcf09bSAndrew Rybchenko sfc_adapter_unlock(sa); 27793fcf09bSAndrew Rybchenko 27893fcf09bSAndrew Rybchenko sfc_log_init(sa, "done"); 27993fcf09bSAndrew Rybchenko } 28093fcf09bSAndrew Rybchenko 2812a05f337SArtem Andreev static int 2822a05f337SArtem Andreev sfc_dev_set_link_up(struct rte_eth_dev *dev) 2832a05f337SArtem Andreev { 2845313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 2852a05f337SArtem Andreev int rc; 2862a05f337SArtem Andreev 2872a05f337SArtem Andreev sfc_log_init(sa, "entry"); 2882a05f337SArtem Andreev 2892a05f337SArtem Andreev sfc_adapter_lock(sa); 2902a05f337SArtem Andreev rc = sfc_start(sa); 2912a05f337SArtem Andreev sfc_adapter_unlock(sa); 2922a05f337SArtem Andreev 2932a05f337SArtem Andreev SFC_ASSERT(rc >= 0); 2942a05f337SArtem Andreev return -rc; 2952a05f337SArtem Andreev } 2962a05f337SArtem Andreev 2972a05f337SArtem Andreev static int 2982a05f337SArtem Andreev sfc_dev_set_link_down(struct rte_eth_dev *dev) 2992a05f337SArtem Andreev { 3005313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 3012a05f337SArtem Andreev 3022a05f337SArtem Andreev sfc_log_init(sa, "entry"); 3032a05f337SArtem Andreev 3042a05f337SArtem Andreev sfc_adapter_lock(sa); 3052a05f337SArtem Andreev sfc_stop(sa); 3062a05f337SArtem Andreev sfc_adapter_unlock(sa); 3072a05f337SArtem Andreev 3082a05f337SArtem Andreev return 0; 3092a05f337SArtem Andreev } 3102a05f337SArtem Andreev 311aaa3f5f0SAndrew Rybchenko static void 312aaa3f5f0SAndrew Rybchenko sfc_dev_close(struct rte_eth_dev *dev) 313aaa3f5f0SAndrew Rybchenko { 3145313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 315aaa3f5f0SAndrew Rybchenko 316aaa3f5f0SAndrew Rybchenko sfc_log_init(sa, "entry"); 317aaa3f5f0SAndrew Rybchenko 318aaa3f5f0SAndrew Rybchenko sfc_adapter_lock(sa); 319aaa3f5f0SAndrew Rybchenko switch (sa->state) { 32093fcf09bSAndrew Rybchenko case SFC_ADAPTER_STARTED: 32193fcf09bSAndrew Rybchenko sfc_stop(sa); 32293fcf09bSAndrew Rybchenko SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED); 32393fcf09bSAndrew Rybchenko /* FALLTHROUGH */ 324aaa3f5f0SAndrew Rybchenko case SFC_ADAPTER_CONFIGURED: 325aaa3f5f0SAndrew Rybchenko sfc_close(sa); 326aaa3f5f0SAndrew Rybchenko SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED); 327aaa3f5f0SAndrew Rybchenko /* FALLTHROUGH */ 328aaa3f5f0SAndrew Rybchenko case SFC_ADAPTER_INITIALIZED: 329aaa3f5f0SAndrew Rybchenko break; 330aaa3f5f0SAndrew Rybchenko default: 331aaa3f5f0SAndrew Rybchenko sfc_err(sa, "unexpected adapter state %u on close", sa->state); 332aaa3f5f0SAndrew Rybchenko break; 333aaa3f5f0SAndrew Rybchenko } 334aaa3f5f0SAndrew Rybchenko sfc_adapter_unlock(sa); 335aaa3f5f0SAndrew Rybchenko 336aaa3f5f0SAndrew Rybchenko sfc_log_init(sa, "done"); 337aaa3f5f0SAndrew Rybchenko } 338aaa3f5f0SAndrew Rybchenko 339f3de3840SIvan Malov static void 340f3de3840SIvan Malov sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode, 341f3de3840SIvan Malov boolean_t enabled) 342f3de3840SIvan Malov { 343f3de3840SIvan Malov struct sfc_port *port; 344f3de3840SIvan Malov boolean_t *toggle; 3455313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 346f3de3840SIvan Malov boolean_t allmulti = (mode == SFC_DEV_FILTER_MODE_ALLMULTI); 347f3de3840SIvan Malov const char *desc = (allmulti) ? "all-multi" : "promiscuous"; 348f3de3840SIvan Malov 349f3de3840SIvan Malov sfc_adapter_lock(sa); 350f3de3840SIvan Malov 351f3de3840SIvan Malov port = &sa->port; 352f3de3840SIvan Malov toggle = (allmulti) ? (&port->allmulti) : (&port->promisc); 353f3de3840SIvan Malov 354f3de3840SIvan Malov if (*toggle != enabled) { 355f3de3840SIvan Malov *toggle = enabled; 356f3de3840SIvan Malov 357e0d5ba7eSAndrew Rybchenko if (sfc_sa2shared(sa)->isolated) { 35884a9b481SIvan Malov sfc_warn(sa, "isolated mode is active on the port"); 35984a9b481SIvan Malov sfc_warn(sa, "the change is to be applied on the next " 36084a9b481SIvan Malov "start provided that isolated mode is " 36184a9b481SIvan Malov "disabled prior the next start"); 36284a9b481SIvan Malov } else if ((sa->state == SFC_ADAPTER_STARTED) && 363f3de3840SIvan Malov (sfc_set_rx_mode(sa) != 0)) { 364f3de3840SIvan Malov *toggle = !(enabled); 365f3de3840SIvan Malov sfc_warn(sa, "Failed to %s %s mode", 366f3de3840SIvan Malov ((enabled) ? "enable" : "disable"), desc); 367f3de3840SIvan Malov } 368f3de3840SIvan Malov } 369f3de3840SIvan Malov 370f3de3840SIvan Malov sfc_adapter_unlock(sa); 371f3de3840SIvan Malov } 372f3de3840SIvan Malov 373f3de3840SIvan Malov static void 374f3de3840SIvan Malov sfc_dev_promisc_enable(struct rte_eth_dev *dev) 375f3de3840SIvan Malov { 376f3de3840SIvan Malov sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_TRUE); 377f3de3840SIvan Malov } 378f3de3840SIvan Malov 379f3de3840SIvan Malov static void 380f3de3840SIvan Malov sfc_dev_promisc_disable(struct rte_eth_dev *dev) 381f3de3840SIvan Malov { 382f3de3840SIvan Malov sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_FALSE); 383f3de3840SIvan Malov } 384f3de3840SIvan Malov 385f3de3840SIvan Malov static void 386f3de3840SIvan Malov sfc_dev_allmulti_enable(struct rte_eth_dev *dev) 387f3de3840SIvan Malov { 388f3de3840SIvan Malov sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_TRUE); 389f3de3840SIvan Malov } 390f3de3840SIvan Malov 391f3de3840SIvan Malov static void 392f3de3840SIvan Malov sfc_dev_allmulti_disable(struct rte_eth_dev *dev) 393f3de3840SIvan Malov { 394f3de3840SIvan Malov sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_FALSE); 395f3de3840SIvan Malov } 396f3de3840SIvan Malov 397ce35b05cSAndrew Rybchenko static int 398ce35b05cSAndrew Rybchenko sfc_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, 399ce35b05cSAndrew Rybchenko uint16_t nb_rx_desc, unsigned int socket_id, 400ce35b05cSAndrew Rybchenko const struct rte_eth_rxconf *rx_conf, 401ce35b05cSAndrew Rybchenko struct rte_mempool *mb_pool) 402ce35b05cSAndrew Rybchenko { 403dda791c2SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 4045313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 405ce35b05cSAndrew Rybchenko int rc; 406ce35b05cSAndrew Rybchenko 407ce35b05cSAndrew Rybchenko sfc_log_init(sa, "RxQ=%u nb_rx_desc=%u socket_id=%u", 408ce35b05cSAndrew Rybchenko rx_queue_id, nb_rx_desc, socket_id); 409ce35b05cSAndrew Rybchenko 410ce35b05cSAndrew Rybchenko sfc_adapter_lock(sa); 411ce35b05cSAndrew Rybchenko 412ce35b05cSAndrew Rybchenko rc = sfc_rx_qinit(sa, rx_queue_id, nb_rx_desc, socket_id, 413ce35b05cSAndrew Rybchenko rx_conf, mb_pool); 414ce35b05cSAndrew Rybchenko if (rc != 0) 415ce35b05cSAndrew Rybchenko goto fail_rx_qinit; 416ce35b05cSAndrew Rybchenko 417dda791c2SAndrew Rybchenko dev->data->rx_queues[rx_queue_id] = sas->rxq_info[rx_queue_id].dp; 418ce35b05cSAndrew Rybchenko 419ce35b05cSAndrew Rybchenko sfc_adapter_unlock(sa); 420ce35b05cSAndrew Rybchenko 421ce35b05cSAndrew Rybchenko return 0; 422ce35b05cSAndrew Rybchenko 423ce35b05cSAndrew Rybchenko fail_rx_qinit: 424ce35b05cSAndrew Rybchenko sfc_adapter_unlock(sa); 425ce35b05cSAndrew Rybchenko SFC_ASSERT(rc > 0); 426ce35b05cSAndrew Rybchenko return -rc; 427ce35b05cSAndrew Rybchenko } 428ce35b05cSAndrew Rybchenko 429ce35b05cSAndrew Rybchenko static void 430ce35b05cSAndrew Rybchenko sfc_rx_queue_release(void *queue) 431ce35b05cSAndrew Rybchenko { 432df1bfde4SAndrew Rybchenko struct sfc_dp_rxq *dp_rxq = queue; 433df1bfde4SAndrew Rybchenko struct sfc_rxq *rxq; 434ce35b05cSAndrew Rybchenko struct sfc_adapter *sa; 435ce35b05cSAndrew Rybchenko unsigned int sw_index; 436ce35b05cSAndrew Rybchenko 437df1bfde4SAndrew Rybchenko if (dp_rxq == NULL) 438ce35b05cSAndrew Rybchenko return; 439ce35b05cSAndrew Rybchenko 440df1bfde4SAndrew Rybchenko rxq = sfc_rxq_by_dp_rxq(dp_rxq); 441ce35b05cSAndrew Rybchenko sa = rxq->evq->sa; 442ce35b05cSAndrew Rybchenko sfc_adapter_lock(sa); 443ce35b05cSAndrew Rybchenko 4449f25da76SAndrew Rybchenko sw_index = dp_rxq->dpq.queue_id; 445ce35b05cSAndrew Rybchenko 446ce35b05cSAndrew Rybchenko sfc_log_init(sa, "RxQ=%u", sw_index); 447ce35b05cSAndrew Rybchenko 448ce35b05cSAndrew Rybchenko sfc_rx_qfini(sa, sw_index); 449ce35b05cSAndrew Rybchenko 450ce35b05cSAndrew Rybchenko sfc_adapter_unlock(sa); 451ce35b05cSAndrew Rybchenko } 452ce35b05cSAndrew Rybchenko 453b1b7ad93SIvan Malov static int 454b1b7ad93SIvan Malov sfc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, 455b1b7ad93SIvan Malov uint16_t nb_tx_desc, unsigned int socket_id, 456b1b7ad93SIvan Malov const struct rte_eth_txconf *tx_conf) 457b1b7ad93SIvan Malov { 458113a14a6SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 4595313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 460b1b7ad93SIvan Malov int rc; 461b1b7ad93SIvan Malov 462b1b7ad93SIvan Malov sfc_log_init(sa, "TxQ = %u, nb_tx_desc = %u, socket_id = %u", 463b1b7ad93SIvan Malov tx_queue_id, nb_tx_desc, socket_id); 464b1b7ad93SIvan Malov 465b1b7ad93SIvan Malov sfc_adapter_lock(sa); 466b1b7ad93SIvan Malov 467b1b7ad93SIvan Malov rc = sfc_tx_qinit(sa, tx_queue_id, nb_tx_desc, socket_id, tx_conf); 468b1b7ad93SIvan Malov if (rc != 0) 469b1b7ad93SIvan Malov goto fail_tx_qinit; 470b1b7ad93SIvan Malov 471113a14a6SAndrew Rybchenko dev->data->tx_queues[tx_queue_id] = sas->txq_info[tx_queue_id].dp; 472b1b7ad93SIvan Malov 473b1b7ad93SIvan Malov sfc_adapter_unlock(sa); 474b1b7ad93SIvan Malov return 0; 475b1b7ad93SIvan Malov 476b1b7ad93SIvan Malov fail_tx_qinit: 477b1b7ad93SIvan Malov sfc_adapter_unlock(sa); 478b1b7ad93SIvan Malov SFC_ASSERT(rc > 0); 479b1b7ad93SIvan Malov return -rc; 480b1b7ad93SIvan Malov } 481b1b7ad93SIvan Malov 482b1b7ad93SIvan Malov static void 483b1b7ad93SIvan Malov sfc_tx_queue_release(void *queue) 484b1b7ad93SIvan Malov { 485dbdc8241SAndrew Rybchenko struct sfc_dp_txq *dp_txq = queue; 486dbdc8241SAndrew Rybchenko struct sfc_txq *txq; 487b1b7ad93SIvan Malov unsigned int sw_index; 488b1b7ad93SIvan Malov struct sfc_adapter *sa; 489b1b7ad93SIvan Malov 490dbdc8241SAndrew Rybchenko if (dp_txq == NULL) 491b1b7ad93SIvan Malov return; 492b1b7ad93SIvan Malov 493dbdc8241SAndrew Rybchenko txq = sfc_txq_by_dp_txq(dp_txq); 494dbe26517SAndrew Rybchenko sw_index = dp_txq->dpq.queue_id; 495b1b7ad93SIvan Malov 496b1b7ad93SIvan Malov SFC_ASSERT(txq->evq != NULL); 497b1b7ad93SIvan Malov sa = txq->evq->sa; 498b1b7ad93SIvan Malov 499b1b7ad93SIvan Malov sfc_log_init(sa, "TxQ = %u", sw_index); 500b1b7ad93SIvan Malov 501b1b7ad93SIvan Malov sfc_adapter_lock(sa); 502b1b7ad93SIvan Malov 503b1b7ad93SIvan Malov sfc_tx_qfini(sa, sw_index); 504b1b7ad93SIvan Malov 505b1b7ad93SIvan Malov sfc_adapter_unlock(sa); 506b1b7ad93SIvan Malov } 507b1b7ad93SIvan Malov 508ab77a001SAndrew Rybchenko /* 509ab77a001SAndrew Rybchenko * Some statistics are computed as A - B where A and B each increase 510ab77a001SAndrew Rybchenko * monotonically with some hardware counter(s) and the counters are read 511ab77a001SAndrew Rybchenko * asynchronously. 512ab77a001SAndrew Rybchenko * 513ab77a001SAndrew Rybchenko * If packet X is counted in A, but not counted in B yet, computed value is 514ab77a001SAndrew Rybchenko * greater than real. 515ab77a001SAndrew Rybchenko * 516ab77a001SAndrew Rybchenko * If packet X is not counted in A at the moment of reading the counter, 517ab77a001SAndrew Rybchenko * but counted in B at the moment of reading the counter, computed value 518ab77a001SAndrew Rybchenko * is less than real. 519ab77a001SAndrew Rybchenko * 520ab77a001SAndrew Rybchenko * However, counter which grows backward is worse evil than slightly wrong 521ab77a001SAndrew Rybchenko * value. So, let's try to guarantee that it never happens except may be 522ab77a001SAndrew Rybchenko * the case when the MAC stats are zeroed as a result of a NIC reset. 523ab77a001SAndrew Rybchenko */ 524ab77a001SAndrew Rybchenko static void 525ab77a001SAndrew Rybchenko sfc_update_diff_stat(uint64_t *stat, uint64_t newval) 526ab77a001SAndrew Rybchenko { 527ab77a001SAndrew Rybchenko if ((int64_t)(newval - *stat) > 0 || newval == 0) 528ab77a001SAndrew Rybchenko *stat = newval; 529ab77a001SAndrew Rybchenko } 530ab77a001SAndrew Rybchenko 531d5b0924bSMatan Azrad static int 5321caab2f1SAndrew Rybchenko sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 5331caab2f1SAndrew Rybchenko { 5345313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 5351caab2f1SAndrew Rybchenko struct sfc_port *port = &sa->port; 5361caab2f1SAndrew Rybchenko uint64_t *mac_stats; 537d5b0924bSMatan Azrad int ret; 5381caab2f1SAndrew Rybchenko 5391caab2f1SAndrew Rybchenko rte_spinlock_lock(&port->mac_stats_lock); 5401caab2f1SAndrew Rybchenko 541d5b0924bSMatan Azrad ret = sfc_port_update_mac_stats(sa); 542d5b0924bSMatan Azrad if (ret != 0) 5431caab2f1SAndrew Rybchenko goto unlock; 5441caab2f1SAndrew Rybchenko 5451caab2f1SAndrew Rybchenko mac_stats = port->mac_stats_buf; 5461caab2f1SAndrew Rybchenko 5471caab2f1SAndrew Rybchenko if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, 5481caab2f1SAndrew Rybchenko EFX_MAC_VADAPTER_RX_UNICAST_PACKETS)) { 5491caab2f1SAndrew Rybchenko stats->ipackets = 5501caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_RX_UNICAST_PACKETS] + 5511caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_RX_MULTICAST_PACKETS] + 5521caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_RX_BROADCAST_PACKETS]; 5531caab2f1SAndrew Rybchenko stats->opackets = 5541caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_TX_UNICAST_PACKETS] + 5551caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_TX_MULTICAST_PACKETS] + 5561caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_TX_BROADCAST_PACKETS]; 5571caab2f1SAndrew Rybchenko stats->ibytes = 5581caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_RX_UNICAST_BYTES] + 5591caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_RX_MULTICAST_BYTES] + 5601caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_RX_BROADCAST_BYTES]; 5611caab2f1SAndrew Rybchenko stats->obytes = 5621caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_TX_UNICAST_BYTES] + 5631caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_TX_MULTICAST_BYTES] + 5641caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_VADAPTER_TX_BROADCAST_BYTES]; 56524f8a959SAndrew Rybchenko stats->imissed = mac_stats[EFX_MAC_VADAPTER_RX_BAD_PACKETS]; 5661caab2f1SAndrew Rybchenko stats->oerrors = mac_stats[EFX_MAC_VADAPTER_TX_BAD_PACKETS]; 5671caab2f1SAndrew Rybchenko } else { 5681caab2f1SAndrew Rybchenko stats->opackets = mac_stats[EFX_MAC_TX_PKTS]; 5691caab2f1SAndrew Rybchenko stats->ibytes = mac_stats[EFX_MAC_RX_OCTETS]; 5701caab2f1SAndrew Rybchenko stats->obytes = mac_stats[EFX_MAC_TX_OCTETS]; 5711caab2f1SAndrew Rybchenko /* 5721caab2f1SAndrew Rybchenko * Take into account stats which are whenever supported 5731caab2f1SAndrew Rybchenko * on EF10. If some stat is not supported by current 5741caab2f1SAndrew Rybchenko * firmware variant or HW revision, it is guaranteed 5751caab2f1SAndrew Rybchenko * to be zero in mac_stats. 5761caab2f1SAndrew Rybchenko */ 5771caab2f1SAndrew Rybchenko stats->imissed = 5781caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_RX_NODESC_DROP_CNT] + 5791caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_TRUNC_BB_OVERFLOW] + 5801caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_DISCARD_BB_OVERFLOW] + 5811caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_TRUNC_VFIFO_FULL] + 5821caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_DISCARD_VFIFO_FULL] + 5831caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_TRUNC_QBB] + 5841caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_DISCARD_QBB] + 5851caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_PM_DISCARD_MAPPING] + 5861caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_RXDP_Q_DISABLED_PKTS] + 5871caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_RXDP_DI_DROPPED_PKTS]; 5881caab2f1SAndrew Rybchenko stats->ierrors = 5891caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_RX_FCS_ERRORS] + 5901caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_RX_ALIGN_ERRORS] + 5911caab2f1SAndrew Rybchenko mac_stats[EFX_MAC_RX_JABBER_PKTS]; 5921caab2f1SAndrew Rybchenko /* no oerrors counters supported on EF10 */ 593ab77a001SAndrew Rybchenko 594ab77a001SAndrew Rybchenko /* Exclude missed, errors and pauses from Rx packets */ 595ab77a001SAndrew Rybchenko sfc_update_diff_stat(&port->ipackets, 596ab77a001SAndrew Rybchenko mac_stats[EFX_MAC_RX_PKTS] - 597ab77a001SAndrew Rybchenko mac_stats[EFX_MAC_RX_PAUSE_PKTS] - 598ab77a001SAndrew Rybchenko stats->imissed - stats->ierrors); 599ab77a001SAndrew Rybchenko stats->ipackets = port->ipackets; 6001caab2f1SAndrew Rybchenko } 6011caab2f1SAndrew Rybchenko 6021caab2f1SAndrew Rybchenko unlock: 6031caab2f1SAndrew Rybchenko rte_spinlock_unlock(&port->mac_stats_lock); 604d5b0924bSMatan Azrad SFC_ASSERT(ret >= 0); 605d5b0924bSMatan Azrad return -ret; 6061caab2f1SAndrew Rybchenko } 6071caab2f1SAndrew Rybchenko 608e8acb329SIvan Malov static void 609e8acb329SIvan Malov sfc_stats_reset(struct rte_eth_dev *dev) 610e8acb329SIvan Malov { 6115313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 612e8acb329SIvan Malov struct sfc_port *port = &sa->port; 613e8acb329SIvan Malov int rc; 614e8acb329SIvan Malov 615e8acb329SIvan Malov if (sa->state != SFC_ADAPTER_STARTED) { 616e8acb329SIvan Malov /* 617e8acb329SIvan Malov * The operation cannot be done if port is not started; it 618e8acb329SIvan Malov * will be scheduled to be done during the next port start 619e8acb329SIvan Malov */ 620e8acb329SIvan Malov port->mac_stats_reset_pending = B_TRUE; 621e8acb329SIvan Malov return; 622e8acb329SIvan Malov } 623e8acb329SIvan Malov 624e8acb329SIvan Malov rc = sfc_port_reset_mac_stats(sa); 625e8acb329SIvan Malov if (rc != 0) 626e8acb329SIvan Malov sfc_err(sa, "failed to reset statistics (rc = %d)", rc); 627e8acb329SIvan Malov } 628e8acb329SIvan Malov 6297b989176SAndrew Rybchenko static int 6307b989176SAndrew Rybchenko sfc_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, 6317b989176SAndrew Rybchenko unsigned int xstats_count) 6327b989176SAndrew Rybchenko { 6335313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 6347b989176SAndrew Rybchenko struct sfc_port *port = &sa->port; 6357b989176SAndrew Rybchenko uint64_t *mac_stats; 6367b989176SAndrew Rybchenko int rc; 6377b989176SAndrew Rybchenko unsigned int i; 6387b989176SAndrew Rybchenko int nstats = 0; 6397b989176SAndrew Rybchenko 6407b989176SAndrew Rybchenko rte_spinlock_lock(&port->mac_stats_lock); 6417b989176SAndrew Rybchenko 6427b989176SAndrew Rybchenko rc = sfc_port_update_mac_stats(sa); 6437b989176SAndrew Rybchenko if (rc != 0) { 6447b989176SAndrew Rybchenko SFC_ASSERT(rc > 0); 6457b989176SAndrew Rybchenko nstats = -rc; 6467b989176SAndrew Rybchenko goto unlock; 6477b989176SAndrew Rybchenko } 6487b989176SAndrew Rybchenko 6497b989176SAndrew Rybchenko mac_stats = port->mac_stats_buf; 6507b989176SAndrew Rybchenko 6517b989176SAndrew Rybchenko for (i = 0; i < EFX_MAC_NSTATS; ++i) { 6527b989176SAndrew Rybchenko if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) { 6537b989176SAndrew Rybchenko if (xstats != NULL && nstats < (int)xstats_count) { 6547b989176SAndrew Rybchenko xstats[nstats].id = nstats; 6557b989176SAndrew Rybchenko xstats[nstats].value = mac_stats[i]; 6567b989176SAndrew Rybchenko } 6577b989176SAndrew Rybchenko nstats++; 6587b989176SAndrew Rybchenko } 6597b989176SAndrew Rybchenko } 6607b989176SAndrew Rybchenko 6617b989176SAndrew Rybchenko unlock: 6627b989176SAndrew Rybchenko rte_spinlock_unlock(&port->mac_stats_lock); 6637b989176SAndrew Rybchenko 6647b989176SAndrew Rybchenko return nstats; 6657b989176SAndrew Rybchenko } 6667b989176SAndrew Rybchenko 6677b989176SAndrew Rybchenko static int 6687b989176SAndrew Rybchenko sfc_xstats_get_names(struct rte_eth_dev *dev, 6697b989176SAndrew Rybchenko struct rte_eth_xstat_name *xstats_names, 6707b989176SAndrew Rybchenko unsigned int xstats_count) 6717b989176SAndrew Rybchenko { 6725313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 6737b989176SAndrew Rybchenko struct sfc_port *port = &sa->port; 6747b989176SAndrew Rybchenko unsigned int i; 6757b989176SAndrew Rybchenko unsigned int nstats = 0; 6767b989176SAndrew Rybchenko 6777b989176SAndrew Rybchenko for (i = 0; i < EFX_MAC_NSTATS; ++i) { 6787b989176SAndrew Rybchenko if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) { 6797b989176SAndrew Rybchenko if (xstats_names != NULL && nstats < xstats_count) 680ed5b9848SAndy Green strlcpy(xstats_names[nstats].name, 6817b989176SAndrew Rybchenko efx_mac_stat_name(sa->nic, i), 6827b989176SAndrew Rybchenko sizeof(xstats_names[0].name)); 6837b989176SAndrew Rybchenko nstats++; 6847b989176SAndrew Rybchenko } 6857b989176SAndrew Rybchenko } 6867b989176SAndrew Rybchenko 6877b989176SAndrew Rybchenko return nstats; 6887b989176SAndrew Rybchenko } 6897b989176SAndrew Rybchenko 690cdbb29cfSAndrew Rybchenko static int 69173280c1eSIvan Malov sfc_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, 69273280c1eSIvan Malov uint64_t *values, unsigned int n) 69373280c1eSIvan Malov { 6945313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 69573280c1eSIvan Malov struct sfc_port *port = &sa->port; 69673280c1eSIvan Malov uint64_t *mac_stats; 69773280c1eSIvan Malov unsigned int nb_supported = 0; 69873280c1eSIvan Malov unsigned int nb_written = 0; 69973280c1eSIvan Malov unsigned int i; 70073280c1eSIvan Malov int ret; 70173280c1eSIvan Malov int rc; 70273280c1eSIvan Malov 70373280c1eSIvan Malov if (unlikely(values == NULL) || 70473280c1eSIvan Malov unlikely((ids == NULL) && (n < port->mac_stats_nb_supported))) 70573280c1eSIvan Malov return port->mac_stats_nb_supported; 70673280c1eSIvan Malov 70773280c1eSIvan Malov rte_spinlock_lock(&port->mac_stats_lock); 70873280c1eSIvan Malov 70973280c1eSIvan Malov rc = sfc_port_update_mac_stats(sa); 71073280c1eSIvan Malov if (rc != 0) { 71173280c1eSIvan Malov SFC_ASSERT(rc > 0); 71273280c1eSIvan Malov ret = -rc; 71373280c1eSIvan Malov goto unlock; 71473280c1eSIvan Malov } 71573280c1eSIvan Malov 71673280c1eSIvan Malov mac_stats = port->mac_stats_buf; 71773280c1eSIvan Malov 71873280c1eSIvan Malov for (i = 0; (i < EFX_MAC_NSTATS) && (nb_written < n); ++i) { 71973280c1eSIvan Malov if (!EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) 72073280c1eSIvan Malov continue; 72173280c1eSIvan Malov 72273280c1eSIvan Malov if ((ids == NULL) || (ids[nb_written] == nb_supported)) 72373280c1eSIvan Malov values[nb_written++] = mac_stats[i]; 72473280c1eSIvan Malov 72573280c1eSIvan Malov ++nb_supported; 72673280c1eSIvan Malov } 72773280c1eSIvan Malov 72873280c1eSIvan Malov ret = nb_written; 72973280c1eSIvan Malov 73073280c1eSIvan Malov unlock: 73173280c1eSIvan Malov rte_spinlock_unlock(&port->mac_stats_lock); 73273280c1eSIvan Malov 73373280c1eSIvan Malov return ret; 73473280c1eSIvan Malov } 73573280c1eSIvan Malov 73673280c1eSIvan Malov static int 73773280c1eSIvan Malov sfc_xstats_get_names_by_id(struct rte_eth_dev *dev, 73873280c1eSIvan Malov struct rte_eth_xstat_name *xstats_names, 73973280c1eSIvan Malov const uint64_t *ids, unsigned int size) 74073280c1eSIvan Malov { 7415313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 74273280c1eSIvan Malov struct sfc_port *port = &sa->port; 74373280c1eSIvan Malov unsigned int nb_supported = 0; 74473280c1eSIvan Malov unsigned int nb_written = 0; 74573280c1eSIvan Malov unsigned int i; 74673280c1eSIvan Malov 74773280c1eSIvan Malov if (unlikely(xstats_names == NULL) || 74873280c1eSIvan Malov unlikely((ids == NULL) && (size < port->mac_stats_nb_supported))) 74973280c1eSIvan Malov return port->mac_stats_nb_supported; 75073280c1eSIvan Malov 75173280c1eSIvan Malov for (i = 0; (i < EFX_MAC_NSTATS) && (nb_written < size); ++i) { 75273280c1eSIvan Malov if (!EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) 75373280c1eSIvan Malov continue; 75473280c1eSIvan Malov 75573280c1eSIvan Malov if ((ids == NULL) || (ids[nb_written] == nb_supported)) { 75673280c1eSIvan Malov char *name = xstats_names[nb_written++].name; 75773280c1eSIvan Malov 758ed5b9848SAndy Green strlcpy(name, efx_mac_stat_name(sa->nic, i), 75973280c1eSIvan Malov sizeof(xstats_names[0].name)); 76073280c1eSIvan Malov } 76173280c1eSIvan Malov 76273280c1eSIvan Malov ++nb_supported; 76373280c1eSIvan Malov } 76473280c1eSIvan Malov 76573280c1eSIvan Malov return nb_written; 76673280c1eSIvan Malov } 76773280c1eSIvan Malov 76873280c1eSIvan Malov static int 769cdbb29cfSAndrew Rybchenko sfc_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 770cdbb29cfSAndrew Rybchenko { 7715313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 772cdbb29cfSAndrew Rybchenko unsigned int wanted_fc, link_fc; 773cdbb29cfSAndrew Rybchenko 774cdbb29cfSAndrew Rybchenko memset(fc_conf, 0, sizeof(*fc_conf)); 775cdbb29cfSAndrew Rybchenko 776cdbb29cfSAndrew Rybchenko sfc_adapter_lock(sa); 777cdbb29cfSAndrew Rybchenko 778cdbb29cfSAndrew Rybchenko if (sa->state == SFC_ADAPTER_STARTED) 779cdbb29cfSAndrew Rybchenko efx_mac_fcntl_get(sa->nic, &wanted_fc, &link_fc); 780cdbb29cfSAndrew Rybchenko else 781cdbb29cfSAndrew Rybchenko link_fc = sa->port.flow_ctrl; 782cdbb29cfSAndrew Rybchenko 783cdbb29cfSAndrew Rybchenko switch (link_fc) { 784cdbb29cfSAndrew Rybchenko case 0: 785cdbb29cfSAndrew Rybchenko fc_conf->mode = RTE_FC_NONE; 786cdbb29cfSAndrew Rybchenko break; 787cdbb29cfSAndrew Rybchenko case EFX_FCNTL_RESPOND: 788cdbb29cfSAndrew Rybchenko fc_conf->mode = RTE_FC_RX_PAUSE; 789cdbb29cfSAndrew Rybchenko break; 790cdbb29cfSAndrew Rybchenko case EFX_FCNTL_GENERATE: 791cdbb29cfSAndrew Rybchenko fc_conf->mode = RTE_FC_TX_PAUSE; 792cdbb29cfSAndrew Rybchenko break; 793cdbb29cfSAndrew Rybchenko case (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE): 794cdbb29cfSAndrew Rybchenko fc_conf->mode = RTE_FC_FULL; 795cdbb29cfSAndrew Rybchenko break; 796cdbb29cfSAndrew Rybchenko default: 797cdbb29cfSAndrew Rybchenko sfc_err(sa, "%s: unexpected flow control value %#x", 798cdbb29cfSAndrew Rybchenko __func__, link_fc); 799cdbb29cfSAndrew Rybchenko } 800cdbb29cfSAndrew Rybchenko 801cdbb29cfSAndrew Rybchenko fc_conf->autoneg = sa->port.flow_ctrl_autoneg; 802cdbb29cfSAndrew Rybchenko 803cdbb29cfSAndrew Rybchenko sfc_adapter_unlock(sa); 804cdbb29cfSAndrew Rybchenko 805cdbb29cfSAndrew Rybchenko return 0; 806cdbb29cfSAndrew Rybchenko } 807cdbb29cfSAndrew Rybchenko 808cdbb29cfSAndrew Rybchenko static int 809cdbb29cfSAndrew Rybchenko sfc_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 810cdbb29cfSAndrew Rybchenko { 8115313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 812cdbb29cfSAndrew Rybchenko struct sfc_port *port = &sa->port; 813cdbb29cfSAndrew Rybchenko unsigned int fcntl; 814cdbb29cfSAndrew Rybchenko int rc; 815cdbb29cfSAndrew Rybchenko 816cdbb29cfSAndrew Rybchenko if (fc_conf->high_water != 0 || fc_conf->low_water != 0 || 817cdbb29cfSAndrew Rybchenko fc_conf->pause_time != 0 || fc_conf->send_xon != 0 || 818cdbb29cfSAndrew Rybchenko fc_conf->mac_ctrl_frame_fwd != 0) { 819cdbb29cfSAndrew Rybchenko sfc_err(sa, "unsupported flow control settings specified"); 820cdbb29cfSAndrew Rybchenko rc = EINVAL; 821cdbb29cfSAndrew Rybchenko goto fail_inval; 822cdbb29cfSAndrew Rybchenko } 823cdbb29cfSAndrew Rybchenko 824cdbb29cfSAndrew Rybchenko switch (fc_conf->mode) { 825cdbb29cfSAndrew Rybchenko case RTE_FC_NONE: 826cdbb29cfSAndrew Rybchenko fcntl = 0; 827cdbb29cfSAndrew Rybchenko break; 828cdbb29cfSAndrew Rybchenko case RTE_FC_RX_PAUSE: 829cdbb29cfSAndrew Rybchenko fcntl = EFX_FCNTL_RESPOND; 830cdbb29cfSAndrew Rybchenko break; 831cdbb29cfSAndrew Rybchenko case RTE_FC_TX_PAUSE: 832cdbb29cfSAndrew Rybchenko fcntl = EFX_FCNTL_GENERATE; 833cdbb29cfSAndrew Rybchenko break; 834cdbb29cfSAndrew Rybchenko case RTE_FC_FULL: 835cdbb29cfSAndrew Rybchenko fcntl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 836cdbb29cfSAndrew Rybchenko break; 837cdbb29cfSAndrew Rybchenko default: 838cdbb29cfSAndrew Rybchenko rc = EINVAL; 839cdbb29cfSAndrew Rybchenko goto fail_inval; 840cdbb29cfSAndrew Rybchenko } 841cdbb29cfSAndrew Rybchenko 842cdbb29cfSAndrew Rybchenko sfc_adapter_lock(sa); 843cdbb29cfSAndrew Rybchenko 844cdbb29cfSAndrew Rybchenko if (sa->state == SFC_ADAPTER_STARTED) { 845cdbb29cfSAndrew Rybchenko rc = efx_mac_fcntl_set(sa->nic, fcntl, fc_conf->autoneg); 846cdbb29cfSAndrew Rybchenko if (rc != 0) 847cdbb29cfSAndrew Rybchenko goto fail_mac_fcntl_set; 848cdbb29cfSAndrew Rybchenko } 849cdbb29cfSAndrew Rybchenko 850cdbb29cfSAndrew Rybchenko port->flow_ctrl = fcntl; 851cdbb29cfSAndrew Rybchenko port->flow_ctrl_autoneg = fc_conf->autoneg; 852cdbb29cfSAndrew Rybchenko 853cdbb29cfSAndrew Rybchenko sfc_adapter_unlock(sa); 854cdbb29cfSAndrew Rybchenko 855cdbb29cfSAndrew Rybchenko return 0; 856cdbb29cfSAndrew Rybchenko 857cdbb29cfSAndrew Rybchenko fail_mac_fcntl_set: 858cdbb29cfSAndrew Rybchenko sfc_adapter_unlock(sa); 859cdbb29cfSAndrew Rybchenko fail_inval: 860cdbb29cfSAndrew Rybchenko SFC_ASSERT(rc > 0); 861cdbb29cfSAndrew Rybchenko return -rc; 862cdbb29cfSAndrew Rybchenko } 863cdbb29cfSAndrew Rybchenko 864e961cf42SAndrew Rybchenko static int 865e961cf42SAndrew Rybchenko sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 866e961cf42SAndrew Rybchenko { 8675313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 868e961cf42SAndrew Rybchenko size_t pdu = EFX_MAC_PDU(mtu); 869e961cf42SAndrew Rybchenko size_t old_pdu; 870e961cf42SAndrew Rybchenko int rc; 871e961cf42SAndrew Rybchenko 872e961cf42SAndrew Rybchenko sfc_log_init(sa, "mtu=%u", mtu); 873e961cf42SAndrew Rybchenko 874e961cf42SAndrew Rybchenko rc = EINVAL; 875e961cf42SAndrew Rybchenko if (pdu < EFX_MAC_PDU_MIN) { 876e961cf42SAndrew Rybchenko sfc_err(sa, "too small MTU %u (PDU size %u less than min %u)", 877e961cf42SAndrew Rybchenko (unsigned int)mtu, (unsigned int)pdu, 878e961cf42SAndrew Rybchenko EFX_MAC_PDU_MIN); 879e961cf42SAndrew Rybchenko goto fail_inval; 880e961cf42SAndrew Rybchenko } 881e961cf42SAndrew Rybchenko if (pdu > EFX_MAC_PDU_MAX) { 882e961cf42SAndrew Rybchenko sfc_err(sa, "too big MTU %u (PDU size %u greater than max %u)", 883e961cf42SAndrew Rybchenko (unsigned int)mtu, (unsigned int)pdu, 884e961cf42SAndrew Rybchenko EFX_MAC_PDU_MAX); 885e961cf42SAndrew Rybchenko goto fail_inval; 886e961cf42SAndrew Rybchenko } 887e961cf42SAndrew Rybchenko 888e961cf42SAndrew Rybchenko sfc_adapter_lock(sa); 889e961cf42SAndrew Rybchenko 890e961cf42SAndrew Rybchenko if (pdu != sa->port.pdu) { 891e961cf42SAndrew Rybchenko if (sa->state == SFC_ADAPTER_STARTED) { 892e961cf42SAndrew Rybchenko sfc_stop(sa); 893e961cf42SAndrew Rybchenko 894e961cf42SAndrew Rybchenko old_pdu = sa->port.pdu; 895e961cf42SAndrew Rybchenko sa->port.pdu = pdu; 896e961cf42SAndrew Rybchenko rc = sfc_start(sa); 897e961cf42SAndrew Rybchenko if (rc != 0) 898e961cf42SAndrew Rybchenko goto fail_start; 899e961cf42SAndrew Rybchenko } else { 900e961cf42SAndrew Rybchenko sa->port.pdu = pdu; 901e961cf42SAndrew Rybchenko } 902e961cf42SAndrew Rybchenko } 903e961cf42SAndrew Rybchenko 904e961cf42SAndrew Rybchenko /* 905ab3ce1e0SFerruh Yigit * The driver does not use it, but other PMDs update jumbo frame 906e961cf42SAndrew Rybchenko * flag and max_rx_pkt_len when MTU is set. 907e961cf42SAndrew Rybchenko */ 908ff6a1197SIvan Malov if (mtu > ETHER_MAX_LEN) { 909ff6a1197SIvan Malov struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; 910ff6a1197SIvan Malov rxmode->offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; 911ff6a1197SIvan Malov } 912ff6a1197SIvan Malov 913e961cf42SAndrew Rybchenko dev->data->dev_conf.rxmode.max_rx_pkt_len = sa->port.pdu; 914e961cf42SAndrew Rybchenko 915e961cf42SAndrew Rybchenko sfc_adapter_unlock(sa); 916e961cf42SAndrew Rybchenko 917e961cf42SAndrew Rybchenko sfc_log_init(sa, "done"); 918e961cf42SAndrew Rybchenko return 0; 919e961cf42SAndrew Rybchenko 920e961cf42SAndrew Rybchenko fail_start: 921e961cf42SAndrew Rybchenko sa->port.pdu = old_pdu; 922e961cf42SAndrew Rybchenko if (sfc_start(sa) != 0) 923e961cf42SAndrew Rybchenko sfc_err(sa, "cannot start with neither new (%u) nor old (%u) " 924e961cf42SAndrew Rybchenko "PDU max size - port is stopped", 925e961cf42SAndrew Rybchenko (unsigned int)pdu, (unsigned int)old_pdu); 926e961cf42SAndrew Rybchenko sfc_adapter_unlock(sa); 927e961cf42SAndrew Rybchenko 928e961cf42SAndrew Rybchenko fail_inval: 929e961cf42SAndrew Rybchenko sfc_log_init(sa, "failed %d", rc); 930e961cf42SAndrew Rybchenko SFC_ASSERT(rc > 0); 931e961cf42SAndrew Rybchenko return -rc; 932e961cf42SAndrew Rybchenko } 933caccf8b3SOlivier Matz static int 934c100fd46SIvan Malov sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) 935c100fd46SIvan Malov { 9365313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 937c100fd46SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 93884a9b481SIvan Malov struct sfc_port *port = &sa->port; 939caccf8b3SOlivier Matz struct ether_addr *old_addr = &dev->data->mac_addrs[0]; 940caccf8b3SOlivier Matz int rc = 0; 941c100fd46SIvan Malov 942c100fd46SIvan Malov sfc_adapter_lock(sa); 943c100fd46SIvan Malov 944642088ddSIvan Malov /* 945642088ddSIvan Malov * Copy the address to the device private data so that 946642088ddSIvan Malov * it could be recalled in the case of adapter restart. 947642088ddSIvan Malov */ 948642088ddSIvan Malov ether_addr_copy(mac_addr, &port->default_mac_addr); 949642088ddSIvan Malov 950caccf8b3SOlivier Matz /* 951caccf8b3SOlivier Matz * Neither of the two following checks can return 952caccf8b3SOlivier Matz * an error. The new MAC address is preserved in 953caccf8b3SOlivier Matz * the device private data and can be activated 954caccf8b3SOlivier Matz * on the next port start if the user prevents 955caccf8b3SOlivier Matz * isolated mode from being enabled. 956caccf8b3SOlivier Matz */ 957e0d5ba7eSAndrew Rybchenko if (sfc_sa2shared(sa)->isolated) { 958caccf8b3SOlivier Matz sfc_warn(sa, "isolated mode is active on the port"); 959caccf8b3SOlivier Matz sfc_warn(sa, "will not set MAC address"); 96084a9b481SIvan Malov goto unlock; 96184a9b481SIvan Malov } 96284a9b481SIvan Malov 963c100fd46SIvan Malov if (sa->state != SFC_ADAPTER_STARTED) { 96491d16276SIvan Malov sfc_notice(sa, "the port is not started"); 96591d16276SIvan Malov sfc_notice(sa, "the new MAC address will be set on port start"); 966c100fd46SIvan Malov 967c100fd46SIvan Malov goto unlock; 968c100fd46SIvan Malov } 969c100fd46SIvan Malov 970c100fd46SIvan Malov if (encp->enc_allow_set_mac_with_installed_filters) { 971c100fd46SIvan Malov rc = efx_mac_addr_set(sa->nic, mac_addr->addr_bytes); 972c100fd46SIvan Malov if (rc != 0) { 973c100fd46SIvan Malov sfc_err(sa, "cannot set MAC address (rc = %u)", rc); 974c100fd46SIvan Malov goto unlock; 975c100fd46SIvan Malov } 976c100fd46SIvan Malov 977c100fd46SIvan Malov /* 978c100fd46SIvan Malov * Changing the MAC address by means of MCDI request 979c100fd46SIvan Malov * has no effect on received traffic, therefore 980c100fd46SIvan Malov * we also need to update unicast filters 981c100fd46SIvan Malov */ 982c100fd46SIvan Malov rc = sfc_set_rx_mode(sa); 983caccf8b3SOlivier Matz if (rc != 0) { 984c100fd46SIvan Malov sfc_err(sa, "cannot set filter (rc = %u)", rc); 985caccf8b3SOlivier Matz /* Rollback the old address */ 986caccf8b3SOlivier Matz (void)efx_mac_addr_set(sa->nic, old_addr->addr_bytes); 987caccf8b3SOlivier Matz (void)sfc_set_rx_mode(sa); 988caccf8b3SOlivier Matz } 989c100fd46SIvan Malov } else { 990c100fd46SIvan Malov sfc_warn(sa, "cannot set MAC address with filters installed"); 991c100fd46SIvan Malov sfc_warn(sa, "adapter will be restarted to pick the new MAC"); 992c100fd46SIvan Malov sfc_warn(sa, "(some traffic may be dropped)"); 993c100fd46SIvan Malov 994c100fd46SIvan Malov /* 995c100fd46SIvan Malov * Since setting MAC address with filters installed is not 996642088ddSIvan Malov * allowed on the adapter, the new MAC address will be set 997642088ddSIvan Malov * by means of adapter restart. sfc_start() shall retrieve 998642088ddSIvan Malov * the new address from the device private data and set it. 999c100fd46SIvan Malov */ 1000c100fd46SIvan Malov sfc_stop(sa); 1001c100fd46SIvan Malov rc = sfc_start(sa); 1002c100fd46SIvan Malov if (rc != 0) 1003c100fd46SIvan Malov sfc_err(sa, "cannot restart adapter (rc = %u)", rc); 1004c100fd46SIvan Malov } 1005c100fd46SIvan Malov 1006c100fd46SIvan Malov unlock: 1007caccf8b3SOlivier Matz if (rc != 0) 1008caccf8b3SOlivier Matz ether_addr_copy(old_addr, &port->default_mac_addr); 1009caccf8b3SOlivier Matz 1010c100fd46SIvan Malov sfc_adapter_unlock(sa); 1011caccf8b3SOlivier Matz 1012caccf8b3SOlivier Matz SFC_ASSERT(rc >= 0); 1013caccf8b3SOlivier Matz return -rc; 1014c100fd46SIvan Malov } 1015c100fd46SIvan Malov 1016e961cf42SAndrew Rybchenko 10170fa0070eSIvan Malov static int 10180fa0070eSIvan Malov sfc_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, 10190fa0070eSIvan Malov uint32_t nb_mc_addr) 10200fa0070eSIvan Malov { 10215313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1022295f647aSIvan Malov struct sfc_port *port = &sa->port; 1023295f647aSIvan Malov uint8_t *mc_addrs = port->mcast_addrs; 10240fa0070eSIvan Malov int rc; 10250fa0070eSIvan Malov unsigned int i; 10260fa0070eSIvan Malov 1027e0d5ba7eSAndrew Rybchenko if (sfc_sa2shared(sa)->isolated) { 102884a9b481SIvan Malov sfc_err(sa, "isolated mode is active on the port"); 102984a9b481SIvan Malov sfc_err(sa, "will not set multicast address list"); 103084a9b481SIvan Malov return -ENOTSUP; 103184a9b481SIvan Malov } 103284a9b481SIvan Malov 1033295f647aSIvan Malov if (mc_addrs == NULL) 1034295f647aSIvan Malov return -ENOBUFS; 1035295f647aSIvan Malov 1036295f647aSIvan Malov if (nb_mc_addr > port->max_mcast_addrs) { 10370fa0070eSIvan Malov sfc_err(sa, "too many multicast addresses: %u > %u", 1038295f647aSIvan Malov nb_mc_addr, port->max_mcast_addrs); 10390fa0070eSIvan Malov return -EINVAL; 10400fa0070eSIvan Malov } 10410fa0070eSIvan Malov 10420fa0070eSIvan Malov for (i = 0; i < nb_mc_addr; ++i) { 1043b171936cSStephen Hemminger rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes, 10440fa0070eSIvan Malov EFX_MAC_ADDR_LEN); 10450fa0070eSIvan Malov mc_addrs += EFX_MAC_ADDR_LEN; 10460fa0070eSIvan Malov } 10470fa0070eSIvan Malov 1048295f647aSIvan Malov port->nb_mcast_addrs = nb_mc_addr; 10490fa0070eSIvan Malov 1050295f647aSIvan Malov if (sa->state != SFC_ADAPTER_STARTED) 1051295f647aSIvan Malov return 0; 10520fa0070eSIvan Malov 1053295f647aSIvan Malov rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs, 1054295f647aSIvan Malov port->nb_mcast_addrs); 10550fa0070eSIvan Malov if (rc != 0) 10560fa0070eSIvan Malov sfc_err(sa, "cannot set multicast address list (rc = %u)", rc); 10570fa0070eSIvan Malov 1058d0dcfe98SAndrew Rybchenko SFC_ASSERT(rc >= 0); 10590fa0070eSIvan Malov return -rc; 10600fa0070eSIvan Malov } 10610fa0070eSIvan Malov 1062f28ede50SAndrew Rybchenko /* 1063f28ede50SAndrew Rybchenko * The function is used by the secondary process as well. It must not 1064f28ede50SAndrew Rybchenko * use any process-local pointers from the adapter data. 1065f28ede50SAndrew Rybchenko */ 10665502e397SAndrew Rybchenko static void 10675502e397SAndrew Rybchenko sfc_rx_queue_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id, 10685502e397SAndrew Rybchenko struct rte_eth_rxq_info *qinfo) 10695502e397SAndrew Rybchenko { 1070dda791c2SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 10715502e397SAndrew Rybchenko struct sfc_rxq_info *rxq_info; 10725502e397SAndrew Rybchenko 1073dda791c2SAndrew Rybchenko SFC_ASSERT(rx_queue_id < sas->rxq_count); 10745502e397SAndrew Rybchenko 1075dda791c2SAndrew Rybchenko rxq_info = &sas->rxq_info[rx_queue_id]; 10765502e397SAndrew Rybchenko 10775befcecbSAndrew Rybchenko qinfo->mp = rxq_info->refill_mb_pool; 10785befcecbSAndrew Rybchenko qinfo->conf.rx_free_thresh = rxq_info->refill_threshold; 10795502e397SAndrew Rybchenko qinfo->conf.rx_drop_en = 1; 1080ac7af396SAndrew Rybchenko qinfo->conf.rx_deferred_start = rxq_info->deferred_start; 1081b7294d88SAndrew Rybchenko qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads; 1082ff6a1197SIvan Malov if (rxq_info->type_flags & EFX_RXQ_FLAG_SCATTER) { 1083ff6a1197SIvan Malov qinfo->conf.offloads |= DEV_RX_OFFLOAD_SCATTER; 1084ff6a1197SIvan Malov qinfo->scattered_rx = 1; 1085ff6a1197SIvan Malov } 10865502e397SAndrew Rybchenko qinfo->nb_desc = rxq_info->entries; 10875502e397SAndrew Rybchenko } 10885502e397SAndrew Rybchenko 1089f28ede50SAndrew Rybchenko /* 1090f28ede50SAndrew Rybchenko * The function is used by the secondary process as well. It must not 1091f28ede50SAndrew Rybchenko * use any process-local pointers from the adapter data. 1092f28ede50SAndrew Rybchenko */ 1093c5938838SIvan Malov static void 1094c5938838SIvan Malov sfc_tx_queue_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id, 1095c5938838SIvan Malov struct rte_eth_txq_info *qinfo) 1096c5938838SIvan Malov { 1097113a14a6SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 1098c5938838SIvan Malov struct sfc_txq_info *txq_info; 1099c5938838SIvan Malov 1100113a14a6SAndrew Rybchenko SFC_ASSERT(tx_queue_id < sas->txq_count); 1101c5938838SIvan Malov 1102113a14a6SAndrew Rybchenko txq_info = &sas->txq_info[tx_queue_id]; 1103c5938838SIvan Malov 1104c5938838SIvan Malov memset(qinfo, 0, sizeof(*qinfo)); 1105c5938838SIvan Malov 1106b57870f2SAndrew Rybchenko qinfo->conf.offloads = txq_info->offloads; 1107b57870f2SAndrew Rybchenko qinfo->conf.tx_free_thresh = txq_info->free_thresh; 1108c6a1d9b5SIvan Malov qinfo->conf.tx_deferred_start = txq_info->deferred_start; 1109c5938838SIvan Malov qinfo->nb_desc = txq_info->entries; 1110c5938838SIvan Malov } 1111c5938838SIvan Malov 1112b76e1b2cSAndrew Rybchenko /* 1113b76e1b2cSAndrew Rybchenko * The function is used by the secondary process as well. It must not 1114b76e1b2cSAndrew Rybchenko * use any process-local pointers from the adapter data. 1115b76e1b2cSAndrew Rybchenko */ 111604aa6b9cSAndrew Rybchenko static uint32_t 111704aa6b9cSAndrew Rybchenko sfc_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) 111804aa6b9cSAndrew Rybchenko { 11195dec95e3SAndrew Rybchenko const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev); 1120dda791c2SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 11212e42d78dSAndrew Rybchenko struct sfc_rxq_info *rxq_info; 112204aa6b9cSAndrew Rybchenko 1123dda791c2SAndrew Rybchenko SFC_ASSERT(rx_queue_id < sas->rxq_count); 1124dda791c2SAndrew Rybchenko rxq_info = &sas->rxq_info[rx_queue_id]; 1125768629c6SAndrew Rybchenko 1126bfea01bcSAndrew Rybchenko if ((rxq_info->state & SFC_RXQ_STARTED) == 0) 1127768629c6SAndrew Rybchenko return 0; 1128768629c6SAndrew Rybchenko 1129bfea01bcSAndrew Rybchenko return sap->dp_rx->qdesc_npending(rxq_info->dp); 113004aa6b9cSAndrew Rybchenko } 113104aa6b9cSAndrew Rybchenko 1132b76e1b2cSAndrew Rybchenko /* 1133b76e1b2cSAndrew Rybchenko * The function is used by the secondary process as well. It must not 1134b76e1b2cSAndrew Rybchenko * use any process-local pointers from the adapter data. 1135b76e1b2cSAndrew Rybchenko */ 113636d84f87SAndrew Rybchenko static int 113736d84f87SAndrew Rybchenko sfc_rx_descriptor_done(void *queue, uint16_t offset) 113836d84f87SAndrew Rybchenko { 1139df1bfde4SAndrew Rybchenko struct sfc_dp_rxq *dp_rxq = queue; 1140b76e1b2cSAndrew Rybchenko const struct sfc_dp_rx *dp_rx; 114136d84f87SAndrew Rybchenko 1142b76e1b2cSAndrew Rybchenko dp_rx = sfc_dp_rx_by_dp_rxq(dp_rxq); 1143b76e1b2cSAndrew Rybchenko 1144b76e1b2cSAndrew Rybchenko return offset < dp_rx->qdesc_npending(dp_rxq); 114536d84f87SAndrew Rybchenko } 114636d84f87SAndrew Rybchenko 1147b76e1b2cSAndrew Rybchenko /* 1148b76e1b2cSAndrew Rybchenko * The function is used by the secondary process as well. It must not 1149b76e1b2cSAndrew Rybchenko * use any process-local pointers from the adapter data. 1150b76e1b2cSAndrew Rybchenko */ 1151ac7af396SAndrew Rybchenko static int 11521d8f3a80SIvan Malov sfc_rx_descriptor_status(void *queue, uint16_t offset) 11531d8f3a80SIvan Malov { 11541d8f3a80SIvan Malov struct sfc_dp_rxq *dp_rxq = queue; 1155b76e1b2cSAndrew Rybchenko const struct sfc_dp_rx *dp_rx; 11561d8f3a80SIvan Malov 1157b76e1b2cSAndrew Rybchenko dp_rx = sfc_dp_rx_by_dp_rxq(dp_rxq); 1158b76e1b2cSAndrew Rybchenko 1159b76e1b2cSAndrew Rybchenko return dp_rx->qdesc_status(dp_rxq, offset); 11601d8f3a80SIvan Malov } 11611d8f3a80SIvan Malov 11623cf4b9c2SAndrew Rybchenko /* 11633cf4b9c2SAndrew Rybchenko * The function is used by the secondary process as well. It must not 11643cf4b9c2SAndrew Rybchenko * use any process-local pointers from the adapter data. 11653cf4b9c2SAndrew Rybchenko */ 11661d8f3a80SIvan Malov static int 11677df6f854SIvan Malov sfc_tx_descriptor_status(void *queue, uint16_t offset) 11687df6f854SIvan Malov { 11697df6f854SIvan Malov struct sfc_dp_txq *dp_txq = queue; 11703cf4b9c2SAndrew Rybchenko const struct sfc_dp_tx *dp_tx; 11717df6f854SIvan Malov 11723cf4b9c2SAndrew Rybchenko dp_tx = sfc_dp_tx_by_dp_txq(dp_txq); 11733cf4b9c2SAndrew Rybchenko 11743cf4b9c2SAndrew Rybchenko return dp_tx->qdesc_status(dp_txq, offset); 11757df6f854SIvan Malov } 11767df6f854SIvan Malov 11777df6f854SIvan Malov static int 1178ac7af396SAndrew Rybchenko sfc_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) 1179ac7af396SAndrew Rybchenko { 1180dda791c2SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 11815313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1182ac7af396SAndrew Rybchenko int rc; 1183ac7af396SAndrew Rybchenko 1184ac7af396SAndrew Rybchenko sfc_log_init(sa, "RxQ=%u", rx_queue_id); 1185ac7af396SAndrew Rybchenko 1186ac7af396SAndrew Rybchenko sfc_adapter_lock(sa); 1187ac7af396SAndrew Rybchenko 1188ac7af396SAndrew Rybchenko rc = EINVAL; 1189ac7af396SAndrew Rybchenko if (sa->state != SFC_ADAPTER_STARTED) 1190ac7af396SAndrew Rybchenko goto fail_not_started; 1191ac7af396SAndrew Rybchenko 1192dda791c2SAndrew Rybchenko if (sas->rxq_info[rx_queue_id].state != SFC_RXQ_INITIALIZED) 11930668a27aSIgor Romanov goto fail_not_setup; 11940668a27aSIgor Romanov 1195ac7af396SAndrew Rybchenko rc = sfc_rx_qstart(sa, rx_queue_id); 1196ac7af396SAndrew Rybchenko if (rc != 0) 1197ac7af396SAndrew Rybchenko goto fail_rx_qstart; 1198ac7af396SAndrew Rybchenko 1199dda791c2SAndrew Rybchenko sas->rxq_info[rx_queue_id].deferred_started = B_TRUE; 1200ac7af396SAndrew Rybchenko 1201ac7af396SAndrew Rybchenko sfc_adapter_unlock(sa); 1202ac7af396SAndrew Rybchenko 1203ac7af396SAndrew Rybchenko return 0; 1204ac7af396SAndrew Rybchenko 1205ac7af396SAndrew Rybchenko fail_rx_qstart: 12060668a27aSIgor Romanov fail_not_setup: 1207ac7af396SAndrew Rybchenko fail_not_started: 1208ac7af396SAndrew Rybchenko sfc_adapter_unlock(sa); 1209ac7af396SAndrew Rybchenko SFC_ASSERT(rc > 0); 1210ac7af396SAndrew Rybchenko return -rc; 1211ac7af396SAndrew Rybchenko } 1212ac7af396SAndrew Rybchenko 1213ac7af396SAndrew Rybchenko static int 1214ac7af396SAndrew Rybchenko sfc_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) 1215ac7af396SAndrew Rybchenko { 1216dda791c2SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 12175313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1218ac7af396SAndrew Rybchenko 1219ac7af396SAndrew Rybchenko sfc_log_init(sa, "RxQ=%u", rx_queue_id); 1220ac7af396SAndrew Rybchenko 1221ac7af396SAndrew Rybchenko sfc_adapter_lock(sa); 1222ac7af396SAndrew Rybchenko sfc_rx_qstop(sa, rx_queue_id); 1223ac7af396SAndrew Rybchenko 1224dda791c2SAndrew Rybchenko sas->rxq_info[rx_queue_id].deferred_started = B_FALSE; 1225ac7af396SAndrew Rybchenko 1226ac7af396SAndrew Rybchenko sfc_adapter_unlock(sa); 1227ac7af396SAndrew Rybchenko 1228ac7af396SAndrew Rybchenko return 0; 1229ac7af396SAndrew Rybchenko } 1230ac7af396SAndrew Rybchenko 1231c6a1d9b5SIvan Malov static int 1232c6a1d9b5SIvan Malov sfc_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) 1233c6a1d9b5SIvan Malov { 1234113a14a6SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 12355313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1236c6a1d9b5SIvan Malov int rc; 1237c6a1d9b5SIvan Malov 1238c6a1d9b5SIvan Malov sfc_log_init(sa, "TxQ = %u", tx_queue_id); 1239c6a1d9b5SIvan Malov 1240c6a1d9b5SIvan Malov sfc_adapter_lock(sa); 1241c6a1d9b5SIvan Malov 1242c6a1d9b5SIvan Malov rc = EINVAL; 1243c6a1d9b5SIvan Malov if (sa->state != SFC_ADAPTER_STARTED) 1244c6a1d9b5SIvan Malov goto fail_not_started; 1245c6a1d9b5SIvan Malov 1246113a14a6SAndrew Rybchenko if (sas->txq_info[tx_queue_id].state != SFC_TXQ_INITIALIZED) 1247862b35afSIgor Romanov goto fail_not_setup; 1248862b35afSIgor Romanov 1249c6a1d9b5SIvan Malov rc = sfc_tx_qstart(sa, tx_queue_id); 1250c6a1d9b5SIvan Malov if (rc != 0) 1251c6a1d9b5SIvan Malov goto fail_tx_qstart; 1252c6a1d9b5SIvan Malov 1253113a14a6SAndrew Rybchenko sas->txq_info[tx_queue_id].deferred_started = B_TRUE; 1254c6a1d9b5SIvan Malov 1255c6a1d9b5SIvan Malov sfc_adapter_unlock(sa); 1256c6a1d9b5SIvan Malov return 0; 1257c6a1d9b5SIvan Malov 1258c6a1d9b5SIvan Malov fail_tx_qstart: 1259c6a1d9b5SIvan Malov 1260862b35afSIgor Romanov fail_not_setup: 1261c6a1d9b5SIvan Malov fail_not_started: 1262c6a1d9b5SIvan Malov sfc_adapter_unlock(sa); 1263c6a1d9b5SIvan Malov SFC_ASSERT(rc > 0); 1264c6a1d9b5SIvan Malov return -rc; 1265c6a1d9b5SIvan Malov } 1266c6a1d9b5SIvan Malov 1267c6a1d9b5SIvan Malov static int 1268c6a1d9b5SIvan Malov sfc_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) 1269c6a1d9b5SIvan Malov { 1270113a14a6SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 12715313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1272c6a1d9b5SIvan Malov 1273c6a1d9b5SIvan Malov sfc_log_init(sa, "TxQ = %u", tx_queue_id); 1274c6a1d9b5SIvan Malov 1275c6a1d9b5SIvan Malov sfc_adapter_lock(sa); 1276c6a1d9b5SIvan Malov 1277c6a1d9b5SIvan Malov sfc_tx_qstop(sa, tx_queue_id); 1278c6a1d9b5SIvan Malov 1279113a14a6SAndrew Rybchenko sas->txq_info[tx_queue_id].deferred_started = B_FALSE; 1280c6a1d9b5SIvan Malov 1281c6a1d9b5SIvan Malov sfc_adapter_unlock(sa); 1282c6a1d9b5SIvan Malov return 0; 1283c6a1d9b5SIvan Malov } 1284c6a1d9b5SIvan Malov 128536c35355SAndrew Rybchenko static efx_tunnel_protocol_t 128636c35355SAndrew Rybchenko sfc_tunnel_rte_type_to_efx_udp_proto(enum rte_eth_tunnel_type rte_type) 128736c35355SAndrew Rybchenko { 128836c35355SAndrew Rybchenko switch (rte_type) { 128936c35355SAndrew Rybchenko case RTE_TUNNEL_TYPE_VXLAN: 129036c35355SAndrew Rybchenko return EFX_TUNNEL_PROTOCOL_VXLAN; 129136c35355SAndrew Rybchenko case RTE_TUNNEL_TYPE_GENEVE: 129236c35355SAndrew Rybchenko return EFX_TUNNEL_PROTOCOL_GENEVE; 129336c35355SAndrew Rybchenko default: 129436c35355SAndrew Rybchenko return EFX_TUNNEL_NPROTOS; 129536c35355SAndrew Rybchenko } 129636c35355SAndrew Rybchenko } 129736c35355SAndrew Rybchenko 129836c35355SAndrew Rybchenko enum sfc_udp_tunnel_op_e { 129936c35355SAndrew Rybchenko SFC_UDP_TUNNEL_ADD_PORT, 130036c35355SAndrew Rybchenko SFC_UDP_TUNNEL_DEL_PORT, 130136c35355SAndrew Rybchenko }; 130236c35355SAndrew Rybchenko 130336c35355SAndrew Rybchenko static int 130436c35355SAndrew Rybchenko sfc_dev_udp_tunnel_op(struct rte_eth_dev *dev, 130536c35355SAndrew Rybchenko struct rte_eth_udp_tunnel *tunnel_udp, 130636c35355SAndrew Rybchenko enum sfc_udp_tunnel_op_e op) 130736c35355SAndrew Rybchenko { 13085313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 130936c35355SAndrew Rybchenko efx_tunnel_protocol_t tunnel_proto; 131036c35355SAndrew Rybchenko int rc; 131136c35355SAndrew Rybchenko 131236c35355SAndrew Rybchenko sfc_log_init(sa, "%s udp_port=%u prot_type=%u", 131336c35355SAndrew Rybchenko (op == SFC_UDP_TUNNEL_ADD_PORT) ? "add" : 131436c35355SAndrew Rybchenko (op == SFC_UDP_TUNNEL_DEL_PORT) ? "delete" : "unknown", 131536c35355SAndrew Rybchenko tunnel_udp->udp_port, tunnel_udp->prot_type); 131636c35355SAndrew Rybchenko 131736c35355SAndrew Rybchenko tunnel_proto = 131836c35355SAndrew Rybchenko sfc_tunnel_rte_type_to_efx_udp_proto(tunnel_udp->prot_type); 131936c35355SAndrew Rybchenko if (tunnel_proto >= EFX_TUNNEL_NPROTOS) { 132036c35355SAndrew Rybchenko rc = ENOTSUP; 132136c35355SAndrew Rybchenko goto fail_bad_proto; 132236c35355SAndrew Rybchenko } 132336c35355SAndrew Rybchenko 132436c35355SAndrew Rybchenko sfc_adapter_lock(sa); 132536c35355SAndrew Rybchenko 132636c35355SAndrew Rybchenko switch (op) { 132736c35355SAndrew Rybchenko case SFC_UDP_TUNNEL_ADD_PORT: 132836c35355SAndrew Rybchenko rc = efx_tunnel_config_udp_add(sa->nic, 132936c35355SAndrew Rybchenko tunnel_udp->udp_port, 133036c35355SAndrew Rybchenko tunnel_proto); 133136c35355SAndrew Rybchenko break; 133236c35355SAndrew Rybchenko case SFC_UDP_TUNNEL_DEL_PORT: 133336c35355SAndrew Rybchenko rc = efx_tunnel_config_udp_remove(sa->nic, 133436c35355SAndrew Rybchenko tunnel_udp->udp_port, 133536c35355SAndrew Rybchenko tunnel_proto); 133636c35355SAndrew Rybchenko break; 133736c35355SAndrew Rybchenko default: 133836c35355SAndrew Rybchenko rc = EINVAL; 133936c35355SAndrew Rybchenko goto fail_bad_op; 134036c35355SAndrew Rybchenko } 134136c35355SAndrew Rybchenko 134236c35355SAndrew Rybchenko if (rc != 0) 134336c35355SAndrew Rybchenko goto fail_op; 134436c35355SAndrew Rybchenko 134536c35355SAndrew Rybchenko if (sa->state == SFC_ADAPTER_STARTED) { 134636c35355SAndrew Rybchenko rc = efx_tunnel_reconfigure(sa->nic); 134736c35355SAndrew Rybchenko if (rc == EAGAIN) { 134836c35355SAndrew Rybchenko /* 134936c35355SAndrew Rybchenko * Configuration is accepted by FW and MC reboot 135036c35355SAndrew Rybchenko * is initiated to apply the changes. MC reboot 135136c35355SAndrew Rybchenko * will be handled in a usual way (MC reboot 135236c35355SAndrew Rybchenko * event on management event queue and adapter 135336c35355SAndrew Rybchenko * restart). 135436c35355SAndrew Rybchenko */ 135536c35355SAndrew Rybchenko rc = 0; 135636c35355SAndrew Rybchenko } else if (rc != 0) { 135736c35355SAndrew Rybchenko goto fail_reconfigure; 135836c35355SAndrew Rybchenko } 135936c35355SAndrew Rybchenko } 136036c35355SAndrew Rybchenko 136136c35355SAndrew Rybchenko sfc_adapter_unlock(sa); 136236c35355SAndrew Rybchenko return 0; 136336c35355SAndrew Rybchenko 136436c35355SAndrew Rybchenko fail_reconfigure: 136536c35355SAndrew Rybchenko /* Remove/restore entry since the change makes the trouble */ 136636c35355SAndrew Rybchenko switch (op) { 136736c35355SAndrew Rybchenko case SFC_UDP_TUNNEL_ADD_PORT: 136836c35355SAndrew Rybchenko (void)efx_tunnel_config_udp_remove(sa->nic, 136936c35355SAndrew Rybchenko tunnel_udp->udp_port, 137036c35355SAndrew Rybchenko tunnel_proto); 137136c35355SAndrew Rybchenko break; 137236c35355SAndrew Rybchenko case SFC_UDP_TUNNEL_DEL_PORT: 137336c35355SAndrew Rybchenko (void)efx_tunnel_config_udp_add(sa->nic, 137436c35355SAndrew Rybchenko tunnel_udp->udp_port, 137536c35355SAndrew Rybchenko tunnel_proto); 137636c35355SAndrew Rybchenko break; 137736c35355SAndrew Rybchenko } 137836c35355SAndrew Rybchenko 137936c35355SAndrew Rybchenko fail_op: 138036c35355SAndrew Rybchenko fail_bad_op: 138136c35355SAndrew Rybchenko sfc_adapter_unlock(sa); 138236c35355SAndrew Rybchenko 138336c35355SAndrew Rybchenko fail_bad_proto: 138436c35355SAndrew Rybchenko SFC_ASSERT(rc > 0); 138536c35355SAndrew Rybchenko return -rc; 138636c35355SAndrew Rybchenko } 138736c35355SAndrew Rybchenko 138836c35355SAndrew Rybchenko static int 138936c35355SAndrew Rybchenko sfc_dev_udp_tunnel_port_add(struct rte_eth_dev *dev, 139036c35355SAndrew Rybchenko struct rte_eth_udp_tunnel *tunnel_udp) 139136c35355SAndrew Rybchenko { 139236c35355SAndrew Rybchenko return sfc_dev_udp_tunnel_op(dev, tunnel_udp, SFC_UDP_TUNNEL_ADD_PORT); 139336c35355SAndrew Rybchenko } 139436c35355SAndrew Rybchenko 139536c35355SAndrew Rybchenko static int 139636c35355SAndrew Rybchenko sfc_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, 139736c35355SAndrew Rybchenko struct rte_eth_udp_tunnel *tunnel_udp) 139836c35355SAndrew Rybchenko { 139936c35355SAndrew Rybchenko return sfc_dev_udp_tunnel_op(dev, tunnel_udp, SFC_UDP_TUNNEL_DEL_PORT); 140036c35355SAndrew Rybchenko } 140136c35355SAndrew Rybchenko 1402128da692SAndrew Rybchenko /* 1403128da692SAndrew Rybchenko * The function is used by the secondary process as well. It must not 1404128da692SAndrew Rybchenko * use any process-local pointers from the adapter data. 1405128da692SAndrew Rybchenko */ 1406088e1721SIvan Malov static int 1407088e1721SIvan Malov sfc_dev_rss_hash_conf_get(struct rte_eth_dev *dev, 1408088e1721SIvan Malov struct rte_eth_rss_conf *rss_conf) 1409088e1721SIvan Malov { 1410e295f175SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 1411e295f175SAndrew Rybchenko struct sfc_rss *rss = &sas->rss; 1412088e1721SIvan Malov 1413453e1d4bSIvan Malov if (rss->context_type != EFX_RX_SCALE_EXCLUSIVE) 1414088e1721SIvan Malov return -ENOTSUP; 1415088e1721SIvan Malov 1416088e1721SIvan Malov /* 1417088e1721SIvan Malov * Mapping of hash configuration between RTE and EFX is not one-to-one, 1418088e1721SIvan Malov * hence, conversion is done here to derive a correct set of ETH_RSS 1419088e1721SIvan Malov * flags which corresponds to the active EFX configuration stored 1420088e1721SIvan Malov * locally in 'sfc_adapter' and kept up-to-date 1421088e1721SIvan Malov */ 1422e295f175SAndrew Rybchenko rss_conf->rss_hf = sfc_rx_hf_efx_to_rte(rss, rss->hash_types); 142337a42c61SAndrew Rybchenko rss_conf->rss_key_len = EFX_RSS_KEY_SIZE; 1424088e1721SIvan Malov if (rss_conf->rss_key != NULL) 1425d1482e21SIvan Malov rte_memcpy(rss_conf->rss_key, rss->key, EFX_RSS_KEY_SIZE); 1426088e1721SIvan Malov 1427088e1721SIvan Malov return 0; 1428088e1721SIvan Malov } 142982faef50SIvan Malov 143082faef50SIvan Malov static int 143182faef50SIvan Malov sfc_dev_rss_hash_update(struct rte_eth_dev *dev, 143282faef50SIvan Malov struct rte_eth_rss_conf *rss_conf) 143382faef50SIvan Malov { 14345313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1435e295f175SAndrew Rybchenko struct sfc_rss *rss = &sfc_sa2shared(sa)->rss; 143682faef50SIvan Malov unsigned int efx_hash_types; 143782faef50SIvan Malov int rc = 0; 143882faef50SIvan Malov 1439e0d5ba7eSAndrew Rybchenko if (sfc_sa2shared(sa)->isolated) 144084a9b481SIvan Malov return -ENOTSUP; 144184a9b481SIvan Malov 1442d1482e21SIvan Malov if (rss->context_type != EFX_RX_SCALE_EXCLUSIVE) { 144382faef50SIvan Malov sfc_err(sa, "RSS is not available"); 144482faef50SIvan Malov return -ENOTSUP; 144582faef50SIvan Malov } 144682faef50SIvan Malov 1447d1482e21SIvan Malov if (rss->channels == 0) { 144863ab5e0cSAndrew Rybchenko sfc_err(sa, "RSS is not configured"); 144963ab5e0cSAndrew Rybchenko return -EINVAL; 145063ab5e0cSAndrew Rybchenko } 145163ab5e0cSAndrew Rybchenko 145282faef50SIvan Malov if ((rss_conf->rss_key != NULL) && 1453d1482e21SIvan Malov (rss_conf->rss_key_len != sizeof(rss->key))) { 145482faef50SIvan Malov sfc_err(sa, "RSS key size is wrong (should be %lu)", 1455d1482e21SIvan Malov sizeof(rss->key)); 145682faef50SIvan Malov return -EINVAL; 145782faef50SIvan Malov } 145882faef50SIvan Malov 145982faef50SIvan Malov sfc_adapter_lock(sa); 146082faef50SIvan Malov 146101764b20SIvan Malov rc = sfc_rx_hf_rte_to_efx(sa, rss_conf->rss_hf, &efx_hash_types); 146201764b20SIvan Malov if (rc != 0) 146301764b20SIvan Malov goto fail_rx_hf_rte_to_efx; 146482faef50SIvan Malov 146503081632SMark Spender rc = efx_rx_scale_mode_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT, 146601764b20SIvan Malov rss->hash_alg, efx_hash_types, B_TRUE); 146782faef50SIvan Malov if (rc != 0) 146882faef50SIvan Malov goto fail_scale_mode_set; 146982faef50SIvan Malov 147082faef50SIvan Malov if (rss_conf->rss_key != NULL) { 147182faef50SIvan Malov if (sa->state == SFC_ADAPTER_STARTED) { 147203081632SMark Spender rc = efx_rx_scale_key_set(sa->nic, 147303081632SMark Spender EFX_RSS_CONTEXT_DEFAULT, 147403081632SMark Spender rss_conf->rss_key, 1475d1482e21SIvan Malov sizeof(rss->key)); 147682faef50SIvan Malov if (rc != 0) 147782faef50SIvan Malov goto fail_scale_key_set; 147882faef50SIvan Malov } 147982faef50SIvan Malov 1480d1482e21SIvan Malov rte_memcpy(rss->key, rss_conf->rss_key, sizeof(rss->key)); 148182faef50SIvan Malov } 148282faef50SIvan Malov 1483d1482e21SIvan Malov rss->hash_types = efx_hash_types; 148482faef50SIvan Malov 148582faef50SIvan Malov sfc_adapter_unlock(sa); 148682faef50SIvan Malov 148782faef50SIvan Malov return 0; 148882faef50SIvan Malov 148982faef50SIvan Malov fail_scale_key_set: 149003081632SMark Spender if (efx_rx_scale_mode_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT, 149103081632SMark Spender EFX_RX_HASHALG_TOEPLITZ, 1492d1482e21SIvan Malov rss->hash_types, B_TRUE) != 0) 149382faef50SIvan Malov sfc_err(sa, "failed to restore RSS mode"); 149482faef50SIvan Malov 149582faef50SIvan Malov fail_scale_mode_set: 149601764b20SIvan Malov fail_rx_hf_rte_to_efx: 149782faef50SIvan Malov sfc_adapter_unlock(sa); 149882faef50SIvan Malov return -rc; 149982faef50SIvan Malov } 1500af0d9317SIvan Malov 1501128da692SAndrew Rybchenko /* 1502128da692SAndrew Rybchenko * The function is used by the secondary process as well. It must not 1503128da692SAndrew Rybchenko * use any process-local pointers from the adapter data. 1504128da692SAndrew Rybchenko */ 1505af0d9317SIvan Malov static int 1506af0d9317SIvan Malov sfc_dev_rss_reta_query(struct rte_eth_dev *dev, 1507af0d9317SIvan Malov struct rte_eth_rss_reta_entry64 *reta_conf, 1508af0d9317SIvan Malov uint16_t reta_size) 1509af0d9317SIvan Malov { 1510e295f175SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 1511e295f175SAndrew Rybchenko struct sfc_rss *rss = &sas->rss; 1512af0d9317SIvan Malov int entry; 1513af0d9317SIvan Malov 1514e0d5ba7eSAndrew Rybchenko if (rss->context_type != EFX_RX_SCALE_EXCLUSIVE || sas->isolated) 1515af0d9317SIvan Malov return -ENOTSUP; 1516af0d9317SIvan Malov 1517d1482e21SIvan Malov if (rss->channels == 0) 151863ab5e0cSAndrew Rybchenko return -EINVAL; 151963ab5e0cSAndrew Rybchenko 1520af0d9317SIvan Malov if (reta_size != EFX_RSS_TBL_SIZE) 1521af0d9317SIvan Malov return -EINVAL; 1522af0d9317SIvan Malov 1523af0d9317SIvan Malov for (entry = 0; entry < reta_size; entry++) { 1524af0d9317SIvan Malov int grp = entry / RTE_RETA_GROUP_SIZE; 1525af0d9317SIvan Malov int grp_idx = entry % RTE_RETA_GROUP_SIZE; 1526af0d9317SIvan Malov 1527af0d9317SIvan Malov if ((reta_conf[grp].mask >> grp_idx) & 1) 1528d1482e21SIvan Malov reta_conf[grp].reta[grp_idx] = rss->tbl[entry]; 1529af0d9317SIvan Malov } 1530af0d9317SIvan Malov 1531af0d9317SIvan Malov return 0; 1532af0d9317SIvan Malov } 153332bcfb0aSIvan Malov 153432bcfb0aSIvan Malov static int 153532bcfb0aSIvan Malov sfc_dev_rss_reta_update(struct rte_eth_dev *dev, 153632bcfb0aSIvan Malov struct rte_eth_rss_reta_entry64 *reta_conf, 153732bcfb0aSIvan Malov uint16_t reta_size) 153832bcfb0aSIvan Malov { 15395313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1540e295f175SAndrew Rybchenko struct sfc_rss *rss = &sfc_sa2shared(sa)->rss; 154132bcfb0aSIvan Malov unsigned int *rss_tbl_new; 154232bcfb0aSIvan Malov uint16_t entry; 154373332ab8SIvan Malov int rc = 0; 154432bcfb0aSIvan Malov 154532bcfb0aSIvan Malov 1546e0d5ba7eSAndrew Rybchenko if (sfc_sa2shared(sa)->isolated) 154784a9b481SIvan Malov return -ENOTSUP; 154884a9b481SIvan Malov 1549d1482e21SIvan Malov if (rss->context_type != EFX_RX_SCALE_EXCLUSIVE) { 155032bcfb0aSIvan Malov sfc_err(sa, "RSS is not available"); 155132bcfb0aSIvan Malov return -ENOTSUP; 155232bcfb0aSIvan Malov } 155332bcfb0aSIvan Malov 1554d1482e21SIvan Malov if (rss->channels == 0) { 155563ab5e0cSAndrew Rybchenko sfc_err(sa, "RSS is not configured"); 155663ab5e0cSAndrew Rybchenko return -EINVAL; 155763ab5e0cSAndrew Rybchenko } 155863ab5e0cSAndrew Rybchenko 155932bcfb0aSIvan Malov if (reta_size != EFX_RSS_TBL_SIZE) { 156032bcfb0aSIvan Malov sfc_err(sa, "RETA size is wrong (should be %u)", 156132bcfb0aSIvan Malov EFX_RSS_TBL_SIZE); 156232bcfb0aSIvan Malov return -EINVAL; 156332bcfb0aSIvan Malov } 156432bcfb0aSIvan Malov 1565d1482e21SIvan Malov rss_tbl_new = rte_zmalloc("rss_tbl_new", sizeof(rss->tbl), 0); 156632bcfb0aSIvan Malov if (rss_tbl_new == NULL) 156732bcfb0aSIvan Malov return -ENOMEM; 156832bcfb0aSIvan Malov 156932bcfb0aSIvan Malov sfc_adapter_lock(sa); 157032bcfb0aSIvan Malov 1571d1482e21SIvan Malov rte_memcpy(rss_tbl_new, rss->tbl, sizeof(rss->tbl)); 157232bcfb0aSIvan Malov 157332bcfb0aSIvan Malov for (entry = 0; entry < reta_size; entry++) { 157432bcfb0aSIvan Malov int grp_idx = entry % RTE_RETA_GROUP_SIZE; 157532bcfb0aSIvan Malov struct rte_eth_rss_reta_entry64 *grp; 157632bcfb0aSIvan Malov 157732bcfb0aSIvan Malov grp = &reta_conf[entry / RTE_RETA_GROUP_SIZE]; 157832bcfb0aSIvan Malov 157932bcfb0aSIvan Malov if (grp->mask & (1ull << grp_idx)) { 1580d1482e21SIvan Malov if (grp->reta[grp_idx] >= rss->channels) { 158132bcfb0aSIvan Malov rc = EINVAL; 158232bcfb0aSIvan Malov goto bad_reta_entry; 158332bcfb0aSIvan Malov } 158432bcfb0aSIvan Malov rss_tbl_new[entry] = grp->reta[grp_idx]; 158532bcfb0aSIvan Malov } 158632bcfb0aSIvan Malov } 158732bcfb0aSIvan Malov 158873332ab8SIvan Malov if (sa->state == SFC_ADAPTER_STARTED) { 158903081632SMark Spender rc = efx_rx_scale_tbl_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT, 159003081632SMark Spender rss_tbl_new, EFX_RSS_TBL_SIZE); 159173332ab8SIvan Malov if (rc != 0) 159273332ab8SIvan Malov goto fail_scale_tbl_set; 159373332ab8SIvan Malov } 159473332ab8SIvan Malov 1595d1482e21SIvan Malov rte_memcpy(rss->tbl, rss_tbl_new, sizeof(rss->tbl)); 159632bcfb0aSIvan Malov 159773332ab8SIvan Malov fail_scale_tbl_set: 159832bcfb0aSIvan Malov bad_reta_entry: 159932bcfb0aSIvan Malov sfc_adapter_unlock(sa); 160032bcfb0aSIvan Malov 160132bcfb0aSIvan Malov rte_free(rss_tbl_new); 160232bcfb0aSIvan Malov 160332bcfb0aSIvan Malov SFC_ASSERT(rc >= 0); 160432bcfb0aSIvan Malov return -rc; 160532bcfb0aSIvan Malov } 1606088e1721SIvan Malov 1607403030f5SAndrew Rybchenko static int 1608403030f5SAndrew Rybchenko sfc_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, 1609a9825ccfSRoman Zhukov enum rte_filter_op filter_op, 1610a9825ccfSRoman Zhukov void *arg) 1611403030f5SAndrew Rybchenko { 16125313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 1613403030f5SAndrew Rybchenko int rc = ENOTSUP; 1614403030f5SAndrew Rybchenko 1615403030f5SAndrew Rybchenko sfc_log_init(sa, "entry"); 1616403030f5SAndrew Rybchenko 1617403030f5SAndrew Rybchenko switch (filter_type) { 1618403030f5SAndrew Rybchenko case RTE_ETH_FILTER_NONE: 1619403030f5SAndrew Rybchenko sfc_err(sa, "Global filters configuration not supported"); 1620403030f5SAndrew Rybchenko break; 1621403030f5SAndrew Rybchenko case RTE_ETH_FILTER_MACVLAN: 1622403030f5SAndrew Rybchenko sfc_err(sa, "MACVLAN filters not supported"); 1623403030f5SAndrew Rybchenko break; 1624403030f5SAndrew Rybchenko case RTE_ETH_FILTER_ETHERTYPE: 1625403030f5SAndrew Rybchenko sfc_err(sa, "EtherType filters not supported"); 1626403030f5SAndrew Rybchenko break; 1627403030f5SAndrew Rybchenko case RTE_ETH_FILTER_FLEXIBLE: 1628403030f5SAndrew Rybchenko sfc_err(sa, "Flexible filters not supported"); 1629403030f5SAndrew Rybchenko break; 1630403030f5SAndrew Rybchenko case RTE_ETH_FILTER_SYN: 1631403030f5SAndrew Rybchenko sfc_err(sa, "SYN filters not supported"); 1632403030f5SAndrew Rybchenko break; 1633403030f5SAndrew Rybchenko case RTE_ETH_FILTER_NTUPLE: 1634403030f5SAndrew Rybchenko sfc_err(sa, "NTUPLE filters not supported"); 1635403030f5SAndrew Rybchenko break; 1636403030f5SAndrew Rybchenko case RTE_ETH_FILTER_TUNNEL: 1637403030f5SAndrew Rybchenko sfc_err(sa, "Tunnel filters not supported"); 1638403030f5SAndrew Rybchenko break; 1639403030f5SAndrew Rybchenko case RTE_ETH_FILTER_FDIR: 1640403030f5SAndrew Rybchenko sfc_err(sa, "Flow Director filters not supported"); 1641403030f5SAndrew Rybchenko break; 1642403030f5SAndrew Rybchenko case RTE_ETH_FILTER_HASH: 1643403030f5SAndrew Rybchenko sfc_err(sa, "Hash filters not supported"); 1644403030f5SAndrew Rybchenko break; 1645a9825ccfSRoman Zhukov case RTE_ETH_FILTER_GENERIC: 1646a9825ccfSRoman Zhukov if (filter_op != RTE_ETH_FILTER_GET) { 1647a9825ccfSRoman Zhukov rc = EINVAL; 1648a9825ccfSRoman Zhukov } else { 1649a9825ccfSRoman Zhukov *(const void **)arg = &sfc_flow_ops; 1650a9825ccfSRoman Zhukov rc = 0; 1651a9825ccfSRoman Zhukov } 1652a9825ccfSRoman Zhukov break; 1653403030f5SAndrew Rybchenko default: 1654403030f5SAndrew Rybchenko sfc_err(sa, "Unknown filter type %u", filter_type); 1655403030f5SAndrew Rybchenko break; 1656403030f5SAndrew Rybchenko } 1657403030f5SAndrew Rybchenko 1658403030f5SAndrew Rybchenko sfc_log_init(sa, "exit: %d", -rc); 1659403030f5SAndrew Rybchenko SFC_ASSERT(rc >= 0); 1660403030f5SAndrew Rybchenko return -rc; 1661403030f5SAndrew Rybchenko } 1662403030f5SAndrew Rybchenko 166308d23c67SAndrew Rybchenko static int 166408d23c67SAndrew Rybchenko sfc_pool_ops_supported(struct rte_eth_dev *dev, const char *pool) 166508d23c67SAndrew Rybchenko { 16665dec95e3SAndrew Rybchenko const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev); 166708d23c67SAndrew Rybchenko 166808d23c67SAndrew Rybchenko /* 166908d23c67SAndrew Rybchenko * If Rx datapath does not provide callback to check mempool, 167008d23c67SAndrew Rybchenko * all pools are supported. 167108d23c67SAndrew Rybchenko */ 16725dec95e3SAndrew Rybchenko if (sap->dp_rx->pool_ops_supported == NULL) 167308d23c67SAndrew Rybchenko return 1; 167408d23c67SAndrew Rybchenko 16755dec95e3SAndrew Rybchenko return sap->dp_rx->pool_ops_supported(pool); 167608d23c67SAndrew Rybchenko } 167708d23c67SAndrew Rybchenko 167863d588ffSAndrew Rybchenko static const struct eth_dev_ops sfc_eth_dev_ops = { 1679aaa3f5f0SAndrew Rybchenko .dev_configure = sfc_dev_configure, 168093fcf09bSAndrew Rybchenko .dev_start = sfc_dev_start, 168193fcf09bSAndrew Rybchenko .dev_stop = sfc_dev_stop, 16822a05f337SArtem Andreev .dev_set_link_up = sfc_dev_set_link_up, 16832a05f337SArtem Andreev .dev_set_link_down = sfc_dev_set_link_down, 1684aaa3f5f0SAndrew Rybchenko .dev_close = sfc_dev_close, 1685f3de3840SIvan Malov .promiscuous_enable = sfc_dev_promisc_enable, 1686f3de3840SIvan Malov .promiscuous_disable = sfc_dev_promisc_disable, 1687f3de3840SIvan Malov .allmulticast_enable = sfc_dev_allmulti_enable, 1688f3de3840SIvan Malov .allmulticast_disable = sfc_dev_allmulti_disable, 1689886f8d8aSArtem Andreev .link_update = sfc_dev_link_update, 16901caab2f1SAndrew Rybchenko .stats_get = sfc_stats_get, 1691e8acb329SIvan Malov .stats_reset = sfc_stats_reset, 16927b989176SAndrew Rybchenko .xstats_get = sfc_xstats_get, 1693e8acb329SIvan Malov .xstats_reset = sfc_stats_reset, 16947b989176SAndrew Rybchenko .xstats_get_names = sfc_xstats_get_names, 169563d588ffSAndrew Rybchenko .dev_infos_get = sfc_dev_infos_get, 169656349dc9SAndrew Rybchenko .dev_supported_ptypes_get = sfc_dev_supported_ptypes_get, 1697e961cf42SAndrew Rybchenko .mtu_set = sfc_dev_set_mtu, 1698ac7af396SAndrew Rybchenko .rx_queue_start = sfc_rx_queue_start, 1699ac7af396SAndrew Rybchenko .rx_queue_stop = sfc_rx_queue_stop, 1700c6a1d9b5SIvan Malov .tx_queue_start = sfc_tx_queue_start, 1701c6a1d9b5SIvan Malov .tx_queue_stop = sfc_tx_queue_stop, 1702ce35b05cSAndrew Rybchenko .rx_queue_setup = sfc_rx_queue_setup, 1703ce35b05cSAndrew Rybchenko .rx_queue_release = sfc_rx_queue_release, 170404aa6b9cSAndrew Rybchenko .rx_queue_count = sfc_rx_queue_count, 170536d84f87SAndrew Rybchenko .rx_descriptor_done = sfc_rx_descriptor_done, 17061d8f3a80SIvan Malov .rx_descriptor_status = sfc_rx_descriptor_status, 17077df6f854SIvan Malov .tx_descriptor_status = sfc_tx_descriptor_status, 1708b1b7ad93SIvan Malov .tx_queue_setup = sfc_tx_queue_setup, 1709b1b7ad93SIvan Malov .tx_queue_release = sfc_tx_queue_release, 1710cdbb29cfSAndrew Rybchenko .flow_ctrl_get = sfc_flow_ctrl_get, 1711cdbb29cfSAndrew Rybchenko .flow_ctrl_set = sfc_flow_ctrl_set, 1712c100fd46SIvan Malov .mac_addr_set = sfc_mac_addr_set, 171336c35355SAndrew Rybchenko .udp_tunnel_port_add = sfc_dev_udp_tunnel_port_add, 171436c35355SAndrew Rybchenko .udp_tunnel_port_del = sfc_dev_udp_tunnel_port_del, 171532bcfb0aSIvan Malov .reta_update = sfc_dev_rss_reta_update, 1716af0d9317SIvan Malov .reta_query = sfc_dev_rss_reta_query, 171782faef50SIvan Malov .rss_hash_update = sfc_dev_rss_hash_update, 1718088e1721SIvan Malov .rss_hash_conf_get = sfc_dev_rss_hash_conf_get, 1719403030f5SAndrew Rybchenko .filter_ctrl = sfc_dev_filter_ctrl, 17200fa0070eSIvan Malov .set_mc_addr_list = sfc_set_mc_addr_list, 17215502e397SAndrew Rybchenko .rxq_info_get = sfc_rx_queue_info_get, 1722c5938838SIvan Malov .txq_info_get = sfc_tx_queue_info_get, 172383fef46aSIvan Malov .fw_version_get = sfc_fw_version_get, 172473280c1eSIvan Malov .xstats_get_by_id = sfc_xstats_get_by_id, 172573280c1eSIvan Malov .xstats_get_names_by_id = sfc_xstats_get_names_by_id, 172608d23c67SAndrew Rybchenko .pool_ops_supported = sfc_pool_ops_supported, 172763d588ffSAndrew Rybchenko }; 172863d588ffSAndrew Rybchenko 1729f28ede50SAndrew Rybchenko /** 1730f28ede50SAndrew Rybchenko * Duplicate a string in potentially shared memory required for 1731f28ede50SAndrew Rybchenko * multi-process support. 1732f28ede50SAndrew Rybchenko * 1733f28ede50SAndrew Rybchenko * strdup() allocates from process-local heap/memory. 1734f28ede50SAndrew Rybchenko */ 1735f28ede50SAndrew Rybchenko static char * 1736f28ede50SAndrew Rybchenko sfc_strdup(const char *str) 1737f28ede50SAndrew Rybchenko { 1738f28ede50SAndrew Rybchenko size_t size; 1739f28ede50SAndrew Rybchenko char *copy; 1740f28ede50SAndrew Rybchenko 1741f28ede50SAndrew Rybchenko if (str == NULL) 1742f28ede50SAndrew Rybchenko return NULL; 1743f28ede50SAndrew Rybchenko 1744f28ede50SAndrew Rybchenko size = strlen(str) + 1; 1745f28ede50SAndrew Rybchenko copy = rte_malloc(__func__, size, 0); 1746f28ede50SAndrew Rybchenko if (copy != NULL) 1747f28ede50SAndrew Rybchenko rte_memcpy(copy, str, size); 1748f28ede50SAndrew Rybchenko 1749f28ede50SAndrew Rybchenko return copy; 1750f28ede50SAndrew Rybchenko } 1751f28ede50SAndrew Rybchenko 175263d588ffSAndrew Rybchenko static int 1753df1bfde4SAndrew Rybchenko sfc_eth_dev_set_ops(struct rte_eth_dev *dev) 1754df1bfde4SAndrew Rybchenko { 17555313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 175650f34eedSAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 1757c7b57f00SAndrew Rybchenko const struct sfc_dp_rx *dp_rx; 1758c7b57f00SAndrew Rybchenko const struct sfc_dp_tx *dp_tx; 1759390f9b8dSAndrew Rybchenko const efx_nic_cfg_t *encp; 1760df1bfde4SAndrew Rybchenko unsigned int avail_caps = 0; 1761df1bfde4SAndrew Rybchenko const char *rx_name = NULL; 1762dbdc8241SAndrew Rybchenko const char *tx_name = NULL; 1763df1bfde4SAndrew Rybchenko int rc; 1764df1bfde4SAndrew Rybchenko 1765638bddc9SAndrew Rybchenko switch (sa->family) { 1766638bddc9SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 1767638bddc9SAndrew Rybchenko case EFX_FAMILY_MEDFORD: 1768f3129efdSAndrew Rybchenko case EFX_FAMILY_MEDFORD2: 1769638bddc9SAndrew Rybchenko avail_caps |= SFC_DP_HW_FW_CAP_EF10; 1770638bddc9SAndrew Rybchenko break; 1771638bddc9SAndrew Rybchenko default: 1772638bddc9SAndrew Rybchenko break; 1773638bddc9SAndrew Rybchenko } 1774638bddc9SAndrew Rybchenko 1775390f9b8dSAndrew Rybchenko encp = efx_nic_cfg_get(sa->nic); 1776390f9b8dSAndrew Rybchenko if (encp->enc_rx_es_super_buffer_supported) 1777390f9b8dSAndrew Rybchenko avail_caps |= SFC_DP_HW_FW_CAP_RX_ES_SUPER_BUFFER; 1778390f9b8dSAndrew Rybchenko 1779df1bfde4SAndrew Rybchenko rc = sfc_kvargs_process(sa, SFC_KVARG_RX_DATAPATH, 1780df1bfde4SAndrew Rybchenko sfc_kvarg_string_handler, &rx_name); 1781df1bfde4SAndrew Rybchenko if (rc != 0) 1782df1bfde4SAndrew Rybchenko goto fail_kvarg_rx_datapath; 1783df1bfde4SAndrew Rybchenko 1784df1bfde4SAndrew Rybchenko if (rx_name != NULL) { 1785c7b57f00SAndrew Rybchenko dp_rx = sfc_dp_find_rx_by_name(&sfc_dp_head, rx_name); 1786c7b57f00SAndrew Rybchenko if (dp_rx == NULL) { 1787df1bfde4SAndrew Rybchenko sfc_err(sa, "Rx datapath %s not found", rx_name); 1788df1bfde4SAndrew Rybchenko rc = ENOENT; 1789df1bfde4SAndrew Rybchenko goto fail_dp_rx; 1790df1bfde4SAndrew Rybchenko } 1791c7b57f00SAndrew Rybchenko if (!sfc_dp_match_hw_fw_caps(&dp_rx->dp, avail_caps)) { 1792df1bfde4SAndrew Rybchenko sfc_err(sa, 1793df1bfde4SAndrew Rybchenko "Insufficient Hw/FW capabilities to use Rx datapath %s", 1794df1bfde4SAndrew Rybchenko rx_name); 1795df1bfde4SAndrew Rybchenko rc = EINVAL; 179635870e50SAndrew Rybchenko goto fail_dp_rx_caps; 1797df1bfde4SAndrew Rybchenko } 1798df1bfde4SAndrew Rybchenko } else { 1799c7b57f00SAndrew Rybchenko dp_rx = sfc_dp_find_rx_by_caps(&sfc_dp_head, avail_caps); 1800c7b57f00SAndrew Rybchenko if (dp_rx == NULL) { 1801df1bfde4SAndrew Rybchenko sfc_err(sa, "Rx datapath by caps %#x not found", 1802df1bfde4SAndrew Rybchenko avail_caps); 1803df1bfde4SAndrew Rybchenko rc = ENOENT; 1804df1bfde4SAndrew Rybchenko goto fail_dp_rx; 1805df1bfde4SAndrew Rybchenko } 1806df1bfde4SAndrew Rybchenko } 1807df1bfde4SAndrew Rybchenko 180850f34eedSAndrew Rybchenko sas->dp_rx_name = sfc_strdup(dp_rx->dp.name); 180950f34eedSAndrew Rybchenko if (sas->dp_rx_name == NULL) { 1810f28ede50SAndrew Rybchenko rc = ENOMEM; 1811f28ede50SAndrew Rybchenko goto fail_dp_rx_name; 1812f28ede50SAndrew Rybchenko } 1813f28ede50SAndrew Rybchenko 181450f34eedSAndrew Rybchenko sfc_notice(sa, "use %s Rx datapath", sas->dp_rx_name); 1815df1bfde4SAndrew Rybchenko 1816dbdc8241SAndrew Rybchenko rc = sfc_kvargs_process(sa, SFC_KVARG_TX_DATAPATH, 1817dbdc8241SAndrew Rybchenko sfc_kvarg_string_handler, &tx_name); 1818dbdc8241SAndrew Rybchenko if (rc != 0) 1819dbdc8241SAndrew Rybchenko goto fail_kvarg_tx_datapath; 1820dbdc8241SAndrew Rybchenko 1821dbdc8241SAndrew Rybchenko if (tx_name != NULL) { 1822c7b57f00SAndrew Rybchenko dp_tx = sfc_dp_find_tx_by_name(&sfc_dp_head, tx_name); 1823c7b57f00SAndrew Rybchenko if (dp_tx == NULL) { 1824dbdc8241SAndrew Rybchenko sfc_err(sa, "Tx datapath %s not found", tx_name); 1825dbdc8241SAndrew Rybchenko rc = ENOENT; 1826dbdc8241SAndrew Rybchenko goto fail_dp_tx; 1827dbdc8241SAndrew Rybchenko } 1828c7b57f00SAndrew Rybchenko if (!sfc_dp_match_hw_fw_caps(&dp_tx->dp, avail_caps)) { 1829dbdc8241SAndrew Rybchenko sfc_err(sa, 1830dbdc8241SAndrew Rybchenko "Insufficient Hw/FW capabilities to use Tx datapath %s", 1831dbdc8241SAndrew Rybchenko tx_name); 1832dbdc8241SAndrew Rybchenko rc = EINVAL; 183335870e50SAndrew Rybchenko goto fail_dp_tx_caps; 1834dbdc8241SAndrew Rybchenko } 1835dbdc8241SAndrew Rybchenko } else { 1836c7b57f00SAndrew Rybchenko dp_tx = sfc_dp_find_tx_by_caps(&sfc_dp_head, avail_caps); 1837c7b57f00SAndrew Rybchenko if (dp_tx == NULL) { 1838dbdc8241SAndrew Rybchenko sfc_err(sa, "Tx datapath by caps %#x not found", 1839dbdc8241SAndrew Rybchenko avail_caps); 1840dbdc8241SAndrew Rybchenko rc = ENOENT; 1841dbdc8241SAndrew Rybchenko goto fail_dp_tx; 1842dbdc8241SAndrew Rybchenko } 1843dbdc8241SAndrew Rybchenko } 1844dbdc8241SAndrew Rybchenko 184550f34eedSAndrew Rybchenko sas->dp_tx_name = sfc_strdup(dp_tx->dp.name); 184650f34eedSAndrew Rybchenko if (sas->dp_tx_name == NULL) { 1847f28ede50SAndrew Rybchenko rc = ENOMEM; 1848f28ede50SAndrew Rybchenko goto fail_dp_tx_name; 1849f28ede50SAndrew Rybchenko } 1850f28ede50SAndrew Rybchenko 185150f34eedSAndrew Rybchenko sfc_notice(sa, "use %s Tx datapath", sas->dp_tx_name); 1852dbdc8241SAndrew Rybchenko 18535dec95e3SAndrew Rybchenko sa->priv.dp_rx = dp_rx; 18545dec95e3SAndrew Rybchenko sa->priv.dp_tx = dp_tx; 1855c7b57f00SAndrew Rybchenko 1856c7b57f00SAndrew Rybchenko dev->rx_pkt_burst = dp_rx->pkt_burst; 1857c7b57f00SAndrew Rybchenko dev->tx_pkt_burst = dp_tx->pkt_burst; 1858df1bfde4SAndrew Rybchenko 1859df1bfde4SAndrew Rybchenko dev->dev_ops = &sfc_eth_dev_ops; 1860df1bfde4SAndrew Rybchenko 1861df1bfde4SAndrew Rybchenko return 0; 1862df1bfde4SAndrew Rybchenko 1863f28ede50SAndrew Rybchenko fail_dp_tx_name: 186435870e50SAndrew Rybchenko fail_dp_tx_caps: 1865dbdc8241SAndrew Rybchenko fail_dp_tx: 1866dbdc8241SAndrew Rybchenko fail_kvarg_tx_datapath: 186750f34eedSAndrew Rybchenko rte_free(sas->dp_rx_name); 186850f34eedSAndrew Rybchenko sas->dp_rx_name = NULL; 1869f28ede50SAndrew Rybchenko 1870f28ede50SAndrew Rybchenko fail_dp_rx_name: 187135870e50SAndrew Rybchenko fail_dp_rx_caps: 1872df1bfde4SAndrew Rybchenko fail_dp_rx: 1873df1bfde4SAndrew Rybchenko fail_kvarg_rx_datapath: 1874df1bfde4SAndrew Rybchenko return rc; 1875df1bfde4SAndrew Rybchenko } 1876df1bfde4SAndrew Rybchenko 1877df1bfde4SAndrew Rybchenko static void 187835870e50SAndrew Rybchenko sfc_eth_dev_clear_ops(struct rte_eth_dev *dev) 187935870e50SAndrew Rybchenko { 18805313b441SAndrew Rybchenko struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); 188150f34eedSAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 188235870e50SAndrew Rybchenko 188335870e50SAndrew Rybchenko dev->dev_ops = NULL; 188435870e50SAndrew Rybchenko dev->rx_pkt_burst = NULL; 188535870e50SAndrew Rybchenko dev->tx_pkt_burst = NULL; 188635870e50SAndrew Rybchenko 188750f34eedSAndrew Rybchenko rte_free(sas->dp_tx_name); 188850f34eedSAndrew Rybchenko sas->dp_tx_name = NULL; 18895dec95e3SAndrew Rybchenko sa->priv.dp_tx = NULL; 1890f28ede50SAndrew Rybchenko 189150f34eedSAndrew Rybchenko rte_free(sas->dp_rx_name); 189250f34eedSAndrew Rybchenko sas->dp_rx_name = NULL; 18935dec95e3SAndrew Rybchenko sa->priv.dp_rx = NULL; 189435870e50SAndrew Rybchenko } 189535870e50SAndrew Rybchenko 1896f28ede50SAndrew Rybchenko static const struct eth_dev_ops sfc_eth_dev_secondary_ops = { 18972646d42fSAndrew Rybchenko .dev_supported_ptypes_get = sfc_dev_supported_ptypes_get, 1898b76e1b2cSAndrew Rybchenko .rx_queue_count = sfc_rx_queue_count, 1899b76e1b2cSAndrew Rybchenko .rx_descriptor_done = sfc_rx_descriptor_done, 1900b76e1b2cSAndrew Rybchenko .rx_descriptor_status = sfc_rx_descriptor_status, 19013cf4b9c2SAndrew Rybchenko .tx_descriptor_status = sfc_tx_descriptor_status, 1902128da692SAndrew Rybchenko .reta_query = sfc_dev_rss_reta_query, 1903128da692SAndrew Rybchenko .rss_hash_conf_get = sfc_dev_rss_hash_conf_get, 1904f28ede50SAndrew Rybchenko .rxq_info_get = sfc_rx_queue_info_get, 1905f28ede50SAndrew Rybchenko .txq_info_get = sfc_tx_queue_info_get, 1906f28ede50SAndrew Rybchenko }; 1907f28ede50SAndrew Rybchenko 1908f28ede50SAndrew Rybchenko static int 19095dec95e3SAndrew Rybchenko sfc_eth_dev_secondary_init(struct rte_eth_dev *dev, uint32_t logtype_main) 1910f28ede50SAndrew Rybchenko { 191150f34eedSAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 19125dec95e3SAndrew Rybchenko struct sfc_adapter_priv *sap; 1913f28ede50SAndrew Rybchenko const struct sfc_dp_rx *dp_rx; 1914f28ede50SAndrew Rybchenko const struct sfc_dp_tx *dp_tx; 1915f28ede50SAndrew Rybchenko int rc; 1916f28ede50SAndrew Rybchenko 19175dec95e3SAndrew Rybchenko /* 19185dec95e3SAndrew Rybchenko * Allocate process private data from heap, since it should not 19195dec95e3SAndrew Rybchenko * be located in shared memory allocated using rte_malloc() API. 19205dec95e3SAndrew Rybchenko */ 19215dec95e3SAndrew Rybchenko sap = calloc(1, sizeof(*sap)); 19225dec95e3SAndrew Rybchenko if (sap == NULL) { 19235dec95e3SAndrew Rybchenko rc = ENOMEM; 19245dec95e3SAndrew Rybchenko goto fail_alloc_priv; 19255dec95e3SAndrew Rybchenko } 19265dec95e3SAndrew Rybchenko 1927f52fa243SAndrew Rybchenko sap->logtype_main = logtype_main; 1928f52fa243SAndrew Rybchenko 192950f34eedSAndrew Rybchenko dp_rx = sfc_dp_find_rx_by_name(&sfc_dp_head, sas->dp_rx_name); 1930f28ede50SAndrew Rybchenko if (dp_rx == NULL) { 193136653b7dSAndrew Rybchenko SFC_LOG(sas, RTE_LOG_ERR, logtype_main, 193250f34eedSAndrew Rybchenko "cannot find %s Rx datapath", sas->dp_rx_name); 1933f28ede50SAndrew Rybchenko rc = ENOENT; 1934f28ede50SAndrew Rybchenko goto fail_dp_rx; 1935f28ede50SAndrew Rybchenko } 1936f28ede50SAndrew Rybchenko if (~dp_rx->features & SFC_DP_RX_FEAT_MULTI_PROCESS) { 193736653b7dSAndrew Rybchenko SFC_LOG(sas, RTE_LOG_ERR, logtype_main, 1938e2c3639aSAndrew Rybchenko "%s Rx datapath does not support multi-process", 193950f34eedSAndrew Rybchenko sas->dp_rx_name); 1940f28ede50SAndrew Rybchenko rc = EINVAL; 1941f28ede50SAndrew Rybchenko goto fail_dp_rx_multi_process; 1942f28ede50SAndrew Rybchenko } 1943f28ede50SAndrew Rybchenko 194450f34eedSAndrew Rybchenko dp_tx = sfc_dp_find_tx_by_name(&sfc_dp_head, sas->dp_tx_name); 1945f28ede50SAndrew Rybchenko if (dp_tx == NULL) { 194636653b7dSAndrew Rybchenko SFC_LOG(sas, RTE_LOG_ERR, logtype_main, 194750f34eedSAndrew Rybchenko "cannot find %s Tx datapath", sas->dp_tx_name); 1948f28ede50SAndrew Rybchenko rc = ENOENT; 1949f28ede50SAndrew Rybchenko goto fail_dp_tx; 1950f28ede50SAndrew Rybchenko } 1951f28ede50SAndrew Rybchenko if (~dp_tx->features & SFC_DP_TX_FEAT_MULTI_PROCESS) { 195236653b7dSAndrew Rybchenko SFC_LOG(sas, RTE_LOG_ERR, logtype_main, 1953e2c3639aSAndrew Rybchenko "%s Tx datapath does not support multi-process", 195450f34eedSAndrew Rybchenko sas->dp_tx_name); 1955f28ede50SAndrew Rybchenko rc = EINVAL; 1956f28ede50SAndrew Rybchenko goto fail_dp_tx_multi_process; 1957f28ede50SAndrew Rybchenko } 1958f28ede50SAndrew Rybchenko 19595dec95e3SAndrew Rybchenko sap->dp_rx = dp_rx; 19605dec95e3SAndrew Rybchenko sap->dp_tx = dp_tx; 19615dec95e3SAndrew Rybchenko 19625dec95e3SAndrew Rybchenko dev->process_private = sap; 1963f28ede50SAndrew Rybchenko dev->rx_pkt_burst = dp_rx->pkt_burst; 1964f28ede50SAndrew Rybchenko dev->tx_pkt_burst = dp_tx->pkt_burst; 1965f28ede50SAndrew Rybchenko dev->dev_ops = &sfc_eth_dev_secondary_ops; 1966f28ede50SAndrew Rybchenko 1967f28ede50SAndrew Rybchenko return 0; 1968f28ede50SAndrew Rybchenko 1969f28ede50SAndrew Rybchenko fail_dp_tx_multi_process: 1970f28ede50SAndrew Rybchenko fail_dp_tx: 1971f28ede50SAndrew Rybchenko fail_dp_rx_multi_process: 1972f28ede50SAndrew Rybchenko fail_dp_rx: 19735dec95e3SAndrew Rybchenko free(sap); 19745dec95e3SAndrew Rybchenko 19755dec95e3SAndrew Rybchenko fail_alloc_priv: 1976f28ede50SAndrew Rybchenko return rc; 1977f28ede50SAndrew Rybchenko } 1978f28ede50SAndrew Rybchenko 1979f28ede50SAndrew Rybchenko static void 1980f28ede50SAndrew Rybchenko sfc_eth_dev_secondary_clear_ops(struct rte_eth_dev *dev) 1981f28ede50SAndrew Rybchenko { 19825dec95e3SAndrew Rybchenko free(dev->process_private); 19835dec95e3SAndrew Rybchenko dev->process_private = NULL; 1984f28ede50SAndrew Rybchenko dev->dev_ops = NULL; 1985f28ede50SAndrew Rybchenko dev->tx_pkt_burst = NULL; 1986f28ede50SAndrew Rybchenko dev->rx_pkt_burst = NULL; 1987f28ede50SAndrew Rybchenko } 1988f28ede50SAndrew Rybchenko 198935870e50SAndrew Rybchenko static void 1990df1bfde4SAndrew Rybchenko sfc_register_dp(void) 1991df1bfde4SAndrew Rybchenko { 1992df1bfde4SAndrew Rybchenko /* Register once */ 1993638bddc9SAndrew Rybchenko if (TAILQ_EMPTY(&sfc_dp_head)) { 1994638bddc9SAndrew Rybchenko /* Prefer EF10 datapath */ 1995390f9b8dSAndrew Rybchenko sfc_dp_register(&sfc_dp_head, &sfc_ef10_essb_rx.dp); 1996638bddc9SAndrew Rybchenko sfc_dp_register(&sfc_dp_head, &sfc_ef10_rx.dp); 1997df1bfde4SAndrew Rybchenko sfc_dp_register(&sfc_dp_head, &sfc_efx_rx.dp); 1998dbdc8241SAndrew Rybchenko 19998b00f426SAndrew Rybchenko sfc_dp_register(&sfc_dp_head, &sfc_ef10_tx.dp); 2000dbdc8241SAndrew Rybchenko sfc_dp_register(&sfc_dp_head, &sfc_efx_tx.dp); 200156885200SAndrew Rybchenko sfc_dp_register(&sfc_dp_head, &sfc_ef10_simple_tx.dp); 2002df1bfde4SAndrew Rybchenko } 2003638bddc9SAndrew Rybchenko } 2004df1bfde4SAndrew Rybchenko 2005df1bfde4SAndrew Rybchenko static int 200663d588ffSAndrew Rybchenko sfc_eth_dev_init(struct rte_eth_dev *dev) 200763d588ffSAndrew Rybchenko { 20085313b441SAndrew Rybchenko struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev); 2009c0802544SFerruh Yigit struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 2010e2c3639aSAndrew Rybchenko uint32_t logtype_main; 20115313b441SAndrew Rybchenko struct sfc_adapter *sa; 201263d588ffSAndrew Rybchenko int rc; 2013ba641f20SAndrew Rybchenko const efx_nic_cfg_t *encp; 2014ba641f20SAndrew Rybchenko const struct ether_addr *from; 201563d588ffSAndrew Rybchenko 2016df1bfde4SAndrew Rybchenko sfc_register_dp(); 2017df1bfde4SAndrew Rybchenko 2018e2c3639aSAndrew Rybchenko logtype_main = sfc_register_logtype(&pci_dev->addr, 2019e2c3639aSAndrew Rybchenko SFC_LOGTYPE_MAIN_STR, 2020e2c3639aSAndrew Rybchenko RTE_LOG_NOTICE); 2021e2c3639aSAndrew Rybchenko 2022f28ede50SAndrew Rybchenko if (rte_eal_process_type() != RTE_PROC_PRIMARY) 20235dec95e3SAndrew Rybchenko return -sfc_eth_dev_secondary_init(dev, logtype_main); 20245dec95e3SAndrew Rybchenko 202563d588ffSAndrew Rybchenko /* Required for logging */ 20261d3c7f9cSAndrew Rybchenko sas->pci_addr = pci_dev->addr; 20271d3c7f9cSAndrew Rybchenko sas->port_id = dev->data->port_id; 20285313b441SAndrew Rybchenko 20295313b441SAndrew Rybchenko /* 20305313b441SAndrew Rybchenko * Allocate process private data from heap, since it should not 20315313b441SAndrew Rybchenko * be located in shared memory allocated using rte_malloc() API. 20325313b441SAndrew Rybchenko */ 20335313b441SAndrew Rybchenko sa = calloc(1, sizeof(*sa)); 20345313b441SAndrew Rybchenko if (sa == NULL) { 20355313b441SAndrew Rybchenko rc = ENOMEM; 20365313b441SAndrew Rybchenko goto fail_alloc_sa; 20375313b441SAndrew Rybchenko } 20385313b441SAndrew Rybchenko 20395313b441SAndrew Rybchenko dev->process_private = sa; 20405313b441SAndrew Rybchenko 20415313b441SAndrew Rybchenko /* Required for logging */ 20425313b441SAndrew Rybchenko sa->priv.shared = sas; 2043f52fa243SAndrew Rybchenko sa->priv.logtype_main = logtype_main; 2044b7be9f43SAndrew Rybchenko 204563d588ffSAndrew Rybchenko sa->eth_dev = dev; 204663d588ffSAndrew Rybchenko 204763d588ffSAndrew Rybchenko /* Copy PCI device info to the dev->data */ 204863d588ffSAndrew Rybchenko rte_eth_copy_pci_info(dev, pci_dev); 204963d588ffSAndrew Rybchenko 205063d588ffSAndrew Rybchenko rc = sfc_kvargs_parse(sa); 205163d588ffSAndrew Rybchenko if (rc != 0) 205263d588ffSAndrew Rybchenko goto fail_kvargs_parse; 205363d588ffSAndrew Rybchenko 205463d588ffSAndrew Rybchenko sfc_log_init(sa, "entry"); 205563d588ffSAndrew Rybchenko 2056ba641f20SAndrew Rybchenko dev->data->mac_addrs = rte_zmalloc("sfc", ETHER_ADDR_LEN, 0); 2057ba641f20SAndrew Rybchenko if (dev->data->mac_addrs == NULL) { 2058ba641f20SAndrew Rybchenko rc = ENOMEM; 2059ba641f20SAndrew Rybchenko goto fail_mac_addrs; 2060ba641f20SAndrew Rybchenko } 2061ba641f20SAndrew Rybchenko 2062ba641f20SAndrew Rybchenko sfc_adapter_lock_init(sa); 2063ba641f20SAndrew Rybchenko sfc_adapter_lock(sa); 2064ba641f20SAndrew Rybchenko 2065329472d4SAndrew Rybchenko sfc_log_init(sa, "probing"); 2066329472d4SAndrew Rybchenko rc = sfc_probe(sa); 2067329472d4SAndrew Rybchenko if (rc != 0) 2068329472d4SAndrew Rybchenko goto fail_probe; 2069329472d4SAndrew Rybchenko 2070329472d4SAndrew Rybchenko sfc_log_init(sa, "set device ops"); 2071329472d4SAndrew Rybchenko rc = sfc_eth_dev_set_ops(dev); 2072329472d4SAndrew Rybchenko if (rc != 0) 2073329472d4SAndrew Rybchenko goto fail_set_ops; 2074329472d4SAndrew Rybchenko 2075ba641f20SAndrew Rybchenko sfc_log_init(sa, "attaching"); 2076ba641f20SAndrew Rybchenko rc = sfc_attach(sa); 2077ba641f20SAndrew Rybchenko if (rc != 0) 2078ba641f20SAndrew Rybchenko goto fail_attach; 2079ba641f20SAndrew Rybchenko 2080ba641f20SAndrew Rybchenko encp = efx_nic_cfg_get(sa->nic); 2081ba641f20SAndrew Rybchenko 2082ba641f20SAndrew Rybchenko /* 2083ba641f20SAndrew Rybchenko * The arguments are really reverse order in comparison to 2084ba641f20SAndrew Rybchenko * Linux kernel. Copy from NIC config to Ethernet device data. 2085ba641f20SAndrew Rybchenko */ 2086ba641f20SAndrew Rybchenko from = (const struct ether_addr *)(encp->enc_mac_addr); 2087ba641f20SAndrew Rybchenko ether_addr_copy(from, &dev->data->mac_addrs[0]); 2088ba641f20SAndrew Rybchenko 2089ba641f20SAndrew Rybchenko sfc_adapter_unlock(sa); 2090ba641f20SAndrew Rybchenko 209163d588ffSAndrew Rybchenko sfc_log_init(sa, "done"); 209263d588ffSAndrew Rybchenko return 0; 209363d588ffSAndrew Rybchenko 2094ba641f20SAndrew Rybchenko fail_attach: 209535870e50SAndrew Rybchenko sfc_eth_dev_clear_ops(dev); 209635870e50SAndrew Rybchenko 2097329472d4SAndrew Rybchenko fail_set_ops: 2098329472d4SAndrew Rybchenko sfc_unprobe(sa); 2099329472d4SAndrew Rybchenko 2100329472d4SAndrew Rybchenko fail_probe: 2101ba641f20SAndrew Rybchenko sfc_adapter_unlock(sa); 2102ba641f20SAndrew Rybchenko sfc_adapter_lock_fini(sa); 2103ba641f20SAndrew Rybchenko rte_free(dev->data->mac_addrs); 2104ba641f20SAndrew Rybchenko dev->data->mac_addrs = NULL; 2105ba641f20SAndrew Rybchenko 2106ba641f20SAndrew Rybchenko fail_mac_addrs: 210763d588ffSAndrew Rybchenko sfc_kvargs_cleanup(sa); 210863d588ffSAndrew Rybchenko 210963d588ffSAndrew Rybchenko fail_kvargs_parse: 211063d588ffSAndrew Rybchenko sfc_log_init(sa, "failed %d", rc); 21115dec95e3SAndrew Rybchenko dev->process_private = NULL; 21125313b441SAndrew Rybchenko free(sa); 21135313b441SAndrew Rybchenko 21145313b441SAndrew Rybchenko fail_alloc_sa: 211563d588ffSAndrew Rybchenko SFC_ASSERT(rc > 0); 211663d588ffSAndrew Rybchenko return -rc; 211763d588ffSAndrew Rybchenko } 211863d588ffSAndrew Rybchenko 211963d588ffSAndrew Rybchenko static int 212063d588ffSAndrew Rybchenko sfc_eth_dev_uninit(struct rte_eth_dev *dev) 212163d588ffSAndrew Rybchenko { 2122f28ede50SAndrew Rybchenko struct sfc_adapter *sa; 212363d588ffSAndrew Rybchenko 2124f28ede50SAndrew Rybchenko if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 2125f28ede50SAndrew Rybchenko sfc_eth_dev_secondary_clear_ops(dev); 2126f28ede50SAndrew Rybchenko return 0; 2127f28ede50SAndrew Rybchenko } 2128f28ede50SAndrew Rybchenko 21295313b441SAndrew Rybchenko sa = sfc_adapter_by_eth_dev(dev); 213063d588ffSAndrew Rybchenko sfc_log_init(sa, "entry"); 213163d588ffSAndrew Rybchenko 2132ba641f20SAndrew Rybchenko sfc_adapter_lock(sa); 2133ba641f20SAndrew Rybchenko 213435870e50SAndrew Rybchenko sfc_eth_dev_clear_ops(dev); 213535870e50SAndrew Rybchenko 2136ba641f20SAndrew Rybchenko sfc_detach(sa); 2137329472d4SAndrew Rybchenko sfc_unprobe(sa); 2138ba641f20SAndrew Rybchenko 213963d588ffSAndrew Rybchenko sfc_kvargs_cleanup(sa); 214063d588ffSAndrew Rybchenko 2141ba641f20SAndrew Rybchenko sfc_adapter_unlock(sa); 2142ba641f20SAndrew Rybchenko sfc_adapter_lock_fini(sa); 2143ba641f20SAndrew Rybchenko 214463d588ffSAndrew Rybchenko sfc_log_init(sa, "done"); 214563d588ffSAndrew Rybchenko 214663d588ffSAndrew Rybchenko /* Required for logging, so cleanup last */ 214763d588ffSAndrew Rybchenko sa->eth_dev = NULL; 21485313b441SAndrew Rybchenko 21495313b441SAndrew Rybchenko dev->process_private = NULL; 21505313b441SAndrew Rybchenko free(sa); 21515313b441SAndrew Rybchenko 215263d588ffSAndrew Rybchenko return 0; 215363d588ffSAndrew Rybchenko } 215463d588ffSAndrew Rybchenko 215563d588ffSAndrew Rybchenko static const struct rte_pci_id pci_id_sfc_efx_map[] = { 2156ba641f20SAndrew Rybchenko { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE) }, 2157223a29a2SIvan Malov { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE_VF) }, 2158ba641f20SAndrew Rybchenko { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT) }, 2159223a29a2SIvan Malov { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT_VF) }, 2160ba641f20SAndrew Rybchenko { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD) }, 2161223a29a2SIvan Malov { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD_VF) }, 2162f3129efdSAndrew Rybchenko { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD2) }, 2163f3129efdSAndrew Rybchenko { RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD2_VF) }, 216463d588ffSAndrew Rybchenko { .vendor_id = 0 /* sentinel */ } 216563d588ffSAndrew Rybchenko }; 216663d588ffSAndrew Rybchenko 2167fdf91e0fSJan Blunck static int sfc_eth_dev_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 2168fdf91e0fSJan Blunck struct rte_pci_device *pci_dev) 2169fdf91e0fSJan Blunck { 2170fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_probe(pci_dev, 21715313b441SAndrew Rybchenko sizeof(struct sfc_adapter_shared), sfc_eth_dev_init); 2172fdf91e0fSJan Blunck } 2173fdf91e0fSJan Blunck 2174fdf91e0fSJan Blunck static int sfc_eth_dev_pci_remove(struct rte_pci_device *pci_dev) 2175fdf91e0fSJan Blunck { 2176fdf91e0fSJan Blunck return rte_eth_dev_pci_generic_remove(pci_dev, sfc_eth_dev_uninit); 2177fdf91e0fSJan Blunck } 2178fdf91e0fSJan Blunck 2179fdf91e0fSJan Blunck static struct rte_pci_driver sfc_efx_pmd = { 218063d588ffSAndrew Rybchenko .id_table = pci_id_sfc_efx_map, 2181ba641f20SAndrew Rybchenko .drv_flags = 21823b809c27SAndrew Rybchenko RTE_PCI_DRV_INTR_LSC | 2183ba641f20SAndrew Rybchenko RTE_PCI_DRV_NEED_MAPPING, 2184fdf91e0fSJan Blunck .probe = sfc_eth_dev_pci_probe, 2185fdf91e0fSJan Blunck .remove = sfc_eth_dev_pci_remove, 218663d588ffSAndrew Rybchenko }; 218763d588ffSAndrew Rybchenko 2188fdf91e0fSJan Blunck RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd); 218963d588ffSAndrew Rybchenko RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map); 219006e81dc9SDavid Marchand RTE_PMD_REGISTER_KMOD_DEP(net_sfc_efx, "* igb_uio | uio_pci_generic | vfio-pci"); 219163d588ffSAndrew Rybchenko RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx, 2192df1bfde4SAndrew Rybchenko SFC_KVARG_RX_DATAPATH "=" SFC_KVARG_VALUES_RX_DATAPATH " " 2193dbdc8241SAndrew Rybchenko SFC_KVARG_TX_DATAPATH "=" SFC_KVARG_VALUES_TX_DATAPATH " " 2194c22d3c50SAndrew Rybchenko SFC_KVARG_PERF_PROFILE "=" SFC_KVARG_VALUES_PERF_PROFILE " " 21959e7fc8b8SRoman Zhukov SFC_KVARG_FW_VARIANT "=" SFC_KVARG_VALUES_FW_VARIANT " " 21965a1ae82dSAndrew Rybchenko SFC_KVARG_RXD_WAIT_TIMEOUT_NS "=<long> " 2197a6fae8f9SIvan Malov SFC_KVARG_STATS_UPDATE_PERIOD_MS "=<long>"); 2198fdceb100SIvan Malov 2199f8e99896SThomas Monjalon RTE_INIT(sfc_driver_register_logtype) 2200fdceb100SIvan Malov { 2201fdceb100SIvan Malov int ret; 2202fdceb100SIvan Malov 2203fdceb100SIvan Malov ret = rte_log_register_type_and_pick_level(SFC_LOGTYPE_PREFIX "driver", 2204fdceb100SIvan Malov RTE_LOG_NOTICE); 2205fdceb100SIvan Malov sfc_logtype_driver = (ret < 0) ? RTE_LOGTYPE_PMD : ret; 2206fdceb100SIvan Malov } 2207