1646ea79cSHeinrich Kuhn /* SPDX-License-Identifier: BSD-3-Clause 2646ea79cSHeinrich Kuhn * Copyright (c) 2014-2021 Netronome Systems, Inc. 3646ea79cSHeinrich Kuhn * All rights reserved. 4646ea79cSHeinrich Kuhn * 5646ea79cSHeinrich Kuhn * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation. 6646ea79cSHeinrich Kuhn */ 7646ea79cSHeinrich Kuhn 88ba461d1SPeng Zhang #include <unistd.h> 98ba461d1SPeng Zhang 105a95b024SChaoyong He #include <eal_firmware.h> 11851f03e1SHeinrich Kuhn #include <rte_alarm.h> 12b301fd73SPeng Zhang #include <rte_kvargs.h> 1320086cb8SPeng Zhang #include <rte_pci.h> 14646ea79cSHeinrich Kuhn 155a95b024SChaoyong He #include "flower/nfp_flower.h" 165a95b024SChaoyong He #include "nfd3/nfp_nfd3.h" 175a95b024SChaoyong He #include "nfdk/nfp_nfdk.h" 18646ea79cSHeinrich Kuhn #include "nfpcore/nfp_cpp.h" 19a2bc299dSPeng Zhang #include "nfpcore/nfp_elf.h" 20646ea79cSHeinrich Kuhn #include "nfpcore/nfp_hwinfo.h" 21646ea79cSHeinrich Kuhn #include "nfpcore/nfp_rtsym.h" 22646ea79cSHeinrich Kuhn #include "nfpcore/nfp_nsp.h" 23796f1aecSChaoyong He #include "nfpcore/nfp6000_pcie.h" 248ba461d1SPeng Zhang #include "nfpcore/nfp_resource.h" 256b4273a0SLong Wu #include "nfpcore/nfp_sync.h" 26646ea79cSHeinrich Kuhn 27646ea79cSHeinrich Kuhn #include "nfp_cpp_bridge.h" 2854713740SChang Miao #include "nfp_ipsec.h" 295a95b024SChaoyong He #include "nfp_logs.h" 308153bc6fSChaoyong He #include "nfp_net_flow.h" 31fb6befdfSLong Wu #include "nfp_rxtx_vec.h" 32b1880421SChaoyong He 33c7a6970fSZerun Fu /* 64-bit per app capabilities */ 34c7a6970fSZerun Fu #define NFP_NET_APP_CAP_SP_INDIFF RTE_BIT64(0) /* Indifferent to port speed */ 35c7a6970fSZerun Fu 36d505ee1dSChaoyong He #define NFP_PF_DRIVER_NAME net_nfp_pf 37b301fd73SPeng Zhang #define NFP_PF_FORCE_RELOAD_FW "force_reload_fw" 38c50bf4f0SLong Wu #define NFP_CPP_SERVICE_ENABLE "cpp_service_enable" 39bb24eb38SPeng Zhang #define NFP_QUEUE_PER_VF 1 40b301fd73SPeng Zhang 416484c847SChaoyong He struct nfp_net_init { 426484c847SChaoyong He /** Sequential physical port number, only valid for CoreNIC firmware */ 436484c847SChaoyong He uint8_t idx; 446484c847SChaoyong He 456484c847SChaoyong He /** Internal port number as seen from NFP */ 466484c847SChaoyong He uint8_t nfp_idx; 476484c847SChaoyong He 486484c847SChaoyong He struct nfp_net_hw_priv *hw_priv; 496484c847SChaoyong He }; 506484c847SChaoyong He 51b301fd73SPeng Zhang static int 52b301fd73SPeng Zhang nfp_devarg_handle_int(const char *key, 53b301fd73SPeng Zhang const char *value, 54b301fd73SPeng Zhang void *extra_args) 55b301fd73SPeng Zhang { 56b301fd73SPeng Zhang char *end_ptr; 57b301fd73SPeng Zhang uint64_t *num = extra_args; 58b301fd73SPeng Zhang 59b301fd73SPeng Zhang if (value == NULL) 60b301fd73SPeng Zhang return -EPERM; 61b301fd73SPeng Zhang 62b301fd73SPeng Zhang *num = strtoul(value, &end_ptr, 10); 63b301fd73SPeng Zhang if (*num == ULONG_MAX) { 64b6de4353SZerun Fu PMD_DRV_LOG(ERR, "%s: '%s' is not a valid param.", key, value); 65b301fd73SPeng Zhang return -ERANGE; 66b301fd73SPeng Zhang } else if (value == end_ptr) { 67b301fd73SPeng Zhang return -EPERM; 68b301fd73SPeng Zhang } 69b301fd73SPeng Zhang 70b301fd73SPeng Zhang return 0; 71b301fd73SPeng Zhang } 72b301fd73SPeng Zhang 731a114cd0SLong Wu static int 741a114cd0SLong Wu nfp_devarg_parse_bool_para(struct rte_kvargs *kvlist, 751a114cd0SLong Wu const char *key_match, 761a114cd0SLong Wu bool *value_ret) 77b301fd73SPeng Zhang { 78b301fd73SPeng Zhang int ret; 791a114cd0SLong Wu uint32_t count; 80b301fd73SPeng Zhang uint64_t value; 81b301fd73SPeng Zhang 821a114cd0SLong Wu count = rte_kvargs_count(kvlist, key_match); 831a114cd0SLong Wu if (count == 0) 841a114cd0SLong Wu return 0; 85b301fd73SPeng Zhang 861a114cd0SLong Wu if (count > 1) { 87b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Too much bool arguments: %s.", key_match); 881a114cd0SLong Wu return -EINVAL; 89b301fd73SPeng Zhang } 90b301fd73SPeng Zhang 911a114cd0SLong Wu ret = rte_kvargs_process(kvlist, key_match, &nfp_devarg_handle_int, &value); 921a114cd0SLong Wu if (ret != 0) 931a114cd0SLong Wu return -EINVAL; 941a114cd0SLong Wu 951a114cd0SLong Wu if (value == 1) { 961a114cd0SLong Wu *value_ret = true; 971a114cd0SLong Wu } else if (value == 0) { 981a114cd0SLong Wu *value_ret = false; 991a114cd0SLong Wu } else { 100b6de4353SZerun Fu PMD_DRV_LOG(ERR, "The param does not work, the format is %s=0/1.", 1011a114cd0SLong Wu key_match); 1021a114cd0SLong Wu return -EINVAL; 1031a114cd0SLong Wu } 1041a114cd0SLong Wu 1051a114cd0SLong Wu return 0; 1061a114cd0SLong Wu } 1071a114cd0SLong Wu 1081a114cd0SLong Wu static int 109b301fd73SPeng Zhang nfp_devargs_parse(struct nfp_devargs *nfp_devargs_param, 110b301fd73SPeng Zhang const struct rte_devargs *devargs) 111b301fd73SPeng Zhang { 1121a114cd0SLong Wu int ret; 113b301fd73SPeng Zhang struct rte_kvargs *kvlist; 114b301fd73SPeng Zhang 115b301fd73SPeng Zhang if (devargs == NULL) 1161a114cd0SLong Wu return 0; 117b301fd73SPeng Zhang 118b301fd73SPeng Zhang kvlist = rte_kvargs_parse(devargs->args, NULL); 119b301fd73SPeng Zhang if (kvlist == NULL) 1201a114cd0SLong Wu return -EINVAL; 121b301fd73SPeng Zhang 1221a114cd0SLong Wu ret = nfp_devarg_parse_bool_para(kvlist, NFP_PF_FORCE_RELOAD_FW, 1231a114cd0SLong Wu &nfp_devargs_param->force_reload_fw); 1241a114cd0SLong Wu if (ret != 0) 1251a114cd0SLong Wu goto exit; 126b301fd73SPeng Zhang 127c50bf4f0SLong Wu ret = nfp_devarg_parse_bool_para(kvlist, NFP_CPP_SERVICE_ENABLE, 128c50bf4f0SLong Wu &nfp_devargs_param->cpp_service_enable); 129c50bf4f0SLong Wu if (ret != 0) 130c50bf4f0SLong Wu goto exit; 131c50bf4f0SLong Wu 1321a114cd0SLong Wu exit: 133b301fd73SPeng Zhang rte_kvargs_free(kvlist); 1341a114cd0SLong Wu 1351a114cd0SLong Wu return ret; 136b301fd73SPeng Zhang } 137d505ee1dSChaoyong He 138a243128bSChaoyong He static void 139f4d24fe9SChaoyong He nfp_net_pf_read_mac(struct nfp_app_fw_nic *app_fw_nic, 140a9fa1da7SChaoyong He uint16_t port, 141a9fa1da7SChaoyong He struct nfp_net_hw_priv *hw_priv) 142646ea79cSHeinrich Kuhn { 14349952141SChaoyong He struct nfp_net_hw *hw; 144646ea79cSHeinrich Kuhn struct nfp_eth_table *nfp_eth_table; 145646ea79cSHeinrich Kuhn 146646ea79cSHeinrich Kuhn /* Grab a pointer to the correct physical port */ 147968ec1c3SChaoyong He hw = app_fw_nic->ports[port]; 148646ea79cSHeinrich Kuhn 149ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 150646ea79cSHeinrich Kuhn 151ef759759SChaoyong He rte_ether_addr_copy(&nfp_eth_table->ports[port].mac_addr, &hw->super.mac_addr); 152646ea79cSHeinrich Kuhn } 153646ea79cSHeinrich Kuhn 154009f43d5SZerun Fu static uint32_t 155009f43d5SZerun Fu nfp_net_speed_bitmap2speed(uint32_t speeds_bitmap) 156009f43d5SZerun Fu { 157009f43d5SZerun Fu switch (speeds_bitmap) { 158009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10M_HD: 159009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10M; 160009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10M: 161009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10M; 162009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100M_HD: 163009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100M; 164009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100M: 165009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100M; 166009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_1G: 167009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_1G; 168009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_2_5G: 169009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_2_5G; 170009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_5G: 171009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_5G; 172009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10G: 173009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10G; 174009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_20G: 175009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_20G; 176009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_25G: 177009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_25G; 178009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_40G: 179009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_40G; 180009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_50G: 181009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_50G; 182009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_56G: 183009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_56G; 184009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100G: 185009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100G; 186009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_200G: 187009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_200G; 188009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_400G: 189009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_400G; 190009f43d5SZerun Fu default: 191009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_NONE; 192009f43d5SZerun Fu } 193009f43d5SZerun Fu } 194009f43d5SZerun Fu 195009f43d5SZerun Fu static int 196009f43d5SZerun Fu nfp_net_nfp4000_speed_configure_check(uint16_t port_id, 197009f43d5SZerun Fu uint32_t configure_speed, 198009f43d5SZerun Fu struct nfp_eth_table *nfp_eth_table) 199009f43d5SZerun Fu { 200009f43d5SZerun Fu switch (port_id) { 201009f43d5SZerun Fu case 0: 202009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_25G && 203009f43d5SZerun Fu nfp_eth_table->ports[1].speed == RTE_ETH_SPEED_NUM_10G) { 204009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000."); 205009f43d5SZerun Fu return -ENOTSUP; 206009f43d5SZerun Fu } 207009f43d5SZerun Fu break; 208009f43d5SZerun Fu case 1: 209009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_10G && 210009f43d5SZerun Fu nfp_eth_table->ports[0].speed == RTE_ETH_SPEED_NUM_25G) { 211009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000."); 212009f43d5SZerun Fu return -ENOTSUP; 213009f43d5SZerun Fu } 214009f43d5SZerun Fu break; 215009f43d5SZerun Fu default: 216009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The port id is invalid."); 217009f43d5SZerun Fu return -EINVAL; 218009f43d5SZerun Fu } 219009f43d5SZerun Fu 220009f43d5SZerun Fu return 0; 221009f43d5SZerun Fu } 222009f43d5SZerun Fu 223009f43d5SZerun Fu static int 2244ef9e4e6SZerun Fu nfp_net_speed_autoneg_set(struct nfp_net_hw_priv *hw_priv, 2254ef9e4e6SZerun Fu struct nfp_eth_table_port *eth_port) 2264ef9e4e6SZerun Fu { 2274ef9e4e6SZerun Fu int ret; 2284ef9e4e6SZerun Fu struct nfp_nsp *nsp; 2294ef9e4e6SZerun Fu 2304ef9e4e6SZerun Fu nsp = nfp_eth_config_start(hw_priv->pf_dev->cpp, eth_port->index); 2314ef9e4e6SZerun Fu if (nsp == NULL) { 2324ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Could not get NSP."); 2334ef9e4e6SZerun Fu return -EIO; 2344ef9e4e6SZerun Fu } 2354ef9e4e6SZerun Fu 2364ef9e4e6SZerun Fu ret = nfp_eth_set_aneg(nsp, NFP_ANEG_AUTO); 2374ef9e4e6SZerun Fu if (ret != 0) { 2384ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Failed to set ANEG enable."); 2394ef9e4e6SZerun Fu nfp_eth_config_cleanup_end(nsp); 2404ef9e4e6SZerun Fu return ret; 2414ef9e4e6SZerun Fu } 2424ef9e4e6SZerun Fu 2434ef9e4e6SZerun Fu return nfp_eth_config_commit_end(nsp); 2444ef9e4e6SZerun Fu } 2454ef9e4e6SZerun Fu 2464ef9e4e6SZerun Fu static int 2474ef9e4e6SZerun Fu nfp_net_speed_fixed_set(struct nfp_net_hw_priv *hw_priv, 2484ef9e4e6SZerun Fu struct nfp_eth_table_port *eth_port, 2494ef9e4e6SZerun Fu uint32_t configure_speed) 2504ef9e4e6SZerun Fu { 2514ef9e4e6SZerun Fu int ret; 2524ef9e4e6SZerun Fu struct nfp_nsp *nsp; 2534ef9e4e6SZerun Fu 2544ef9e4e6SZerun Fu nsp = nfp_eth_config_start(hw_priv->pf_dev->cpp, eth_port->index); 2554ef9e4e6SZerun Fu if (nsp == NULL) { 2564ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Could not get NSP."); 2574ef9e4e6SZerun Fu return -EIO; 2584ef9e4e6SZerun Fu } 2594ef9e4e6SZerun Fu 2604ef9e4e6SZerun Fu ret = nfp_eth_set_aneg(nsp, NFP_ANEG_DISABLED); 2614ef9e4e6SZerun Fu if (ret != 0) { 2624ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Failed to set ANEG disable."); 2634ef9e4e6SZerun Fu goto config_cleanup; 2644ef9e4e6SZerun Fu } 2654ef9e4e6SZerun Fu 2664ef9e4e6SZerun Fu ret = nfp_eth_set_speed(nsp, configure_speed); 2674ef9e4e6SZerun Fu if (ret != 0) { 2684ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Failed to set speed."); 2694ef9e4e6SZerun Fu goto config_cleanup; 2704ef9e4e6SZerun Fu } 2714ef9e4e6SZerun Fu 2724ef9e4e6SZerun Fu return nfp_eth_config_commit_end(nsp); 2734ef9e4e6SZerun Fu 2744ef9e4e6SZerun Fu config_cleanup: 2754ef9e4e6SZerun Fu nfp_eth_config_cleanup_end(nsp); 2764ef9e4e6SZerun Fu 2774ef9e4e6SZerun Fu return ret; 2784ef9e4e6SZerun Fu } 2794ef9e4e6SZerun Fu 2804ef9e4e6SZerun Fu static int 281ff9f5a56SChaoyong He nfp_net_speed_configure(struct rte_eth_dev *dev) 282009f43d5SZerun Fu { 283009f43d5SZerun Fu int ret; 284c33504deSQin Ke uint8_t idx; 285009f43d5SZerun Fu uint32_t speed_capa; 286009f43d5SZerun Fu uint32_t link_speeds; 287009f43d5SZerun Fu uint32_t configure_speed; 288009f43d5SZerun Fu struct nfp_eth_table_port *eth_port; 289009f43d5SZerun Fu struct nfp_eth_table *nfp_eth_table; 290ff9f5a56SChaoyong He struct nfp_net_hw *net_hw = dev->data->dev_private; 291ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv = dev->process_private; 292009f43d5SZerun Fu 293c33504deSQin Ke idx = nfp_net_get_idx(dev); 294ff9f5a56SChaoyong He nfp_eth_table = hw_priv->pf_dev->nfp_eth_table; 295c33504deSQin Ke eth_port = &nfp_eth_table->ports[idx]; 296009f43d5SZerun Fu 297ff9f5a56SChaoyong He speed_capa = hw_priv->pf_dev->speed_capa; 298009f43d5SZerun Fu if (speed_capa == 0) { 299009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Speed_capa is invalid."); 300009f43d5SZerun Fu return -EINVAL; 301009f43d5SZerun Fu } 302009f43d5SZerun Fu 303009f43d5SZerun Fu link_speeds = dev->data->dev_conf.link_speeds; 304009f43d5SZerun Fu configure_speed = nfp_net_speed_bitmap2speed(speed_capa & link_speeds); 305009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_NONE && 306009f43d5SZerun Fu link_speeds != RTE_ETH_LINK_SPEED_AUTONEG) { 307009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Configured speed is invalid."); 308009f43d5SZerun Fu return -EINVAL; 309009f43d5SZerun Fu } 310009f43d5SZerun Fu 311009f43d5SZerun Fu /* NFP4000 does not allow the port 0 25Gbps and port 1 10Gbps at the same time. */ 312009f43d5SZerun Fu if (net_hw->device_id == PCI_DEVICE_ID_NFP4000_PF_NIC) { 313c33504deSQin Ke ret = nfp_net_nfp4000_speed_configure_check(idx, 314009f43d5SZerun Fu configure_speed, nfp_eth_table); 315009f43d5SZerun Fu if (ret != 0) { 316009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure speed for NFP4000."); 317009f43d5SZerun Fu return ret; 318009f43d5SZerun Fu } 319009f43d5SZerun Fu } 320009f43d5SZerun Fu 3214ef9e4e6SZerun Fu if (configure_speed == RTE_ETH_LINK_SPEED_AUTONEG) { 3224ef9e4e6SZerun Fu if (!eth_port->supp_aneg) 3234ef9e4e6SZerun Fu return 0; 324009f43d5SZerun Fu 3254ef9e4e6SZerun Fu if (eth_port->aneg == NFP_ANEG_AUTO) 3264ef9e4e6SZerun Fu return 0; 3274ef9e4e6SZerun Fu 3284ef9e4e6SZerun Fu ret = nfp_net_speed_autoneg_set(hw_priv, eth_port); 329009f43d5SZerun Fu if (ret != 0) { 3304ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Failed to set speed autoneg."); 3314ef9e4e6SZerun Fu return ret; 332009f43d5SZerun Fu } 333009f43d5SZerun Fu } else { 3344ef9e4e6SZerun Fu if (eth_port->aneg == NFP_ANEG_DISABLED && configure_speed == eth_port->speed) 3354ef9e4e6SZerun Fu return 0; 3364ef9e4e6SZerun Fu 3374ef9e4e6SZerun Fu ret = nfp_net_speed_fixed_set(hw_priv, eth_port, configure_speed); 338009f43d5SZerun Fu if (ret != 0) { 3394ef9e4e6SZerun Fu PMD_DRV_LOG(ERR, "Failed to set speed fixed."); 340009f43d5SZerun Fu return ret; 341009f43d5SZerun Fu } 3424ef9e4e6SZerun Fu } 3434ef9e4e6SZerun Fu 344aaa57548SZerun Fu hw_priv->pf_dev->speed_updated = true; 345aaa57548SZerun Fu 3464ef9e4e6SZerun Fu return 0; 3474ef9e4e6SZerun Fu } 348009f43d5SZerun Fu 349646ea79cSHeinrich Kuhn static int 350646ea79cSHeinrich Kuhn nfp_net_start(struct rte_eth_dev *dev) 351646ea79cSHeinrich Kuhn { 35249952141SChaoyong He int ret; 35349952141SChaoyong He uint16_t i; 35472d1dea6SChaoyong He struct nfp_hw *hw; 35549952141SChaoyong He uint32_t new_ctrl; 35649952141SChaoyong He uint32_t update = 0; 3572e7c3612SQin Ke uint32_t cap_extend; 35849952141SChaoyong He uint32_t intr_vector; 35949952141SChaoyong He uint32_t ctrl_extend = 0; 36072d1dea6SChaoyong He struct nfp_net_hw *net_hw; 361646ea79cSHeinrich Kuhn struct nfp_pf_dev *pf_dev; 362646ea79cSHeinrich Kuhn struct rte_eth_rxmode *rxmode; 3635126a904SLong Wu struct rte_eth_txmode *txmode; 364ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 36549952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 36649952141SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 36749952141SChaoyong He struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 368646ea79cSHeinrich Kuhn 3699d723baaSChaoyong He net_hw = dev->data->dev_private; 370ff9f5a56SChaoyong He hw_priv = dev->process_private; 371ff9f5a56SChaoyong He pf_dev = hw_priv->pf_dev; 372968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 37372d1dea6SChaoyong He hw = &net_hw->super; 374646ea79cSHeinrich Kuhn 375646ea79cSHeinrich Kuhn /* Disabling queues just in case... */ 376646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 377646ea79cSHeinrich Kuhn 378646ea79cSHeinrich Kuhn /* Enabling the required queues in the device */ 379646ea79cSHeinrich Kuhn nfp_net_enable_queues(dev); 380646ea79cSHeinrich Kuhn 381009f43d5SZerun Fu /* Configure the port speed and the auto-negotiation mode. */ 382ff9f5a56SChaoyong He ret = nfp_net_speed_configure(dev); 383009f43d5SZerun Fu if (ret < 0) { 384009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set the speed and auto-negotiation mode."); 385009f43d5SZerun Fu return ret; 386009f43d5SZerun Fu } 387009f43d5SZerun Fu 38840688372SChaoyong He /* Check and configure queue intr-vector mapping */ 389646ea79cSHeinrich Kuhn if (dev->data->dev_conf.intr_conf.rxq != 0) { 390968ec1c3SChaoyong He if (app_fw_nic->multiport) { 391646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt is not supported " 392b6de4353SZerun Fu "with NFP multiport PF."); 393646ea79cSHeinrich Kuhn return -EINVAL; 394646ea79cSHeinrich Kuhn } 395b0c496abSChaoyong He 396f4d24fe9SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 397646ea79cSHeinrich Kuhn /* 398646ea79cSHeinrich Kuhn * Better not to share LSC with RX interrupts. 39940688372SChaoyong He * Unregistering LSC interrupt handler. 400646ea79cSHeinrich Kuhn */ 401e7978635SChaoyong He rte_intr_callback_unregister(intr_handle, 402646ea79cSHeinrich Kuhn nfp_net_dev_interrupt_handler, (void *)dev); 403646ea79cSHeinrich Kuhn 404646ea79cSHeinrich Kuhn if (dev->data->nb_rx_queues > 1) { 405646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt only " 406b6de4353SZerun Fu "supports 1 queue with UIO."); 407646ea79cSHeinrich Kuhn return -EIO; 408646ea79cSHeinrich Kuhn } 409646ea79cSHeinrich Kuhn } 410b0c496abSChaoyong He 411646ea79cSHeinrich Kuhn intr_vector = dev->data->nb_rx_queues; 412c01e5c0cSChaoyong He if (rte_intr_efd_enable(intr_handle, intr_vector) != 0) 413646ea79cSHeinrich Kuhn return -1; 414646ea79cSHeinrich Kuhn 415646ea79cSHeinrich Kuhn nfp_configure_rx_interrupt(dev, intr_handle); 416646ea79cSHeinrich Kuhn update = NFP_NET_CFG_UPDATE_MSIX; 417646ea79cSHeinrich Kuhn } 418646ea79cSHeinrich Kuhn 419dbad6f64SPeng Zhang /* Checking MTU set */ 42072d1dea6SChaoyong He if (dev->data->mtu > net_hw->flbufsz) { 421b6de4353SZerun Fu PMD_INIT_LOG(ERR, "MTU (%u) can not be larger than the current NFP_FRAME_SIZE (%u).", 42272d1dea6SChaoyong He dev->data->mtu, net_hw->flbufsz); 423dbad6f64SPeng Zhang return -ERANGE; 424dbad6f64SPeng Zhang } 425dbad6f64SPeng Zhang 426646ea79cSHeinrich Kuhn rte_intr_enable(intr_handle); 427646ea79cSHeinrich Kuhn 428646ea79cSHeinrich Kuhn new_ctrl = nfp_check_offloads(dev); 429646ea79cSHeinrich Kuhn 430646ea79cSHeinrich Kuhn /* Writing configuration parameters in the device */ 43172d1dea6SChaoyong He nfp_net_params_setup(net_hw); 432646ea79cSHeinrich Kuhn 433c4de52ecSChaoyong He rxmode = &dev->data->dev_conf.rxmode; 434b8e15e9fSLong Wu if ((rxmode->offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) != 0) { 435646ea79cSHeinrich Kuhn nfp_net_rss_config_default(dev); 436646ea79cSHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_RSS; 43772d1dea6SChaoyong He new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap); 438646ea79cSHeinrich Kuhn } 439646ea79cSHeinrich Kuhn 440646ea79cSHeinrich Kuhn /* Enable device */ 441646ea79cSHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; 442646ea79cSHeinrich Kuhn 443646ea79cSHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING; 444646ea79cSHeinrich Kuhn 4455126a904SLong Wu txmode = &dev->data->dev_conf.txmode; 446c55abf61SChaoyong He 44772d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0) 448646ea79cSHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; 449646ea79cSHeinrich Kuhn 450ff9da649SLong Wu if ((hw->cap & NFP_NET_CFG_CTRL_TXRWB) != 0) 451ff9da649SLong Wu new_ctrl |= NFP_NET_CFG_CTRL_TXRWB; 452ff9da649SLong Wu 45372d1dea6SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) 454646ea79cSHeinrich Kuhn return -EIO; 455646ea79cSHeinrich Kuhn 4561e80c074SChaoyong He hw->ctrl = new_ctrl; 4571e80c074SChaoyong He 4582e7c3612SQin Ke /* Enable packet type offload by extend ctrl word1. */ 45972d1dea6SChaoyong He cap_extend = hw->cap_ext; 4602e7c3612SQin Ke if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0) 4612e7c3612SQin Ke ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE; 4622e7c3612SQin Ke 46353e1412dSLong Wu if ((rxmode->offloads & RTE_ETH_RX_OFFLOAD_SECURITY) != 0 || 46453e1412dSLong Wu (txmode->offloads & RTE_ETH_TX_OFFLOAD_SECURITY) != 0) { 46554713740SChang Miao if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) 4669177c800SChaoyong He ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC | 4679177c800SChaoyong He NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP | 4689177c800SChaoyong He NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP; 46953e1412dSLong Wu } 47054713740SChang Miao 4718153bc6fSChaoyong He /* Enable flow steer by extend ctrl word1. */ 4728153bc6fSChaoyong He if ((cap_extend & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) 4738153bc6fSChaoyong He ctrl_extend |= NFP_NET_CFG_CTRL_FLOW_STEER; 4748153bc6fSChaoyong He 4752e7c3612SQin Ke update = NFP_NET_CFG_UPDATE_GEN; 47672d1dea6SChaoyong He if (nfp_ext_reconfig(hw, ctrl_extend, update) != 0) 4772e7c3612SQin Ke return -EIO; 4782e7c3612SQin Ke 47972d1dea6SChaoyong He hw->ctrl_ext = ctrl_extend; 480b4b6988aSChaoyong He 481646ea79cSHeinrich Kuhn /* 482646ea79cSHeinrich Kuhn * Allocating rte mbufs for configured rx queues. 48340688372SChaoyong He * This requires queues being enabled before. 484646ea79cSHeinrich Kuhn */ 485c01e5c0cSChaoyong He if (nfp_net_rx_freelist_setup(dev) != 0) { 486646ea79cSHeinrich Kuhn ret = -ENOMEM; 487646ea79cSHeinrich Kuhn goto error; 488646ea79cSHeinrich Kuhn } 489646ea79cSHeinrich Kuhn 490acb6bebfSChaoyong He /* Configure the physical port up */ 4911580387eSChaoyong He ret = nfp_eth_set_configured(pf_dev->cpp, net_hw->nfp_idx, 1); 4921580387eSChaoyong He if (ret < 0) 4931580387eSChaoyong He goto error; 494646ea79cSHeinrich Kuhn 495c46216e7SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 496c46216e7SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 497c46216e7SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 498c46216e7SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 499c46216e7SJie Hai 500646ea79cSHeinrich Kuhn return 0; 501646ea79cSHeinrich Kuhn 502646ea79cSHeinrich Kuhn error: 503646ea79cSHeinrich Kuhn /* 504646ea79cSHeinrich Kuhn * An error returned by this function should mean the app 505646ea79cSHeinrich Kuhn * exiting and then the system releasing all the memory 506646ea79cSHeinrich Kuhn * allocated even memory coming from hugepages. 507646ea79cSHeinrich Kuhn * 508646ea79cSHeinrich Kuhn * The device could be enabled at this point with some queues 509646ea79cSHeinrich Kuhn * ready for getting packets. This is true if the call to 510646ea79cSHeinrich Kuhn * nfp_net_rx_freelist_setup() succeeds for some queues but 511646ea79cSHeinrich Kuhn * fails for subsequent queues. 512646ea79cSHeinrich Kuhn * 513646ea79cSHeinrich Kuhn * This should make the app exiting but better if we tell the 514646ea79cSHeinrich Kuhn * device first. 515646ea79cSHeinrich Kuhn */ 516646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 517646ea79cSHeinrich Kuhn 518646ea79cSHeinrich Kuhn return ret; 519646ea79cSHeinrich Kuhn } 520646ea79cSHeinrich Kuhn 521646ea79cSHeinrich Kuhn /* Set the link up. */ 522646ea79cSHeinrich Kuhn static int 523646ea79cSHeinrich Kuhn nfp_net_set_link_up(struct rte_eth_dev *dev) 524646ea79cSHeinrich Kuhn { 5250ca4f216SChaoyong He int ret; 526646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 527ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 528646ea79cSHeinrich Kuhn 5299d723baaSChaoyong He hw = dev->data->dev_private; 530ff9f5a56SChaoyong He hw_priv = dev->process_private; 531646ea79cSHeinrich Kuhn 5320ca4f216SChaoyong He ret = nfp_eth_set_configured(hw_priv->pf_dev->cpp, hw->nfp_idx, 1); 5330ca4f216SChaoyong He if (ret < 0) 5340ca4f216SChaoyong He return ret; 5350ca4f216SChaoyong He 5360ca4f216SChaoyong He return 0; 537646ea79cSHeinrich Kuhn } 538646ea79cSHeinrich Kuhn 539646ea79cSHeinrich Kuhn /* Set the link down. */ 540646ea79cSHeinrich Kuhn static int 541646ea79cSHeinrich Kuhn nfp_net_set_link_down(struct rte_eth_dev *dev) 542646ea79cSHeinrich Kuhn { 5430ca4f216SChaoyong He int ret; 544646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 545ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 546646ea79cSHeinrich Kuhn 5479d723baaSChaoyong He hw = dev->data->dev_private; 548ff9f5a56SChaoyong He hw_priv = dev->process_private; 549646ea79cSHeinrich Kuhn 5500ca4f216SChaoyong He ret = nfp_eth_set_configured(hw_priv->pf_dev->cpp, hw->nfp_idx, 0); 5510ca4f216SChaoyong He if (ret < 0) 5520ca4f216SChaoyong He return ret; 5530ca4f216SChaoyong He 5540ca4f216SChaoyong He return 0; 555646ea79cSHeinrich Kuhn } 556646ea79cSHeinrich Kuhn 5578ba461d1SPeng Zhang static void 5588ba461d1SPeng Zhang nfp_net_beat_timer(void *arg) 5598ba461d1SPeng Zhang { 5608ba461d1SPeng Zhang uint64_t cur_sec; 5618ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf = arg; 5628ba461d1SPeng Zhang 5638ba461d1SPeng Zhang cur_sec = rte_rdtsc(); 5648ba461d1SPeng Zhang nn_writeq(cur_sec, multi_pf->beat_addr + NFP_BEAT_OFFSET(multi_pf->function_id)); 5658ba461d1SPeng Zhang 5668ba461d1SPeng Zhang /* Beat once per second. */ 5678ba461d1SPeng Zhang if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer, 5688ba461d1SPeng Zhang (void *)multi_pf) < 0) { 569b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Error setting alarm."); 5708ba461d1SPeng Zhang } 5718ba461d1SPeng Zhang } 5728ba461d1SPeng Zhang 5738ba461d1SPeng Zhang static int 5748ba461d1SPeng Zhang nfp_net_keepalive_init(struct nfp_cpp *cpp, 5758ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 5768ba461d1SPeng Zhang { 5778ba461d1SPeng Zhang uint8_t *base; 5788ba461d1SPeng Zhang uint64_t addr; 5798ba461d1SPeng Zhang uint32_t size; 5808ba461d1SPeng Zhang uint32_t cpp_id; 5818ba461d1SPeng Zhang struct nfp_resource *res; 5828ba461d1SPeng Zhang 5838ba461d1SPeng Zhang res = nfp_resource_acquire(cpp, NFP_RESOURCE_KEEPALIVE); 5848ba461d1SPeng Zhang if (res == NULL) 5858ba461d1SPeng Zhang return -EIO; 5868ba461d1SPeng Zhang 5878ba461d1SPeng Zhang cpp_id = nfp_resource_cpp_id(res); 5888ba461d1SPeng Zhang addr = nfp_resource_address(res); 5898ba461d1SPeng Zhang size = nfp_resource_size(res); 5908ba461d1SPeng Zhang 5918ba461d1SPeng Zhang nfp_resource_release(res); 5928ba461d1SPeng Zhang 5938ba461d1SPeng Zhang /* Allocate a fixed area for keepalive. */ 5948ba461d1SPeng Zhang base = nfp_cpp_map_area(cpp, cpp_id, addr, size, &multi_pf->beat_area); 5958ba461d1SPeng Zhang if (base == NULL) { 5968ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Failed to map area for keepalive."); 5978ba461d1SPeng Zhang return -EIO; 5988ba461d1SPeng Zhang } 5998ba461d1SPeng Zhang 6008ba461d1SPeng Zhang multi_pf->beat_addr = base; 6018ba461d1SPeng Zhang 6028ba461d1SPeng Zhang return 0; 6038ba461d1SPeng Zhang } 6048ba461d1SPeng Zhang 6058ba461d1SPeng Zhang static void 6068ba461d1SPeng Zhang nfp_net_keepalive_uninit(struct nfp_multi_pf *multi_pf) 6078ba461d1SPeng Zhang { 6088ba461d1SPeng Zhang nfp_cpp_area_release_free(multi_pf->beat_area); 6098ba461d1SPeng Zhang } 6108ba461d1SPeng Zhang 6118ba461d1SPeng Zhang static int 6128ba461d1SPeng Zhang nfp_net_keepalive_start(struct nfp_multi_pf *multi_pf) 6138ba461d1SPeng Zhang { 6148ba461d1SPeng Zhang if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer, 6158ba461d1SPeng Zhang (void *)multi_pf) < 0) { 616b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Error setting alarm."); 6178ba461d1SPeng Zhang return -EIO; 6188ba461d1SPeng Zhang } 6198ba461d1SPeng Zhang 6208ba461d1SPeng Zhang return 0; 6218ba461d1SPeng Zhang } 6228ba461d1SPeng Zhang 6238ba461d1SPeng Zhang static void 624b67a7b40SPeng Zhang nfp_net_keepalive_clear(uint8_t *beat_addr, 625b67a7b40SPeng Zhang uint8_t function_id) 626b67a7b40SPeng Zhang { 627b67a7b40SPeng Zhang nn_writeq(0, beat_addr + NFP_BEAT_OFFSET(function_id)); 628b67a7b40SPeng Zhang } 629b67a7b40SPeng Zhang 630b67a7b40SPeng Zhang static void 631b67a7b40SPeng Zhang nfp_net_keepalive_clear_others(const struct nfp_dev_info *dev_info, 632b67a7b40SPeng Zhang struct nfp_multi_pf *multi_pf) 633b67a7b40SPeng Zhang { 634b67a7b40SPeng Zhang uint8_t port_num; 635b67a7b40SPeng Zhang 636b67a7b40SPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 637b67a7b40SPeng Zhang if (port_num == multi_pf->function_id) 638b67a7b40SPeng Zhang continue; 639b67a7b40SPeng Zhang 640b67a7b40SPeng Zhang nfp_net_keepalive_clear(multi_pf->beat_addr, port_num); 641b67a7b40SPeng Zhang } 642b67a7b40SPeng Zhang } 643b67a7b40SPeng Zhang 644b67a7b40SPeng Zhang static void 6458ba461d1SPeng Zhang nfp_net_keepalive_stop(struct nfp_multi_pf *multi_pf) 6468ba461d1SPeng Zhang { 6478ba461d1SPeng Zhang /* Cancel keepalive for multiple PF setup */ 6488ba461d1SPeng Zhang rte_eal_alarm_cancel(nfp_net_beat_timer, (void *)multi_pf); 6498ba461d1SPeng Zhang } 6508ba461d1SPeng Zhang 6516484c847SChaoyong He static int 6528b8f116bSChaoyong He nfp_net_uninit(struct rte_eth_dev *eth_dev) 6538b8f116bSChaoyong He { 6548b8f116bSChaoyong He struct nfp_net_hw *net_hw; 655ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 6568b8f116bSChaoyong He 6578b8f116bSChaoyong He net_hw = eth_dev->data->dev_private; 658ff9f5a56SChaoyong He hw_priv = eth_dev->process_private; 6598153bc6fSChaoyong He 6608153bc6fSChaoyong He if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) 661ff9f5a56SChaoyong He nfp_net_flow_priv_uninit(hw_priv->pf_dev, net_hw->idx); 6628153bc6fSChaoyong He 6638b8f116bSChaoyong He rte_free(net_hw->eth_xstats_base); 664ff9da649SLong Wu if ((net_hw->super.cap & NFP_NET_CFG_CTRL_TXRWB) != 0) 665ff9da649SLong Wu nfp_net_txrwb_free(eth_dev); 6668b8f116bSChaoyong He nfp_ipsec_uninit(eth_dev); 6676484c847SChaoyong He 6686484c847SChaoyong He return 0; 6698b8f116bSChaoyong He } 6708b8f116bSChaoyong He 67166d5f53dSChaoyong He static void 67266d5f53dSChaoyong He nfp_cleanup_port_app_fw_nic(struct nfp_pf_dev *pf_dev, 673a9fa1da7SChaoyong He uint8_t id, 674a9fa1da7SChaoyong He struct rte_eth_dev *eth_dev) 67566d5f53dSChaoyong He { 67666d5f53dSChaoyong He struct nfp_app_fw_nic *app_fw_nic; 67766d5f53dSChaoyong He 67866d5f53dSChaoyong He app_fw_nic = pf_dev->app_fw_priv; 67966d5f53dSChaoyong He if (app_fw_nic->ports[id] != NULL) { 68066d5f53dSChaoyong He nfp_net_uninit(eth_dev); 68166d5f53dSChaoyong He app_fw_nic->ports[id] = NULL; 68266d5f53dSChaoyong He } 68366d5f53dSChaoyong He } 68466d5f53dSChaoyong He 68566d5f53dSChaoyong He static void 68666d5f53dSChaoyong He nfp_uninit_app_fw_nic(struct nfp_pf_dev *pf_dev) 68766d5f53dSChaoyong He { 68866d5f53dSChaoyong He nfp_cpp_area_release_free(pf_dev->ctrl_area); 68966d5f53dSChaoyong He rte_free(pf_dev->app_fw_priv); 69066d5f53dSChaoyong He } 69166d5f53dSChaoyong He 69219542093SPeng Zhang static void 69319542093SPeng Zhang nfp_net_vf_config_uninit(struct nfp_pf_dev *pf_dev) 69419542093SPeng Zhang { 69519542093SPeng Zhang if (pf_dev->sriov_vf == 0) 69619542093SPeng Zhang return; 69719542093SPeng Zhang 69819542093SPeng Zhang nfp_cpp_area_release_free(pf_dev->vf_cfg_tbl_area); 69919542093SPeng Zhang nfp_cpp_area_release_free(pf_dev->vf_area); 70019542093SPeng Zhang } 70119542093SPeng Zhang 70266d5f53dSChaoyong He void 703ff9f5a56SChaoyong He nfp_pf_uninit(struct nfp_net_hw_priv *hw_priv) 70466d5f53dSChaoyong He { 705ff9f5a56SChaoyong He struct nfp_pf_dev *pf_dev = hw_priv->pf_dev; 706ff9f5a56SChaoyong He 707c50bf4f0SLong Wu if (pf_dev->devargs.cpp_service_enable) 708929b0531SLong Wu nfp_disable_cpp_service(pf_dev); 70919542093SPeng Zhang nfp_net_vf_config_uninit(pf_dev); 710e54d68a0SChaoyong He nfp_cpp_area_release_free(pf_dev->mac_stats_area); 71166d5f53dSChaoyong He nfp_cpp_area_release_free(pf_dev->qc_area); 71266d5f53dSChaoyong He free(pf_dev->sym_tbl); 71366d5f53dSChaoyong He if (pf_dev->multi_pf.enabled) { 71466d5f53dSChaoyong He nfp_net_keepalive_stop(&pf_dev->multi_pf); 715b67a7b40SPeng Zhang nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id); 71666d5f53dSChaoyong He nfp_net_keepalive_uninit(&pf_dev->multi_pf); 71766d5f53dSChaoyong He } 71866d5f53dSChaoyong He free(pf_dev->nfp_eth_table); 71966d5f53dSChaoyong He free(pf_dev->hwinfo); 72066d5f53dSChaoyong He nfp_cpp_free(pf_dev->cpp); 7216b4273a0SLong Wu nfp_sync_free(pf_dev->sync); 72266d5f53dSChaoyong He rte_free(pf_dev); 723ff9f5a56SChaoyong He rte_free(hw_priv); 72466d5f53dSChaoyong He } 72566d5f53dSChaoyong He 72666d5f53dSChaoyong He static int 727ff9f5a56SChaoyong He nfp_pf_secondary_uninit(struct nfp_net_hw_priv *hw_priv) 72866d5f53dSChaoyong He { 729ff9f5a56SChaoyong He struct nfp_pf_dev *pf_dev = hw_priv->pf_dev; 730ff9f5a56SChaoyong He 73166d5f53dSChaoyong He free(pf_dev->sym_tbl); 73266d5f53dSChaoyong He nfp_cpp_free(pf_dev->cpp); 7336b4273a0SLong Wu nfp_sync_free(pf_dev->sync); 73466d5f53dSChaoyong He rte_free(pf_dev); 735ff9f5a56SChaoyong He rte_free(hw_priv); 73666d5f53dSChaoyong He 73766d5f53dSChaoyong He return 0; 73866d5f53dSChaoyong He } 73966d5f53dSChaoyong He 740646ea79cSHeinrich Kuhn /* Reset and stop device. The device can not be restarted. */ 741646ea79cSHeinrich Kuhn static int 742646ea79cSHeinrich Kuhn nfp_net_close(struct rte_eth_dev *dev) 743646ea79cSHeinrich Kuhn { 7448ceb85c3SChaoyong He uint8_t i; 7453b00109dSPeng Zhang uint8_t id; 74649952141SChaoyong He struct nfp_net_hw *hw; 74749952141SChaoyong He struct nfp_pf_dev *pf_dev; 74849952141SChaoyong He struct rte_pci_device *pci_dev; 749ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 75049952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 751646ea79cSHeinrich Kuhn 752ff9f5a56SChaoyong He hw_priv = dev->process_private; 753ff9f5a56SChaoyong He 75466d5f53dSChaoyong He /* 75566d5f53dSChaoyong He * In secondary process, a released eth device can be found by its name 75666d5f53dSChaoyong He * in shared memory. 75766d5f53dSChaoyong He * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the 75866d5f53dSChaoyong He * eth device has been released. 75966d5f53dSChaoyong He */ 76066d5f53dSChaoyong He if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 76166d5f53dSChaoyong He if (dev->state == RTE_ETH_DEV_UNUSED) 762646ea79cSHeinrich Kuhn return 0; 763646ea79cSHeinrich Kuhn 764ff9f5a56SChaoyong He nfp_pf_secondary_uninit(hw_priv); 76566d5f53dSChaoyong He return 0; 76666d5f53dSChaoyong He } 76766d5f53dSChaoyong He 7689d723baaSChaoyong He hw = dev->data->dev_private; 769ff9f5a56SChaoyong He pf_dev = hw_priv->pf_dev; 770646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(dev); 771968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 772646ea79cSHeinrich Kuhn 773646ea79cSHeinrich Kuhn /* 774646ea79cSHeinrich Kuhn * We assume that the DPDK application is stopping all the 775646ea79cSHeinrich Kuhn * threads/queues before calling the device close function. 776646ea79cSHeinrich Kuhn */ 777646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 778646ea79cSHeinrich Kuhn 779646ea79cSHeinrich Kuhn /* Clear queues */ 7801c8d02bbSJin Liu nfp_net_close_tx_queue(dev); 7811c8d02bbSJin Liu nfp_net_close_rx_queue(dev); 782646ea79cSHeinrich Kuhn 783851f03e1SHeinrich Kuhn /* Cancel possible impending LSC work here before releasing the port */ 784f4d24fe9SChaoyong He rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev); 785851f03e1SHeinrich Kuhn 786646ea79cSHeinrich Kuhn /* Only free PF resources after all physical ports have been closed */ 787646ea79cSHeinrich Kuhn /* Mark this port as unused and free device priv resources */ 788f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_LSC, 0xff); 78966d5f53dSChaoyong He 79066d5f53dSChaoyong He if (pf_dev->app_fw_id != NFP_APP_FW_CORE_NIC) 79166d5f53dSChaoyong He return -EINVAL; 79266d5f53dSChaoyong He 793a9fa1da7SChaoyong He nfp_cleanup_port_app_fw_nic(pf_dev, hw->idx, dev); 794646ea79cSHeinrich Kuhn 7956408420cSPeng Zhang for (i = 0; i < pf_dev->total_phyports; i++) { 7963b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 7973b00109dSPeng Zhang 798646ea79cSHeinrich Kuhn /* Check to see if ports are still in use */ 7993b00109dSPeng Zhang if (app_fw_nic->ports[id] != NULL) 800646ea79cSHeinrich Kuhn return 0; 801646ea79cSHeinrich Kuhn } 802646ea79cSHeinrich Kuhn 80366d5f53dSChaoyong He /* Enable in nfp_net_start() */ 804d61138d4SHarman Kalra rte_intr_disable(pci_dev->intr_handle); 805646ea79cSHeinrich Kuhn 80666d5f53dSChaoyong He /* Register in nfp_net_init() */ 807d61138d4SHarman Kalra rte_intr_callback_unregister(pci_dev->intr_handle, 808a6189a67SJin Liu nfp_net_dev_interrupt_handler, (void *)dev); 809646ea79cSHeinrich Kuhn 81066d5f53dSChaoyong He nfp_uninit_app_fw_nic(pf_dev); 811ff9f5a56SChaoyong He nfp_pf_uninit(hw_priv); 81266d5f53dSChaoyong He 813646ea79cSHeinrich Kuhn return 0; 814646ea79cSHeinrich Kuhn } 815646ea79cSHeinrich Kuhn 816c55abf61SChaoyong He static int 817c55abf61SChaoyong He nfp_net_find_vxlan_idx(struct nfp_net_hw *hw, 818c55abf61SChaoyong He uint16_t port, 819c55abf61SChaoyong He uint32_t *idx) 820c55abf61SChaoyong He { 821c55abf61SChaoyong He uint32_t i; 822c55abf61SChaoyong He int free_idx = -1; 823c55abf61SChaoyong He 824c55abf61SChaoyong He for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i++) { 825c55abf61SChaoyong He if (hw->vxlan_ports[i] == port) { 826c55abf61SChaoyong He free_idx = i; 827c55abf61SChaoyong He break; 828c55abf61SChaoyong He } 829c55abf61SChaoyong He 830c55abf61SChaoyong He if (hw->vxlan_usecnt[i] == 0) { 831c55abf61SChaoyong He free_idx = i; 832c55abf61SChaoyong He break; 833c55abf61SChaoyong He } 834c55abf61SChaoyong He } 835c55abf61SChaoyong He 836c55abf61SChaoyong He if (free_idx == -1) 837c55abf61SChaoyong He return -EINVAL; 838c55abf61SChaoyong He 839c55abf61SChaoyong He *idx = free_idx; 840c55abf61SChaoyong He 841c55abf61SChaoyong He return 0; 842c55abf61SChaoyong He } 843c55abf61SChaoyong He 844c55abf61SChaoyong He static int 845c55abf61SChaoyong He nfp_udp_tunnel_port_add(struct rte_eth_dev *dev, 846c55abf61SChaoyong He struct rte_eth_udp_tunnel *tunnel_udp) 847c55abf61SChaoyong He { 848c55abf61SChaoyong He int ret; 849c55abf61SChaoyong He uint32_t idx; 8505b81c1e2SLong Wu uint32_t ctrl; 8515b81c1e2SLong Wu struct nfp_hw *hw; 852c55abf61SChaoyong He uint16_t vxlan_port; 8535b81c1e2SLong Wu struct nfp_net_hw *net_hw; 854c55abf61SChaoyong He enum rte_eth_tunnel_type tnl_type; 855c55abf61SChaoyong He 8565b81c1e2SLong Wu net_hw = dev->data->dev_private; 857c55abf61SChaoyong He vxlan_port = tunnel_udp->udp_port; 858c55abf61SChaoyong He tnl_type = tunnel_udp->prot_type; 859c55abf61SChaoyong He 860c55abf61SChaoyong He if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) { 861b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Not VXLAN tunnel."); 862c55abf61SChaoyong He return -ENOTSUP; 863c55abf61SChaoyong He } 864c55abf61SChaoyong He 8655b81c1e2SLong Wu ret = nfp_net_find_vxlan_idx(net_hw, vxlan_port, &idx); 866c55abf61SChaoyong He if (ret != 0) { 867b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed find valid vxlan idx."); 868c55abf61SChaoyong He return -EINVAL; 869c55abf61SChaoyong He } 870c55abf61SChaoyong He 8715b81c1e2SLong Wu if (net_hw->vxlan_usecnt[idx] == 0) { 8725b81c1e2SLong Wu hw = &net_hw->super; 8735b81c1e2SLong Wu ctrl = hw->ctrl | NFP_NET_CFG_CTRL_VXLAN; 8745b81c1e2SLong Wu 8755b81c1e2SLong Wu ret = nfp_net_set_vxlan_port(net_hw, idx, vxlan_port, ctrl); 876c55abf61SChaoyong He if (ret != 0) { 877b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed set vxlan port."); 878c55abf61SChaoyong He return -EINVAL; 879c55abf61SChaoyong He } 8805b81c1e2SLong Wu 8815b81c1e2SLong Wu hw->ctrl = ctrl; 882c55abf61SChaoyong He } 883c55abf61SChaoyong He 8845b81c1e2SLong Wu net_hw->vxlan_usecnt[idx]++; 885c55abf61SChaoyong He 886c55abf61SChaoyong He return 0; 887c55abf61SChaoyong He } 888c55abf61SChaoyong He 889c55abf61SChaoyong He static int 890c55abf61SChaoyong He nfp_udp_tunnel_port_del(struct rte_eth_dev *dev, 891c55abf61SChaoyong He struct rte_eth_udp_tunnel *tunnel_udp) 892c55abf61SChaoyong He { 893c55abf61SChaoyong He int ret; 894c55abf61SChaoyong He uint32_t idx; 8955b81c1e2SLong Wu uint32_t ctrl; 8965b81c1e2SLong Wu struct nfp_hw *hw; 897c55abf61SChaoyong He uint16_t vxlan_port; 8985b81c1e2SLong Wu struct nfp_net_hw *net_hw; 899c55abf61SChaoyong He enum rte_eth_tunnel_type tnl_type; 900c55abf61SChaoyong He 9015b81c1e2SLong Wu net_hw = dev->data->dev_private; 902c55abf61SChaoyong He vxlan_port = tunnel_udp->udp_port; 903c55abf61SChaoyong He tnl_type = tunnel_udp->prot_type; 904c55abf61SChaoyong He 905c55abf61SChaoyong He if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) { 906b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Not VXLAN tunnel."); 907c55abf61SChaoyong He return -ENOTSUP; 908c55abf61SChaoyong He } 909c55abf61SChaoyong He 9105b81c1e2SLong Wu ret = nfp_net_find_vxlan_idx(net_hw, vxlan_port, &idx); 9115b81c1e2SLong Wu if (ret != 0 || net_hw->vxlan_usecnt[idx] == 0) { 912b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed find valid vxlan idx."); 913c55abf61SChaoyong He return -EINVAL; 914c55abf61SChaoyong He } 915c55abf61SChaoyong He 9165b81c1e2SLong Wu net_hw->vxlan_usecnt[idx]--; 917c55abf61SChaoyong He 9185b81c1e2SLong Wu if (net_hw->vxlan_usecnt[idx] == 0) { 9195b81c1e2SLong Wu hw = &net_hw->super; 9205b81c1e2SLong Wu ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_VXLAN; 9215b81c1e2SLong Wu 9225b81c1e2SLong Wu ret = nfp_net_set_vxlan_port(net_hw, idx, 0, ctrl); 923c55abf61SChaoyong He if (ret != 0) { 924b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Failed set vxlan port."); 925c55abf61SChaoyong He return -EINVAL; 926c55abf61SChaoyong He } 9275b81c1e2SLong Wu 9285b81c1e2SLong Wu hw->ctrl = ctrl; 929c55abf61SChaoyong He } 930c55abf61SChaoyong He 931c55abf61SChaoyong He return 0; 932c55abf61SChaoyong He } 933c55abf61SChaoyong He 934646ea79cSHeinrich Kuhn /* Initialise and register driver with DPDK Application */ 9358d961320SJin Liu static const struct eth_dev_ops nfp_net_eth_dev_ops = { 936646ea79cSHeinrich Kuhn .dev_configure = nfp_net_configure, 937646ea79cSHeinrich Kuhn .dev_start = nfp_net_start, 938646ea79cSHeinrich Kuhn .dev_stop = nfp_net_stop, 939646ea79cSHeinrich Kuhn .dev_set_link_up = nfp_net_set_link_up, 940646ea79cSHeinrich Kuhn .dev_set_link_down = nfp_net_set_link_down, 941646ea79cSHeinrich Kuhn .dev_close = nfp_net_close, 942646ea79cSHeinrich Kuhn .promiscuous_enable = nfp_net_promisc_enable, 943646ea79cSHeinrich Kuhn .promiscuous_disable = nfp_net_promisc_disable, 9444a86c36bSQin Ke .allmulticast_enable = nfp_net_allmulticast_enable, 9454a86c36bSQin Ke .allmulticast_disable = nfp_net_allmulticast_disable, 946646ea79cSHeinrich Kuhn .link_update = nfp_net_link_update, 947646ea79cSHeinrich Kuhn .stats_get = nfp_net_stats_get, 948646ea79cSHeinrich Kuhn .stats_reset = nfp_net_stats_reset, 949f26e8239SJames Hershaw .xstats_get = nfp_net_xstats_get, 950f26e8239SJames Hershaw .xstats_reset = nfp_net_xstats_reset, 951f26e8239SJames Hershaw .xstats_get_names = nfp_net_xstats_get_names, 952f26e8239SJames Hershaw .xstats_get_by_id = nfp_net_xstats_get_by_id, 953f26e8239SJames Hershaw .xstats_get_names_by_id = nfp_net_xstats_get_names_by_id, 954646ea79cSHeinrich Kuhn .dev_infos_get = nfp_net_infos_get, 955646ea79cSHeinrich Kuhn .dev_supported_ptypes_get = nfp_net_supported_ptypes_get, 956a498019dSLong Wu .dev_ptypes_set = nfp_net_ptypes_set, 957646ea79cSHeinrich Kuhn .mtu_set = nfp_net_dev_mtu_set, 9580a94d6bcSJin Liu .mac_addr_set = nfp_net_set_mac_addr, 959646ea79cSHeinrich Kuhn .vlan_offload_set = nfp_net_vlan_offload_set, 960646ea79cSHeinrich Kuhn .reta_update = nfp_net_reta_update, 961646ea79cSHeinrich Kuhn .reta_query = nfp_net_reta_query, 962646ea79cSHeinrich Kuhn .rss_hash_update = nfp_net_rss_hash_update, 963646ea79cSHeinrich Kuhn .rss_hash_conf_get = nfp_net_rss_hash_conf_get, 964646ea79cSHeinrich Kuhn .rx_queue_setup = nfp_net_rx_queue_setup, 965646ea79cSHeinrich Kuhn .rx_queue_release = nfp_net_rx_queue_release, 96630198b3fSLong Wu .rxq_info_get = nfp_net_rx_queue_info_get, 9678d961320SJin Liu .tx_queue_setup = nfp_net_tx_queue_setup, 96852ddc4c2SJin Liu .tx_queue_release = nfp_net_tx_queue_release, 969fbe2e2ecSLong Wu .txq_info_get = nfp_net_tx_queue_info_get, 97052ddc4c2SJin Liu .rx_queue_intr_enable = nfp_rx_queue_intr_enable, 97152ddc4c2SJin Liu .rx_queue_intr_disable = nfp_rx_queue_intr_disable, 972c55abf61SChaoyong He .udp_tunnel_port_add = nfp_udp_tunnel_port_add, 973c55abf61SChaoyong He .udp_tunnel_port_del = nfp_udp_tunnel_port_del, 974128c8ad9SChaoyong He .fw_version_get = nfp_net_firmware_version_get, 97551d15e82SZerun Fu .flow_ctrl_get = nfp_net_flow_ctrl_get, 97668aa3537SZerun Fu .flow_ctrl_set = nfp_net_flow_ctrl_set, 9770b9079d2SChaoyong He .flow_ops_get = nfp_net_flow_ops_get, 9780786add9SZerun Fu .fec_get_capability = nfp_net_fec_get_capability, 979c6835a32SZerun Fu .fec_get = nfp_net_fec_get, 98037bd1b84SZerun Fu .fec_set = nfp_net_fec_set, 9817f693813SChaoyong He .get_eeprom_length = nfp_net_get_eeprom_len, 9827f693813SChaoyong He .get_eeprom = nfp_net_get_eeprom, 9837f693813SChaoyong He .set_eeprom = nfp_net_set_eeprom, 9847f693813SChaoyong He .get_module_info = nfp_net_get_module_info, 9857f693813SChaoyong He .get_module_eeprom = nfp_net_get_module_eeprom, 9868bd6f540SChaoyong He .dev_led_on = nfp_net_led_on, 9878bd6f540SChaoyong He .dev_led_off = nfp_net_led_off, 988*4dcbf32fSChaoyong He .rx_burst_mode_get = nfp_net_rx_burst_mode_get, 989*4dcbf32fSChaoyong He .tx_burst_mode_get = nfp_net_tx_burst_mode_get, 99052ddc4c2SJin Liu }; 99152ddc4c2SJin Liu 992ee8ca64eSChaoyong He static inline void 993000feb4cSChaoyong He nfp_net_ethdev_ops_mount(struct nfp_pf_dev *pf_dev, 994ee8ca64eSChaoyong He struct rte_eth_dev *eth_dev) 995266470b2SJin Liu { 996000feb4cSChaoyong He if (pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 997ee8ca64eSChaoyong He eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts; 998ee8ca64eSChaoyong He else 999fb6befdfSLong Wu nfp_net_nfdk_xmit_pkts_set(eth_dev); 1000266470b2SJin Liu 10018d961320SJin Liu eth_dev->dev_ops = &nfp_net_eth_dev_ops; 1002266470b2SJin Liu eth_dev->rx_queue_count = nfp_net_rx_queue_count; 1003b6755530SLong Wu nfp_net_recv_pkts_set(eth_dev); 1004266470b2SJin Liu } 1005266470b2SJin Liu 1006646ea79cSHeinrich Kuhn static int 10076484c847SChaoyong He nfp_net_init(struct rte_eth_dev *eth_dev, 10086484c847SChaoyong He void *para) 1009646ea79cSHeinrich Kuhn { 101049952141SChaoyong He int err; 101149952141SChaoyong He uint16_t port; 10120314a8ffSChaoyong He uint64_t rx_base; 10130314a8ffSChaoyong He uint64_t tx_base; 10144a9bb682SChaoyong He struct nfp_hw *hw; 10154a9bb682SChaoyong He struct nfp_net_hw *net_hw; 101649952141SChaoyong He struct nfp_pf_dev *pf_dev; 10176484c847SChaoyong He struct nfp_net_init *hw_init; 101849952141SChaoyong He struct rte_pci_device *pci_dev; 1019ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 102049952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 1021646ea79cSHeinrich Kuhn 1022646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 102365f6915dSChaoyong He net_hw = eth_dev->data->dev_private; 1024646ea79cSHeinrich Kuhn 10256484c847SChaoyong He hw_init = para; 10266484c847SChaoyong He net_hw->idx = hw_init->idx; 10276484c847SChaoyong He net_hw->nfp_idx = hw_init->nfp_idx; 10286484c847SChaoyong He eth_dev->process_private = hw_init->hw_priv; 10296484c847SChaoyong He 1030646ea79cSHeinrich Kuhn /* Use backpointer here to the PF of this eth_dev */ 1031ff9f5a56SChaoyong He hw_priv = eth_dev->process_private; 1032ff9f5a56SChaoyong He pf_dev = hw_priv->pf_dev; 1033646ea79cSHeinrich Kuhn 1034968ec1c3SChaoyong He /* Use backpointer to the CoreNIC app struct */ 1035968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 1036968ec1c3SChaoyong He 10376484c847SChaoyong He /* Add this device to the PF's array of physical ports */ 10386484c847SChaoyong He app_fw_nic->ports[net_hw->idx] = net_hw; 10396484c847SChaoyong He 10406484c847SChaoyong He port = net_hw->idx; 10418ceb85c3SChaoyong He if (port > 7) { 1042b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Port value is wrong."); 1043646ea79cSHeinrich Kuhn return -ENODEV; 1044646ea79cSHeinrich Kuhn } 1045646ea79cSHeinrich Kuhn 10464a9bb682SChaoyong He hw = &net_hw->super; 1047646ea79cSHeinrich Kuhn 1048030b2b19SChaoyong He PMD_INIT_LOG(DEBUG, "Working with physical port number: %hu, " 1049b6de4353SZerun Fu "NFP internal port number: %d.", port, net_hw->nfp_idx); 1050646ea79cSHeinrich Kuhn 1051646ea79cSHeinrich Kuhn rte_eth_copy_pci_info(eth_dev, pci_dev); 1052646ea79cSHeinrich Kuhn 1053e54d68a0SChaoyong He if (pf_dev->multi_pf.enabled) 10544a9bb682SChaoyong He hw->ctrl_bar = pf_dev->ctrl_bar; 1055e54d68a0SChaoyong He else 105619bd7cceSChaoyong He hw->ctrl_bar = pf_dev->ctrl_bar + (port * pf_dev->ctrl_bar_size); 1057e54d68a0SChaoyong He 1058e54d68a0SChaoyong He net_hw->mac_stats = pf_dev->mac_stats_bar + 10594a9bb682SChaoyong He (net_hw->nfp_idx * NFP_MAC_STATS_SIZE); 1060646ea79cSHeinrich Kuhn 1061b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "Ctrl bar: %p.", hw->ctrl_bar); 1062b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "MAC stats: %p.", net_hw->mac_stats); 1063646ea79cSHeinrich Kuhn 1064000feb4cSChaoyong He err = nfp_net_common_init(pf_dev, net_hw); 1065cd4397ebSPeng Zhang if (err != 0) 1066e54d68a0SChaoyong He return err; 1067fd392f84SPeng Zhang 1068eecdfcc1SShihong Wang err = nfp_net_tlv_caps_parse(eth_dev); 1069eecdfcc1SShihong Wang if (err != 0) { 1070b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to parser TLV caps."); 1071e54d68a0SChaoyong He return err; 1072eecdfcc1SShihong Wang } 1073eecdfcc1SShihong Wang 107454713740SChang Miao err = nfp_ipsec_init(eth_dev); 107554713740SChang Miao if (err != 0) { 1076b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to init IPsec module."); 1077e54d68a0SChaoyong He return err; 107854713740SChang Miao } 107954713740SChang Miao 1080000feb4cSChaoyong He nfp_net_ethdev_ops_mount(pf_dev, eth_dev); 1081266470b2SJin Liu 10824a9bb682SChaoyong He net_hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) * 1083f26e8239SJames Hershaw nfp_net_xstats_size(eth_dev), 0); 10844a9bb682SChaoyong He if (net_hw->eth_xstats_base == NULL) { 1085f6272c7aSZerun Fu PMD_INIT_LOG(ERR, "No memory for xstats base values on device %s!", 1086f26e8239SJames Hershaw pci_dev->device.name); 108736994566SChaoyong He err = -ENOMEM; 108836994566SChaoyong He goto ipsec_exit; 1089f26e8239SJames Hershaw } 1090f26e8239SJames Hershaw 1091646ea79cSHeinrich Kuhn /* Work out where in the BAR the queues start. */ 10924a9bb682SChaoyong He tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 10934a9bb682SChaoyong He rx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ); 1094646ea79cSHeinrich Kuhn 10954a9bb682SChaoyong He net_hw->tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ; 10964a9bb682SChaoyong He net_hw->rx_bar = pf_dev->qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ; 1097646ea79cSHeinrich Kuhn 1098b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "The ctrl_bar: %p, tx_bar: %p, rx_bar: %p.", 10994a9bb682SChaoyong He hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar); 1100646ea79cSHeinrich Kuhn 11014a9bb682SChaoyong He nfp_net_cfg_queue_setup(net_hw); 11024a9bb682SChaoyong He net_hw->mtu = RTE_ETHER_MTU; 1103646ea79cSHeinrich Kuhn 1104646ea79cSHeinrich Kuhn /* VLAN insertion is incompatible with LSOv2 */ 11054a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0) 11064a9bb682SChaoyong He hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN; 1107646ea79cSHeinrich Kuhn 1108000feb4cSChaoyong He nfp_net_log_device_information(net_hw, pf_dev); 1109646ea79cSHeinrich Kuhn 1110646ea79cSHeinrich Kuhn /* Initializing spinlock for reconfigs */ 11114a9bb682SChaoyong He rte_spinlock_init(&hw->reconfig_lock); 1112646ea79cSHeinrich Kuhn 111387abbaf9SPeng Zhang if ((port == 0 || pf_dev->multi_pf.enabled)) { 111487abbaf9SPeng Zhang err = nfp_net_vf_config_app_init(net_hw, pf_dev); 111587abbaf9SPeng Zhang if (err != 0) { 1116b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to init sriov module."); 111787abbaf9SPeng Zhang goto xstats_free; 111887abbaf9SPeng Zhang } 111987abbaf9SPeng Zhang } 112087abbaf9SPeng Zhang 1121646ea79cSHeinrich Kuhn /* Allocating memory for mac addr */ 1122f4d24fe9SChaoyong He eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0); 1123646ea79cSHeinrich Kuhn if (eth_dev->data->mac_addrs == NULL) { 1124b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to space for MAC address."); 112536994566SChaoyong He err = -ENOMEM; 112636994566SChaoyong He goto xstats_free; 1127646ea79cSHeinrich Kuhn } 1128646ea79cSHeinrich Kuhn 1129ff9da649SLong Wu if ((hw->cap & NFP_NET_CFG_CTRL_TXRWB) != 0) { 1130ff9da649SLong Wu err = nfp_net_txrwb_alloc(eth_dev); 1131ff9da649SLong Wu if (err != 0) 1132ff9da649SLong Wu goto xstats_free; 1133ff9da649SLong Wu } 1134ff9da649SLong Wu 1135a9fa1da7SChaoyong He nfp_net_pf_read_mac(app_fw_nic, port, hw_priv); 1136503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 1137646ea79cSHeinrich Kuhn 11384a9bb682SChaoyong He if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) { 1139b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Using random mac address for port %d.", port); 1140646ea79cSHeinrich Kuhn /* Using random mac addresses for VFs */ 11414a9bb682SChaoyong He rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]); 1142503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 1143646ea79cSHeinrich Kuhn } 1144646ea79cSHeinrich Kuhn 1145646ea79cSHeinrich Kuhn /* Copying mac address to DPDK eth_dev struct */ 11464a9bb682SChaoyong He rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs); 1147646ea79cSHeinrich Kuhn 11484a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) 1149646ea79cSHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR; 1150646ea79cSHeinrich Kuhn 1151646ea79cSHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 1152646ea79cSHeinrich Kuhn 1153f6272c7aSZerun Fu PMD_INIT_LOG(INFO, "Port %d VendorID=%#x DeviceID=%#x " 1154c2c4f87bSAman Deep Singh "mac=" RTE_ETHER_ADDR_PRT_FMT, 1155646ea79cSHeinrich Kuhn eth_dev->data->port_id, pci_dev->id.vendor_id, 1156646ea79cSHeinrich Kuhn pci_dev->id.device_id, 11574a9bb682SChaoyong He RTE_ETHER_ADDR_BYTES(&hw->mac_addr)); 1158646ea79cSHeinrich Kuhn 1159646ea79cSHeinrich Kuhn /* Registering LSC interrupt handler */ 1160d61138d4SHarman Kalra rte_intr_callback_register(pci_dev->intr_handle, 1161a6189a67SJin Liu nfp_net_dev_interrupt_handler, (void *)eth_dev); 1162646ea79cSHeinrich Kuhn /* Telling the firmware about the LSC interrupt entry */ 11634a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); 116494d0631aSPeng Zhang /* Unmask the LSC interrupt */ 116594d0631aSPeng Zhang nfp_net_irq_unmask(eth_dev); 1166646ea79cSHeinrich Kuhn /* Recording current stats counters values */ 1167646ea79cSHeinrich Kuhn nfp_net_stats_reset(eth_dev); 1168646ea79cSHeinrich Kuhn 11698153bc6fSChaoyong He if ((hw->cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) { 11708153bc6fSChaoyong He err = nfp_net_flow_priv_init(pf_dev, port); 11718153bc6fSChaoyong He if (err != 0) { 1172b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Init net flow priv failed."); 1173ff9da649SLong Wu goto txrwb_free; 11748153bc6fSChaoyong He } 11758153bc6fSChaoyong He } 11768153bc6fSChaoyong He 1177646ea79cSHeinrich Kuhn return 0; 117836994566SChaoyong He 1179ff9da649SLong Wu txrwb_free: 1180ff9da649SLong Wu if ((hw->cap & NFP_NET_CFG_CTRL_TXRWB) != 0) 1181ff9da649SLong Wu nfp_net_txrwb_free(eth_dev); 118236994566SChaoyong He xstats_free: 118336994566SChaoyong He rte_free(net_hw->eth_xstats_base); 118436994566SChaoyong He ipsec_exit: 118536994566SChaoyong He nfp_ipsec_uninit(eth_dev); 118636994566SChaoyong He 118736994566SChaoyong He return err; 1188646ea79cSHeinrich Kuhn } 1189646ea79cSHeinrich Kuhn 119008461d7bSPeng Zhang static int 11916f708e52SChaoyong He nfp_net_device_activate(struct nfp_pf_dev *pf_dev) 119208461d7bSPeng Zhang { 119308461d7bSPeng Zhang int ret; 119408461d7bSPeng Zhang struct nfp_nsp *nsp; 11956f708e52SChaoyong He struct nfp_multi_pf *multi_pf; 119608461d7bSPeng Zhang 11976f708e52SChaoyong He multi_pf = &pf_dev->multi_pf; 119808461d7bSPeng Zhang if (multi_pf->enabled && multi_pf->function_id != 0) { 11996f708e52SChaoyong He nsp = nfp_nsp_open(pf_dev->cpp); 120008461d7bSPeng Zhang if (nsp == NULL) { 1201b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle."); 120208461d7bSPeng Zhang return -EIO; 120308461d7bSPeng Zhang } 120408461d7bSPeng Zhang 120508461d7bSPeng Zhang ret = nfp_nsp_device_activate(nsp); 120608461d7bSPeng Zhang nfp_nsp_close(nsp); 120708461d7bSPeng Zhang if (ret != 0 && ret != -EOPNOTSUPP) 120808461d7bSPeng Zhang return ret; 120908461d7bSPeng Zhang } 121008461d7bSPeng Zhang 121108461d7bSPeng Zhang return 0; 121208461d7bSPeng Zhang } 121308461d7bSPeng Zhang 1214646ea79cSHeinrich Kuhn #define DEFAULT_FW_PATH "/lib/firmware/netronome" 1215646ea79cSHeinrich Kuhn 1216646ea79cSHeinrich Kuhn static int 12176f708e52SChaoyong He nfp_fw_get_name(struct nfp_pf_dev *pf_dev, 1218ebfb540eSPeng Zhang char *fw_name, 1219ebfb540eSPeng Zhang size_t fw_size) 1220646ea79cSHeinrich Kuhn { 122149952141SChaoyong He char serial[40]; 1222ff627b74SChaoyong He uint16_t interface; 122330f9f163SChaoyong He char card_desc[100]; 1224ff627b74SChaoyong He uint32_t cpp_serial_len; 122530f9f163SChaoyong He const char *nfp_fw_model; 1226ff627b74SChaoyong He const uint8_t *cpp_serial; 1227ff627b74SChaoyong He 12286f708e52SChaoyong He cpp_serial_len = nfp_cpp_serial(pf_dev->cpp, &cpp_serial); 1229ff627b74SChaoyong He if (cpp_serial_len != NFP_SERIAL_LEN) 1230ff627b74SChaoyong He return -ERANGE; 1231ff627b74SChaoyong He 12326f708e52SChaoyong He interface = nfp_cpp_interface(pf_dev->cpp); 1233646ea79cSHeinrich Kuhn 1234646ea79cSHeinrich Kuhn /* Looking for firmware file in order of priority */ 1235646ea79cSHeinrich Kuhn 1236646ea79cSHeinrich Kuhn /* First try to find a firmware image specific for this device */ 1237646ea79cSHeinrich Kuhn snprintf(serial, sizeof(serial), 1238646ea79cSHeinrich Kuhn "serial-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 1239ff627b74SChaoyong He cpp_serial[0], cpp_serial[1], cpp_serial[2], cpp_serial[3], 1240ff627b74SChaoyong He cpp_serial[4], cpp_serial[5], interface >> 8, interface & 0xff); 1241ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/%s.nffw", DEFAULT_FW_PATH, serial); 1242646ea79cSHeinrich Kuhn 1243b6de4353SZerun Fu PMD_DRV_LOG(DEBUG, "Trying with fw file: %s.", fw_name); 1244ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1245ebfb540eSPeng Zhang return 0; 1246b0c496abSChaoyong He 1247646ea79cSHeinrich Kuhn /* Then try the PCI name */ 1248ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/pci-%s.nffw", DEFAULT_FW_PATH, 12496f708e52SChaoyong He pf_dev->pci_dev->name); 1250646ea79cSHeinrich Kuhn 1251b6de4353SZerun Fu PMD_DRV_LOG(DEBUG, "Trying with fw file: %s.", fw_name); 1252ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1253ebfb540eSPeng Zhang return 0; 1254646ea79cSHeinrich Kuhn 12556f708e52SChaoyong He nfp_fw_model = nfp_hwinfo_lookup(pf_dev->hwinfo, "nffw.partno"); 125630f9f163SChaoyong He if (nfp_fw_model == NULL) { 12576f708e52SChaoyong He nfp_fw_model = nfp_hwinfo_lookup(pf_dev->hwinfo, "assembly.partno"); 125830f9f163SChaoyong He if (nfp_fw_model == NULL) { 1259b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Firmware model NOT found."); 126030f9f163SChaoyong He return -EIO; 126130f9f163SChaoyong He } 126230f9f163SChaoyong He } 126330f9f163SChaoyong He 1264a2a0edc5SChaoyong He /* And then try the model name */ 1265a2a0edc5SChaoyong He snprintf(card_desc, sizeof(card_desc), "%s.nffw", nfp_fw_model); 1266a2a0edc5SChaoyong He snprintf(fw_name, fw_size, "%s/%s", DEFAULT_FW_PATH, card_desc); 1267b6de4353SZerun Fu PMD_DRV_LOG(DEBUG, "Trying with fw file: %s.", fw_name); 1268a2a0edc5SChaoyong He if (access(fw_name, F_OK) == 0) 1269a2a0edc5SChaoyong He return 0; 1270a2a0edc5SChaoyong He 1271646ea79cSHeinrich Kuhn /* Finally try the card type and media */ 127230f9f163SChaoyong He snprintf(card_desc, sizeof(card_desc), "nic_%s_%dx%d.nffw", 12736f708e52SChaoyong He nfp_fw_model, pf_dev->nfp_eth_table->count, 12746f708e52SChaoyong He pf_dev->nfp_eth_table->ports[0].speed / 1000); 127530f9f163SChaoyong He snprintf(fw_name, fw_size, "%s/%s", DEFAULT_FW_PATH, card_desc); 1276b6de4353SZerun Fu PMD_DRV_LOG(DEBUG, "Trying with fw file: %s.", fw_name); 1277ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1278ebfb540eSPeng Zhang return 0; 1279c01e5c0cSChaoyong He 1280646ea79cSHeinrich Kuhn return -ENOENT; 1281ebfb540eSPeng Zhang } 1282646ea79cSHeinrich Kuhn 1283ebfb540eSPeng Zhang static int 1284ebfb540eSPeng Zhang nfp_fw_upload(struct nfp_nsp *nsp, 1285ebfb540eSPeng Zhang char *fw_name) 1286ebfb540eSPeng Zhang { 1287ebfb540eSPeng Zhang int err; 1288ebfb540eSPeng Zhang void *fw_buf; 1289ebfb540eSPeng Zhang size_t fsize; 1290ebfb540eSPeng Zhang 1291ebfb540eSPeng Zhang err = rte_firmware_read(fw_name, &fw_buf, &fsize); 1292ebfb540eSPeng Zhang if (err != 0) { 1293f6272c7aSZerun Fu PMD_DRV_LOG(ERR, "Firmware %s not found!", fw_name); 1294ebfb540eSPeng Zhang return -ENOENT; 1295ebfb540eSPeng Zhang } 1296ebfb540eSPeng Zhang 1297b6de4353SZerun Fu PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu.", 1298646ea79cSHeinrich Kuhn fw_name, fsize); 1299646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Uploading the firmware ..."); 13002e634b03SPeng Zhang if (nfp_nsp_load_fw(nsp, fw_buf, fsize) < 0) { 13012e634b03SPeng Zhang free(fw_buf); 13022e634b03SPeng Zhang PMD_DRV_LOG(ERR, "Firmware load failed."); 13032e634b03SPeng Zhang return -EIO; 13042e634b03SPeng Zhang } 13052e634b03SPeng Zhang 1306b6de4353SZerun Fu PMD_DRV_LOG(INFO, "Done."); 1307646ea79cSHeinrich Kuhn 1308646ea79cSHeinrich Kuhn free(fw_buf); 1309646ea79cSHeinrich Kuhn 1310646ea79cSHeinrich Kuhn return 0; 1311646ea79cSHeinrich Kuhn } 1312646ea79cSHeinrich Kuhn 13133b00109dSPeng Zhang static void 13143b00109dSPeng Zhang nfp_fw_unload(struct nfp_cpp *cpp) 13153b00109dSPeng Zhang { 1316aa6b4a80SHuaxing Zhu int err; 13173b00109dSPeng Zhang struct nfp_nsp *nsp; 13183b00109dSPeng Zhang 13193b00109dSPeng Zhang nsp = nfp_nsp_open(cpp); 13203b00109dSPeng Zhang if (nsp == NULL) 13213b00109dSPeng Zhang return; 13223b00109dSPeng Zhang 1323aa6b4a80SHuaxing Zhu err = nfp_nsp_device_soft_reset(nsp); 1324aa6b4a80SHuaxing Zhu if (err != 0) 1325aa6b4a80SHuaxing Zhu PMD_DRV_LOG(WARNING, "Failed to do soft reset when nfp fw unload."); 1326aa6b4a80SHuaxing Zhu 13273b00109dSPeng Zhang nfp_nsp_close(nsp); 13283b00109dSPeng Zhang } 13293b00109dSPeng Zhang 1330646ea79cSHeinrich Kuhn static int 1331a2bc299dSPeng Zhang nfp_fw_check_change(struct nfp_cpp *cpp, 1332a2bc299dSPeng Zhang char *fw_name, 1333a2bc299dSPeng Zhang bool *fw_changed) 1334a2bc299dSPeng Zhang { 1335a2bc299dSPeng Zhang int ret; 1336a2bc299dSPeng Zhang uint32_t new_version = 0; 1337a2bc299dSPeng Zhang uint32_t old_version = 0; 1338a2bc299dSPeng Zhang 1339a2bc299dSPeng Zhang ret = nfp_elf_get_fw_version(&new_version, fw_name); 1340a2bc299dSPeng Zhang if (ret != 0) 1341a2bc299dSPeng Zhang return ret; 1342a2bc299dSPeng Zhang 1343b3c21344SChaoyong He nfp_net_get_fw_version(cpp, &old_version); 1344a2bc299dSPeng Zhang 1345a2bc299dSPeng Zhang if (new_version != old_version) { 1346b6de4353SZerun Fu PMD_DRV_LOG(INFO, "FW version is changed, new %u, old %u.", 1347a2bc299dSPeng Zhang new_version, old_version); 1348a2bc299dSPeng Zhang *fw_changed = true; 1349a2bc299dSPeng Zhang } else { 1350b6de4353SZerun Fu PMD_DRV_LOG(INFO, "FW version is not changed and is %u.", new_version); 1351a2bc299dSPeng Zhang *fw_changed = false; 1352a2bc299dSPeng Zhang } 1353a2bc299dSPeng Zhang 1354a2bc299dSPeng Zhang return 0; 1355a2bc299dSPeng Zhang } 1356a2bc299dSPeng Zhang 1357c4ced2d5SHuaxing Zhu static void 1358c4ced2d5SHuaxing Zhu nfp_pcie_reg32_write_clear(struct rte_pci_device *pci_dev, 1359c4ced2d5SHuaxing Zhu int position) 1360c4ced2d5SHuaxing Zhu { 1361c4ced2d5SHuaxing Zhu int ret; 1362c4ced2d5SHuaxing Zhu uint32_t capability; 1363c4ced2d5SHuaxing Zhu 1364c4ced2d5SHuaxing Zhu ret = rte_pci_read_config(pci_dev, &capability, 4, position); 1365c4ced2d5SHuaxing Zhu if (ret < 0) 1366c4ced2d5SHuaxing Zhu capability = 0xffffffff; 1367c4ced2d5SHuaxing Zhu 1368c4ced2d5SHuaxing Zhu (void)rte_pci_write_config(pci_dev, &capability, 4, position); 1369c4ced2d5SHuaxing Zhu } 1370c4ced2d5SHuaxing Zhu 1371c4ced2d5SHuaxing Zhu static void 1372c4ced2d5SHuaxing Zhu nfp_pcie_aer_clear(struct rte_pci_device *pci_dev) 1373c4ced2d5SHuaxing Zhu { 1374c4ced2d5SHuaxing Zhu int pos; 1375c4ced2d5SHuaxing Zhu 1376c4ced2d5SHuaxing Zhu pos = rte_pci_find_ext_capability(pci_dev, RTE_PCI_EXT_CAP_ID_ERR); 1377c4ced2d5SHuaxing Zhu if (pos <= 0) 1378c4ced2d5SHuaxing Zhu return; 1379c4ced2d5SHuaxing Zhu 1380c4ced2d5SHuaxing Zhu nfp_pcie_reg32_write_clear(pci_dev, pos + RTE_PCI_ERR_UNCOR_STATUS); 1381c4ced2d5SHuaxing Zhu nfp_pcie_reg32_write_clear(pci_dev, pos + RTE_PCI_ERR_COR_STATUS); 1382c4ced2d5SHuaxing Zhu } 1383c4ced2d5SHuaxing Zhu 1384a2bc299dSPeng Zhang static int 1385ebfb540eSPeng Zhang nfp_fw_reload(struct nfp_nsp *nsp, 138608ea495dSChaoyong He char *fw_name, 1387c4ced2d5SHuaxing Zhu struct rte_pci_device *pci_dev, 138808ea495dSChaoyong He int reset) 13898ba461d1SPeng Zhang { 13908ba461d1SPeng Zhang int err; 139108ea495dSChaoyong He bool reset_flag; 13928ba461d1SPeng Zhang 139308ea495dSChaoyong He reset_flag = (reset == NFP_NSP_DRV_RESET_ALWAYS) || 139408ea495dSChaoyong He (reset == NFP_NSP_DRV_RESET_DISK); 13958ba461d1SPeng Zhang 139608ea495dSChaoyong He if (reset_flag) { 139708ea495dSChaoyong He err = nfp_nsp_device_soft_reset(nsp); 139808ea495dSChaoyong He if (err != 0) { 1399b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP firmware soft reset failed."); 14008ba461d1SPeng Zhang return err; 14018ba461d1SPeng Zhang } 140208ea495dSChaoyong He } 140308ea495dSChaoyong He 1404c4ced2d5SHuaxing Zhu /* 1405c4ced2d5SHuaxing Zhu * Accessing device memory during soft reset may result in some 1406c4ced2d5SHuaxing Zhu * errors being recorded in PCIE's AER register, which is normal. 1407c4ced2d5SHuaxing Zhu * Therefore, after the soft reset is completed, these errors 1408c4ced2d5SHuaxing Zhu * should be cleared. 1409c4ced2d5SHuaxing Zhu */ 1410c4ced2d5SHuaxing Zhu nfp_pcie_aer_clear(pci_dev); 1411c4ced2d5SHuaxing Zhu 141208ea495dSChaoyong He err = nfp_fw_upload(nsp, fw_name); 141308ea495dSChaoyong He if (err != 0) { 1414b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP firmware load failed."); 141508ea495dSChaoyong He return err; 141608ea495dSChaoyong He } 141708ea495dSChaoyong He 141808ea495dSChaoyong He return 0; 141908ea495dSChaoyong He } 14208ba461d1SPeng Zhang 1421a99ca614SPeng Zhang static bool 1422a99ca614SPeng Zhang nfp_fw_skip_load(const struct nfp_dev_info *dev_info, 1423b301fd73SPeng Zhang struct nfp_multi_pf *multi_pf, 1424b301fd73SPeng Zhang bool *reload_fw) 14258ba461d1SPeng Zhang { 142674397a7aSPeng Zhang uint8_t i; 142774397a7aSPeng Zhang uint64_t tmp_beat; 14288ba461d1SPeng Zhang uint32_t port_num; 14298b9a83eaSPeng Zhang uint8_t in_use = 0; 143074397a7aSPeng Zhang uint64_t beat[dev_info->pf_num_per_unit]; 143174397a7aSPeng Zhang uint32_t offset[dev_info->pf_num_per_unit]; 14328b9a83eaSPeng Zhang uint8_t abnormal = dev_info->pf_num_per_unit; 143374397a7aSPeng Zhang 1434ab47cecfSPeng Zhang sleep(1); 143574397a7aSPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 1436ab47cecfSPeng Zhang if (port_num == multi_pf->function_id) { 1437ab47cecfSPeng Zhang abnormal--; 1438ab47cecfSPeng Zhang continue; 1439ab47cecfSPeng Zhang } 1440ab47cecfSPeng Zhang 144174397a7aSPeng Zhang offset[port_num] = NFP_BEAT_OFFSET(port_num); 144274397a7aSPeng Zhang beat[port_num] = nn_readq(multi_pf->beat_addr + offset[port_num]); 14438b9a83eaSPeng Zhang if (beat[port_num] == 0) 14448b9a83eaSPeng Zhang abnormal--; 144574397a7aSPeng Zhang } 14468ba461d1SPeng Zhang 14478b9a83eaSPeng Zhang if (abnormal == 0) 14488b9a83eaSPeng Zhang return true; 14498b9a83eaSPeng Zhang 145074397a7aSPeng Zhang for (i = 0; i < 3; i++) { 145174397a7aSPeng Zhang sleep(1); 14528ba461d1SPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 14538ba461d1SPeng Zhang if (port_num == multi_pf->function_id) 14548ba461d1SPeng Zhang continue; 14558ba461d1SPeng Zhang 14568b9a83eaSPeng Zhang if (beat[port_num] == 0) 14578b9a83eaSPeng Zhang continue; 14588b9a83eaSPeng Zhang 145974397a7aSPeng Zhang tmp_beat = nn_readq(multi_pf->beat_addr + offset[port_num]); 14608b9a83eaSPeng Zhang if (tmp_beat != beat[port_num]) { 14618b9a83eaSPeng Zhang in_use++; 14628b9a83eaSPeng Zhang abnormal--; 14638b9a83eaSPeng Zhang beat[port_num] = 0; 1464b301fd73SPeng Zhang if (*reload_fw) { 1465b301fd73SPeng Zhang *reload_fw = false; 1466b6de4353SZerun Fu PMD_DRV_LOG(ERR, "The param %s does not work.", 1467b301fd73SPeng Zhang NFP_PF_FORCE_RELOAD_FW); 1468b301fd73SPeng Zhang } 14698b9a83eaSPeng Zhang } 14708b9a83eaSPeng Zhang } 14718b9a83eaSPeng Zhang 14728b9a83eaSPeng Zhang if (abnormal == 0) 1473a99ca614SPeng Zhang return true; 14748ba461d1SPeng Zhang } 14758b9a83eaSPeng Zhang 14768b9a83eaSPeng Zhang if (in_use != 0) { 14778b9a83eaSPeng Zhang PMD_DRV_LOG(WARNING, "Abnormal %u != 0, the nic has port which is exit abnormally.", 14788b9a83eaSPeng Zhang abnormal); 14798b9a83eaSPeng Zhang return true; 14808ba461d1SPeng Zhang } 14818ba461d1SPeng Zhang 1482a99ca614SPeng Zhang return false; 14838ba461d1SPeng Zhang } 148408ea495dSChaoyong He 1485a2bc299dSPeng Zhang static int 148608ea495dSChaoyong He nfp_fw_reload_from_flash(struct nfp_nsp *nsp) 148708ea495dSChaoyong He { 148808ea495dSChaoyong He int ret; 148908ea495dSChaoyong He 149008ea495dSChaoyong He ret = nfp_nsp_load_stored_fw(nsp); 149108ea495dSChaoyong He if (ret != 0) { 149208ea495dSChaoyong He PMD_DRV_LOG(ERR, "Load firmware from flash failed."); 149308ea495dSChaoyong He return -EACCES; 149408ea495dSChaoyong He } 149508ea495dSChaoyong He 149608ea495dSChaoyong He return 0; 149708ea495dSChaoyong He } 149808ea495dSChaoyong He 149908ea495dSChaoyong He static int 150008ea495dSChaoyong He nfp_fw_reload_for_single_pf_from_disk(struct nfp_nsp *nsp, 1501a2bc299dSPeng Zhang char *fw_name, 15026f708e52SChaoyong He struct nfp_pf_dev *pf_dev, 150308ea495dSChaoyong He int reset) 1504a2bc299dSPeng Zhang { 1505a2bc299dSPeng Zhang int ret; 1506a2bc299dSPeng Zhang bool fw_changed = true; 1507a2bc299dSPeng Zhang 15086f708e52SChaoyong He if (nfp_nsp_has_fw_loaded(nsp) && nfp_nsp_fw_loaded(nsp) && 15096f708e52SChaoyong He !pf_dev->devargs.force_reload_fw) { 15106f708e52SChaoyong He ret = nfp_fw_check_change(pf_dev->cpp, fw_name, &fw_changed); 1511a2bc299dSPeng Zhang if (ret != 0) 1512a2bc299dSPeng Zhang return ret; 1513a2bc299dSPeng Zhang } 1514a2bc299dSPeng Zhang 1515a2bc299dSPeng Zhang if (!fw_changed) 1516a2bc299dSPeng Zhang return 0; 1517a2bc299dSPeng Zhang 1518c4ced2d5SHuaxing Zhu ret = nfp_fw_reload(nsp, fw_name, pf_dev->pci_dev, reset); 1519a2bc299dSPeng Zhang if (ret != 0) 1520a2bc299dSPeng Zhang return ret; 1521a2bc299dSPeng Zhang 1522a2bc299dSPeng Zhang return 0; 1523a2bc299dSPeng Zhang } 15248ba461d1SPeng Zhang 15258ba461d1SPeng Zhang static int 152608ea495dSChaoyong He nfp_fw_reload_for_single_pf(struct nfp_nsp *nsp, 152708ea495dSChaoyong He char *fw_name, 15286f708e52SChaoyong He struct nfp_pf_dev *pf_dev, 152908ea495dSChaoyong He int reset, 153008ea495dSChaoyong He int policy) 153108ea495dSChaoyong He { 153208ea495dSChaoyong He int ret; 153308ea495dSChaoyong He 153408ea495dSChaoyong He if (policy == NFP_NSP_APP_FW_LOAD_FLASH && nfp_nsp_has_stored_fw_load(nsp)) { 153508ea495dSChaoyong He ret = nfp_fw_reload_from_flash(nsp); 153608ea495dSChaoyong He if (ret != 0) { 153708ea495dSChaoyong He PMD_DRV_LOG(ERR, "Load single PF firmware from flash failed."); 153808ea495dSChaoyong He return ret; 153908ea495dSChaoyong He } 154008ea495dSChaoyong He } else if (fw_name[0] != 0) { 15416f708e52SChaoyong He ret = nfp_fw_reload_for_single_pf_from_disk(nsp, fw_name, pf_dev, reset); 154208ea495dSChaoyong He if (ret != 0) { 154308ea495dSChaoyong He PMD_DRV_LOG(ERR, "Load single PF firmware from disk failed."); 154408ea495dSChaoyong He return ret; 154508ea495dSChaoyong He } 154608ea495dSChaoyong He } else { 154708ea495dSChaoyong He PMD_DRV_LOG(ERR, "Not load firmware, please update flash or recofigure card."); 154808ea495dSChaoyong He return -ENODATA; 154908ea495dSChaoyong He } 155008ea495dSChaoyong He 155108ea495dSChaoyong He return 0; 155208ea495dSChaoyong He } 155308ea495dSChaoyong He 155408ea495dSChaoyong He static int 155508ea495dSChaoyong He nfp_fw_reload_for_multi_pf_from_disk(struct nfp_nsp *nsp, 155608ea495dSChaoyong He char *fw_name, 155708ea495dSChaoyong He const struct nfp_dev_info *dev_info, 15586f708e52SChaoyong He struct nfp_pf_dev *pf_dev, 155908ea495dSChaoyong He int reset) 156008ea495dSChaoyong He { 156108ea495dSChaoyong He int err; 156208ea495dSChaoyong He bool fw_changed = true; 156308ea495dSChaoyong He bool skip_load_fw = false; 15646f708e52SChaoyong He bool reload_fw = pf_dev->devargs.force_reload_fw; 156508ea495dSChaoyong He 156608ea495dSChaoyong He if (nfp_nsp_has_fw_loaded(nsp) && nfp_nsp_fw_loaded(nsp) && !reload_fw) { 15676f708e52SChaoyong He err = nfp_fw_check_change(pf_dev->cpp, fw_name, &fw_changed); 156808ea495dSChaoyong He if (err != 0) 156908ea495dSChaoyong He return err; 157008ea495dSChaoyong He } 157108ea495dSChaoyong He 157208ea495dSChaoyong He if (!fw_changed || reload_fw) 15736f708e52SChaoyong He skip_load_fw = nfp_fw_skip_load(dev_info, &pf_dev->multi_pf, &reload_fw); 157408ea495dSChaoyong He 157508ea495dSChaoyong He if (skip_load_fw && !reload_fw) 157608ea495dSChaoyong He return 0; 157708ea495dSChaoyong He 1578c4ced2d5SHuaxing Zhu err = nfp_fw_reload(nsp, fw_name, pf_dev->pci_dev, reset); 157908ea495dSChaoyong He if (err != 0) 158008ea495dSChaoyong He return err; 158108ea495dSChaoyong He 158208ea495dSChaoyong He return 0; 158308ea495dSChaoyong He } 158408ea495dSChaoyong He 158508ea495dSChaoyong He static int 1586a2bc299dSPeng Zhang nfp_fw_reload_for_multi_pf(struct nfp_nsp *nsp, 1587ebfb540eSPeng Zhang char *fw_name, 15888ba461d1SPeng Zhang const struct nfp_dev_info *dev_info, 15896f708e52SChaoyong He struct nfp_pf_dev *pf_dev, 159008ea495dSChaoyong He int reset, 159108ea495dSChaoyong He int policy) 15928ba461d1SPeng Zhang { 15938ba461d1SPeng Zhang int err; 15946f708e52SChaoyong He struct nfp_multi_pf *multi_pf; 15958ba461d1SPeng Zhang 15966f708e52SChaoyong He multi_pf = &pf_dev->multi_pf; 15976f708e52SChaoyong He 15986f708e52SChaoyong He err = nfp_net_keepalive_init(pf_dev->cpp, multi_pf); 15998ba461d1SPeng Zhang if (err != 0) { 1600b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP init beat failed."); 16018ba461d1SPeng Zhang return err; 16028ba461d1SPeng Zhang } 16038ba461d1SPeng Zhang 16048ba461d1SPeng Zhang err = nfp_net_keepalive_start(multi_pf); 16058ba461d1SPeng Zhang if (err != 0) { 1606b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP write beat failed."); 1607a2bc299dSPeng Zhang goto keepalive_uninit; 16088ba461d1SPeng Zhang } 16098ba461d1SPeng Zhang 161008ea495dSChaoyong He if (policy == NFP_NSP_APP_FW_LOAD_FLASH && nfp_nsp_has_stored_fw_load(nsp)) { 161108ea495dSChaoyong He err = nfp_fw_reload_from_flash(nsp); 161208ea495dSChaoyong He if (err != 0) { 161308ea495dSChaoyong He PMD_DRV_LOG(ERR, "Load multi PF firmware from flash failed."); 1614a2bc299dSPeng Zhang goto keepalive_stop; 1615a2bc299dSPeng Zhang } 161608ea495dSChaoyong He } else if (fw_name[0] != 0) { 16176f708e52SChaoyong He err = nfp_fw_reload_for_multi_pf_from_disk(nsp, fw_name, dev_info, 16186f708e52SChaoyong He pf_dev, reset); 161908ea495dSChaoyong He if (err != 0) { 162008ea495dSChaoyong He PMD_DRV_LOG(ERR, "Load multi PF firmware from disk failed."); 1621a2bc299dSPeng Zhang goto keepalive_stop; 162208ea495dSChaoyong He } 162308ea495dSChaoyong He } else { 162408ea495dSChaoyong He PMD_DRV_LOG(ERR, "Not load firmware, please update flash or recofigure card."); 162508ea495dSChaoyong He err = -ENODATA; 162608ea495dSChaoyong He goto keepalive_stop; 162708ea495dSChaoyong He } 16288ba461d1SPeng Zhang 1629b67a7b40SPeng Zhang nfp_net_keepalive_clear_others(dev_info, multi_pf); 1630b67a7b40SPeng Zhang 1631a99ca614SPeng Zhang return 0; 1632a2bc299dSPeng Zhang 1633a2bc299dSPeng Zhang keepalive_stop: 1634a2bc299dSPeng Zhang nfp_net_keepalive_stop(multi_pf); 1635a2bc299dSPeng Zhang keepalive_uninit: 1636a2bc299dSPeng Zhang nfp_net_keepalive_uninit(multi_pf); 1637a2bc299dSPeng Zhang 1638a2bc299dSPeng Zhang return err; 1639a99ca614SPeng Zhang } 1640a99ca614SPeng Zhang 16418ba461d1SPeng Zhang static int 164208ea495dSChaoyong He nfp_strtol(const char *buf, 164308ea495dSChaoyong He int base, 164408ea495dSChaoyong He long *value) 164508ea495dSChaoyong He { 164608ea495dSChaoyong He long val; 164708ea495dSChaoyong He char *tmp; 164808ea495dSChaoyong He 164908ea495dSChaoyong He if (value == NULL) 165008ea495dSChaoyong He return -EINVAL; 165108ea495dSChaoyong He 165208ea495dSChaoyong He val = strtol(buf, &tmp, base); 165308ea495dSChaoyong He if (tmp == NULL || *tmp != 0) 165408ea495dSChaoyong He return -EINVAL; 165508ea495dSChaoyong He 165608ea495dSChaoyong He *value = val; 165708ea495dSChaoyong He 165808ea495dSChaoyong He return 0; 165908ea495dSChaoyong He } 166008ea495dSChaoyong He 166108ea495dSChaoyong He static int 166208ea495dSChaoyong He nfp_fw_policy_value_get(struct nfp_nsp *nsp, 166308ea495dSChaoyong He const char *key, 166408ea495dSChaoyong He const char *default_val, 166508ea495dSChaoyong He int max_val, 166608ea495dSChaoyong He int *value) 166708ea495dSChaoyong He { 166808ea495dSChaoyong He int ret; 166908ea495dSChaoyong He int64_t val; 167008ea495dSChaoyong He char buf[64]; 167108ea495dSChaoyong He 167208ea495dSChaoyong He snprintf(buf, sizeof(buf), "%s", key); 167308ea495dSChaoyong He ret = nfp_nsp_hwinfo_lookup_optional(nsp, buf, sizeof(buf), default_val); 167408ea495dSChaoyong He if (ret != 0) 167508ea495dSChaoyong He return ret; 167608ea495dSChaoyong He 167708ea495dSChaoyong He ret = nfp_strtol(buf, 0, &val); 167808ea495dSChaoyong He if (ret != 0 || val < 0 || val > max_val) { 1679b6de4353SZerun Fu PMD_DRV_LOG(WARNING, "Invalid value '%s' from '%s', ignoring.", 168008ea495dSChaoyong He buf, key); 168108ea495dSChaoyong He /* Fall back to the default value */ 168208ea495dSChaoyong He ret = nfp_strtol(default_val, 0, &val); 168308ea495dSChaoyong He if (ret != 0) 168408ea495dSChaoyong He return ret; 168508ea495dSChaoyong He } 168608ea495dSChaoyong He 168708ea495dSChaoyong He *value = val; 168808ea495dSChaoyong He 168908ea495dSChaoyong He return 0; 169008ea495dSChaoyong He } 169108ea495dSChaoyong He 169208ea495dSChaoyong He static int 16936f708e52SChaoyong He nfp_fw_setup(struct nfp_pf_dev *pf_dev, 16946f708e52SChaoyong He const struct nfp_dev_info *dev_info) 1695646ea79cSHeinrich Kuhn { 169649952141SChaoyong He int err; 169708ea495dSChaoyong He int reset; 169808ea495dSChaoyong He int policy; 1699ebfb540eSPeng Zhang char fw_name[125]; 1700646ea79cSHeinrich Kuhn struct nfp_nsp *nsp; 1701646ea79cSHeinrich Kuhn 17026f708e52SChaoyong He nsp = nfp_nsp_open(pf_dev->cpp); 1703a6189a67SJin Liu if (nsp == NULL) { 1704b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle."); 1705646ea79cSHeinrich Kuhn return -EIO; 1706646ea79cSHeinrich Kuhn } 1707646ea79cSHeinrich Kuhn 170808ea495dSChaoyong He err = nfp_fw_policy_value_get(nsp, "abi_drv_reset", 170908ea495dSChaoyong He NFP_NSP_DRV_RESET_DEFAULT, NFP_NSP_DRV_RESET_NEVER, 171008ea495dSChaoyong He &reset); 171108ea495dSChaoyong He if (err != 0) { 171208ea495dSChaoyong He PMD_DRV_LOG(ERR, "Get 'abi_drv_reset' from HWinfo failed."); 171308ea495dSChaoyong He goto close_nsp; 171408ea495dSChaoyong He } 1715646ea79cSHeinrich Kuhn 171608ea495dSChaoyong He err = nfp_fw_policy_value_get(nsp, "app_fw_from_flash", 171708ea495dSChaoyong He NFP_NSP_APP_FW_LOAD_DEFAULT, NFP_NSP_APP_FW_LOAD_PREF, 171808ea495dSChaoyong He &policy); 171908ea495dSChaoyong He if (err != 0) { 172008ea495dSChaoyong He PMD_DRV_LOG(ERR, "Get 'app_fw_from_flash' from HWinfo failed."); 172108ea495dSChaoyong He goto close_nsp; 172208ea495dSChaoyong He } 172308ea495dSChaoyong He 172408ea495dSChaoyong He fw_name[0] = 0; 172508ea495dSChaoyong He if (policy != NFP_NSP_APP_FW_LOAD_FLASH) { 17266f708e52SChaoyong He err = nfp_fw_get_name(pf_dev, fw_name, sizeof(fw_name)); 172708ea495dSChaoyong He if (err != 0) { 1728fb86136dSZerun Fu PMD_DRV_LOG(ERR, "Can not find suitable firmware."); 172908ea495dSChaoyong He goto close_nsp; 173008ea495dSChaoyong He } 173108ea495dSChaoyong He } 173208ea495dSChaoyong He 17336f708e52SChaoyong He if (pf_dev->multi_pf.enabled) 17346f708e52SChaoyong He err = nfp_fw_reload_for_multi_pf(nsp, fw_name, dev_info, 17356f708e52SChaoyong He pf_dev, reset, policy); 173608ea495dSChaoyong He else 17376f708e52SChaoyong He err = nfp_fw_reload_for_single_pf(nsp, fw_name, pf_dev, 17386f708e52SChaoyong He reset, policy); 173908ea495dSChaoyong He 174008ea495dSChaoyong He close_nsp: 1741646ea79cSHeinrich Kuhn nfp_nsp_close(nsp); 1742646ea79cSHeinrich Kuhn return err; 1743646ea79cSHeinrich Kuhn } 1744646ea79cSHeinrich Kuhn 17458ad2cc8fSPeng Zhang static inline bool 1746a508fa23SPeng Zhang nfp_check_multi_pf_from_fw(uint32_t total_vnics) 1747a508fa23SPeng Zhang { 1748a508fa23SPeng Zhang if (total_vnics == 1) 1749a508fa23SPeng Zhang return true; 1750a508fa23SPeng Zhang 1751a508fa23SPeng Zhang return false; 1752a508fa23SPeng Zhang } 1753a508fa23SPeng Zhang 1754a508fa23SPeng Zhang static inline bool 17558ad2cc8fSPeng Zhang nfp_check_multi_pf_from_nsp(struct rte_pci_device *pci_dev, 17568ad2cc8fSPeng Zhang struct nfp_cpp *cpp) 17578ad2cc8fSPeng Zhang { 17588ad2cc8fSPeng Zhang bool flag; 17598ad2cc8fSPeng Zhang struct nfp_nsp *nsp; 17608ad2cc8fSPeng Zhang 17618ad2cc8fSPeng Zhang nsp = nfp_nsp_open(cpp); 17628ad2cc8fSPeng Zhang if (nsp == NULL) { 1763b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle."); 17648ad2cc8fSPeng Zhang return false; 17658ad2cc8fSPeng Zhang } 17668ad2cc8fSPeng Zhang 17678ad2cc8fSPeng Zhang flag = (nfp_nsp_get_abi_ver_major(nsp) > 0) && 17688ad2cc8fSPeng Zhang (pci_dev->id.device_id == PCI_DEVICE_ID_NFP3800_PF_NIC); 17698ad2cc8fSPeng Zhang 17708ad2cc8fSPeng Zhang nfp_nsp_close(nsp); 17718ad2cc8fSPeng Zhang return flag; 17728ad2cc8fSPeng Zhang } 17738ad2cc8fSPeng Zhang 1774a6189a67SJin Liu static int 177595f978efSPeng Zhang nfp_enable_multi_pf(struct nfp_pf_dev *pf_dev) 177695f978efSPeng Zhang { 177795f978efSPeng Zhang int err = 0; 177895f978efSPeng Zhang uint64_t tx_base; 177995f978efSPeng Zhang uint8_t *ctrl_bar; 178095f978efSPeng Zhang struct nfp_hw *hw; 178195f978efSPeng Zhang uint32_t cap_extend; 178295f978efSPeng Zhang struct nfp_net_hw net_hw; 178395f978efSPeng Zhang struct nfp_cpp_area *area; 178495f978efSPeng Zhang char name[RTE_ETH_NAME_MAX_LEN]; 178595f978efSPeng Zhang 178695f978efSPeng Zhang memset(&net_hw, 0, sizeof(struct nfp_net_hw)); 178795f978efSPeng Zhang 178895f978efSPeng Zhang /* Map the symbol table */ 178919bd7cceSChaoyong He pf_dev->ctrl_bar_size = NFP_NET_CFG_BAR_SZ_MIN; 179095f978efSPeng Zhang snprintf(name, sizeof(name), "_pf%u_net_bar0", 179195f978efSPeng Zhang pf_dev->multi_pf.function_id); 179219bd7cceSChaoyong He ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, name, pf_dev->ctrl_bar_size, 179395f978efSPeng Zhang &area); 179495f978efSPeng Zhang if (ctrl_bar == NULL) { 1795b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to find data vNIC memory symbol."); 179695f978efSPeng Zhang return -ENODEV; 179795f978efSPeng Zhang } 179895f978efSPeng Zhang 179995f978efSPeng Zhang hw = &net_hw.super; 180095f978efSPeng Zhang hw->ctrl_bar = ctrl_bar; 180195f978efSPeng Zhang 1802000feb4cSChaoyong He /* Check the version from firmware */ 1803000feb4cSChaoyong He if (!nfp_net_version_check(hw, pf_dev)) { 1804000feb4cSChaoyong He PMD_INIT_LOG(ERR, "Not the valid version."); 1805000feb4cSChaoyong He err = -EINVAL; 1806000feb4cSChaoyong He goto end; 1807000feb4cSChaoyong He } 1808000feb4cSChaoyong He 180919bd7cceSChaoyong He /* Set the ctrl bar size */ 181019bd7cceSChaoyong He nfp_net_ctrl_bar_size_set(pf_dev); 181119bd7cceSChaoyong He 1812000feb4cSChaoyong He if (!pf_dev->multi_pf.enabled) 1813000feb4cSChaoyong He goto end; 1814000feb4cSChaoyong He 181595f978efSPeng Zhang cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1); 181695f978efSPeng Zhang if ((cap_extend & NFP_NET_CFG_CTRL_MULTI_PF) == 0) { 1817b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Loaded firmware does not support multiple PF."); 181895f978efSPeng Zhang err = -EINVAL; 181995f978efSPeng Zhang goto end; 182095f978efSPeng Zhang } 182195f978efSPeng Zhang 182295f978efSPeng Zhang tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 182395f978efSPeng Zhang net_hw.tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ; 182495f978efSPeng Zhang nfp_net_cfg_queue_setup(&net_hw); 182595f978efSPeng Zhang rte_spinlock_init(&hw->reconfig_lock); 18268c1d15f1SChaoyong He err = nfp_ext_reconfig(&net_hw.super, NFP_NET_CFG_CTRL_MULTI_PF, 18278c1d15f1SChaoyong He NFP_NET_CFG_UPDATE_GEN); 18288c1d15f1SChaoyong He if (err != 0) { 18298c1d15f1SChaoyong He PMD_INIT_LOG(ERR, "Configure multiple PF failed."); 18308c1d15f1SChaoyong He goto end; 18318c1d15f1SChaoyong He } 18328c1d15f1SChaoyong He 183395f978efSPeng Zhang end: 183495f978efSPeng Zhang nfp_cpp_area_release_free(area); 183595f978efSPeng Zhang return err; 183695f978efSPeng Zhang } 183795f978efSPeng Zhang 18386408420cSPeng Zhang static bool 18396408420cSPeng Zhang nfp_app_fw_nic_total_phyports_check(struct nfp_pf_dev *pf_dev) 18406408420cSPeng Zhang { 18416408420cSPeng Zhang uint8_t total_phyports; 18426408420cSPeng Zhang 1843eac7eda4SChaoyong He total_phyports = nfp_net_get_phyports_from_fw(pf_dev); 18446408420cSPeng Zhang 18456408420cSPeng Zhang if (pf_dev->multi_pf.enabled) { 18466408420cSPeng Zhang if (!nfp_check_multi_pf_from_fw(total_phyports)) { 1847b6de4353SZerun Fu PMD_INIT_LOG(ERR, "NSP report multipf, but FW report not multipf."); 18486408420cSPeng Zhang return false; 18496408420cSPeng Zhang } 18506408420cSPeng Zhang } else { 18516408420cSPeng Zhang /* 18526408420cSPeng Zhang * For single PF the number of vNICs exposed should be the same as the 18536408420cSPeng Zhang * number of physical ports. 18546408420cSPeng Zhang */ 18556408420cSPeng Zhang if (total_phyports != pf_dev->nfp_eth_table->count) { 1856b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Total physical ports do not match number of vNICs."); 18576408420cSPeng Zhang return false; 18586408420cSPeng Zhang } 18596408420cSPeng Zhang } 18606408420cSPeng Zhang 18616408420cSPeng Zhang return true; 18626408420cSPeng Zhang } 18636408420cSPeng Zhang 1864eac7eda4SChaoyong He static void 1865eac7eda4SChaoyong He nfp_port_name_generate(char *port_name, 1866eac7eda4SChaoyong He size_t length, 1867eac7eda4SChaoyong He int port_id, 1868eac7eda4SChaoyong He struct nfp_pf_dev *pf_dev) 1869eac7eda4SChaoyong He { 1870eac7eda4SChaoyong He const char *name = pf_dev->pci_dev->device.name; 1871eac7eda4SChaoyong He 1872eac7eda4SChaoyong He if (pf_dev->multi_pf.enabled) 1873eac7eda4SChaoyong He snprintf(port_name, length, "%s", name); 1874eac7eda4SChaoyong He else 1875eac7eda4SChaoyong He snprintf(port_name, length, "%s_port%u", name, port_id); 1876eac7eda4SChaoyong He } 1877eac7eda4SChaoyong He 187895f978efSPeng Zhang static int 1879d81e2b51SChaoyong He nfp_init_app_fw_nic(struct nfp_net_hw_priv *hw_priv) 1880646ea79cSHeinrich Kuhn { 18818ceb85c3SChaoyong He uint8_t i; 18823b00109dSPeng Zhang uint8_t id; 1883e7978635SChaoyong He int ret = 0; 1884968ec1c3SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 1885a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table; 18863b00109dSPeng Zhang char bar_name[RTE_ETH_NAME_MAX_LEN]; 1887646ea79cSHeinrich Kuhn char port_name[RTE_ETH_NAME_MAX_LEN]; 1888ff9f5a56SChaoyong He struct nfp_pf_dev *pf_dev = hw_priv->pf_dev; 18896484c847SChaoyong He struct nfp_net_init hw_init = { 18906484c847SChaoyong He .hw_priv = hw_priv, 18916484c847SChaoyong He }; 1892646ea79cSHeinrich Kuhn 1893968ec1c3SChaoyong He nfp_eth_table = pf_dev->nfp_eth_table; 1894b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Total physical ports: %d.", nfp_eth_table->count); 18953b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, 0); 1896968ec1c3SChaoyong He 1897968ec1c3SChaoyong He /* Allocate memory for the CoreNIC app */ 1898968ec1c3SChaoyong He app_fw_nic = rte_zmalloc("nfp_app_fw_nic", sizeof(*app_fw_nic), 0); 1899968ec1c3SChaoyong He if (app_fw_nic == NULL) 1900968ec1c3SChaoyong He return -ENOMEM; 1901968ec1c3SChaoyong He 1902968ec1c3SChaoyong He /* Point the app_fw_priv pointer in the PF to the coreNIC app */ 1903968ec1c3SChaoyong He pf_dev->app_fw_priv = app_fw_nic; 1904968ec1c3SChaoyong He 19056408420cSPeng Zhang /* Check the number of vNIC's created for the PF */ 19066408420cSPeng Zhang if (!nfp_app_fw_nic_total_phyports_check(pf_dev)) { 1907968ec1c3SChaoyong He ret = -ENODEV; 1908968ec1c3SChaoyong He goto app_cleanup; 1909968ec1c3SChaoyong He } 1910968ec1c3SChaoyong He 1911968ec1c3SChaoyong He /* Populate coreNIC app properties */ 19126408420cSPeng Zhang if (pf_dev->total_phyports > 1) 1913968ec1c3SChaoyong He app_fw_nic->multiport = true; 1914968ec1c3SChaoyong He 1915968ec1c3SChaoyong He /* Map the symbol table */ 19163b00109dSPeng Zhang snprintf(bar_name, sizeof(bar_name), "_pf%u_net_bar0", id); 19173b00109dSPeng Zhang pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, bar_name, 191819bd7cceSChaoyong He pf_dev->total_phyports * pf_dev->ctrl_bar_size, 1919d5e9fc86SChaoyong He &pf_dev->ctrl_area); 1920968ec1c3SChaoyong He if (pf_dev->ctrl_bar == NULL) { 1921b6de4353SZerun Fu PMD_INIT_LOG(ERR, "The nfp_rtsym_map fails for %s.", bar_name); 1922968ec1c3SChaoyong He ret = -EIO; 1923968ec1c3SChaoyong He goto app_cleanup; 1924968ec1c3SChaoyong He } 1925968ec1c3SChaoyong He 1926b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "Ctrl bar: %p.", pf_dev->ctrl_bar); 1927968ec1c3SChaoyong He 1928968ec1c3SChaoyong He /* Loop through all physical ports on PF */ 19296408420cSPeng Zhang for (i = 0; i < pf_dev->total_phyports; i++) { 1930eac7eda4SChaoyong He nfp_port_name_generate(port_name, sizeof(port_name), i, pf_dev); 1931646ea79cSHeinrich Kuhn 1932c92c83d4SPeng Zhang id = nfp_function_id_get(pf_dev, i); 19336484c847SChaoyong He hw_init.idx = id; 19346484c847SChaoyong He hw_init.nfp_idx = nfp_eth_table->ports[id].index; 19356484c847SChaoyong He ret = rte_eth_dev_create(&pf_dev->pci_dev->device, port_name, 19366484c847SChaoyong He sizeof(struct nfp_net_hw), NULL, NULL, 19376484c847SChaoyong He nfp_net_init, &hw_init); 19386484c847SChaoyong He if (ret != 0) 1939646ea79cSHeinrich Kuhn goto port_cleanup; 1940646ea79cSHeinrich Kuhn 1941646ea79cSHeinrich Kuhn } /* End loop, all ports on this PF */ 1942968ec1c3SChaoyong He 1943968ec1c3SChaoyong He return 0; 1944646ea79cSHeinrich Kuhn 1945646ea79cSHeinrich Kuhn port_cleanup: 1946eac7eda4SChaoyong He for (uint32_t j = 0; j < i; j++) { 1947a9fa1da7SChaoyong He struct rte_eth_dev *eth_dev; 19483b00109dSPeng Zhang 1949eac7eda4SChaoyong He nfp_port_name_generate(port_name, sizeof(port_name), j, pf_dev); 1950a9fa1da7SChaoyong He eth_dev = rte_eth_dev_get_by_name(port_name); 19516484c847SChaoyong He if (eth_dev != NULL) 19526484c847SChaoyong He rte_eth_dev_destroy(eth_dev, nfp_net_uninit); 1953646ea79cSHeinrich Kuhn } 19548b8f116bSChaoyong He nfp_cpp_area_release_free(pf_dev->ctrl_area); 1955968ec1c3SChaoyong He app_cleanup: 1956968ec1c3SChaoyong He rte_free(app_fw_nic); 1957a6189a67SJin Liu 1958646ea79cSHeinrich Kuhn return ret; 1959646ea79cSHeinrich Kuhn } 1960646ea79cSHeinrich Kuhn 1961a6189a67SJin Liu static int 1962c7a6970fSZerun Fu nfp_net_hwinfo_set(uint8_t function_id, 1963c7a6970fSZerun Fu struct nfp_rtsym_table *sym_tbl, 1964103134d2SZerun Fu struct nfp_cpp *cpp, 1965103134d2SZerun Fu enum nfp_app_fw_id app_fw_id) 1966c7a6970fSZerun Fu { 1967c7a6970fSZerun Fu int ret = 0; 1968c7a6970fSZerun Fu uint64_t app_cap; 1969c7a6970fSZerun Fu struct nfp_nsp *nsp; 1970103134d2SZerun Fu uint8_t sp_indiff = 1; 1971c7a6970fSZerun Fu char hw_info[RTE_ETH_NAME_MAX_LEN]; 1972c7a6970fSZerun Fu char app_cap_name[RTE_ETH_NAME_MAX_LEN]; 1973c7a6970fSZerun Fu 1974103134d2SZerun Fu if (app_fw_id != NFP_APP_FW_FLOWER_NIC) { 1975c7a6970fSZerun Fu /* Read the app capabilities of the firmware loaded */ 1976c7a6970fSZerun Fu snprintf(app_cap_name, sizeof(app_cap_name), "_pf%u_net_app_cap", function_id); 1977c7a6970fSZerun Fu app_cap = nfp_rtsym_read_le(sym_tbl, app_cap_name, &ret); 1978c7a6970fSZerun Fu if (ret != 0) { 1979103134d2SZerun Fu PMD_INIT_LOG(ERR, "Could not read app_fw_cap from firmware."); 1980c7a6970fSZerun Fu return ret; 1981c7a6970fSZerun Fu } 1982c7a6970fSZerun Fu 1983c7a6970fSZerun Fu /* Calculate the value of sp_indiff and write to hw_info */ 1984c7a6970fSZerun Fu sp_indiff = app_cap & NFP_NET_APP_CAP_SP_INDIFF; 1985103134d2SZerun Fu } 1986103134d2SZerun Fu 1987c7a6970fSZerun Fu snprintf(hw_info, sizeof(hw_info), "sp_indiff=%u", sp_indiff); 1988c7a6970fSZerun Fu 1989c7a6970fSZerun Fu nsp = nfp_nsp_open(cpp); 1990c7a6970fSZerun Fu if (nsp == NULL) { 1991103134d2SZerun Fu PMD_INIT_LOG(ERR, "Could not get NSP."); 1992c7a6970fSZerun Fu return -EIO; 1993c7a6970fSZerun Fu } 1994c7a6970fSZerun Fu 1995c7a6970fSZerun Fu ret = nfp_nsp_hwinfo_set(nsp, hw_info, sizeof(hw_info)); 1996c7a6970fSZerun Fu nfp_nsp_close(nsp); 1997c7a6970fSZerun Fu if (ret != 0) { 1998c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Failed to set parameter to hwinfo."); 1999c7a6970fSZerun Fu return ret; 2000c7a6970fSZerun Fu } 2001c7a6970fSZerun Fu 2002c7a6970fSZerun Fu return 0; 2003c7a6970fSZerun Fu } 2004c7a6970fSZerun Fu 20053110ab73SZerun Fu const uint32_t nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = { 20063110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10M] = RTE_ETH_LINK_SPEED_10M, 20073110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10M_HD] = RTE_ETH_LINK_SPEED_10M_HD, 20083110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_100M] = RTE_ETH_LINK_SPEED_100M, 20093110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_100M_HD] = RTE_ETH_LINK_SPEED_100M_HD, 20103110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_1G] = RTE_ETH_LINK_SPEED_1G, 20113110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_2P5G] = RTE_ETH_LINK_SPEED_2_5G, 20123110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_5G] = RTE_ETH_LINK_SPEED_5G, 20133110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10G] = RTE_ETH_LINK_SPEED_10G, 20143110ab73SZerun Fu [NFP_MEDIA_1000BASE_CX] = RTE_ETH_LINK_SPEED_1G, 20153110ab73SZerun Fu [NFP_MEDIA_1000BASE_KX] = RTE_ETH_LINK_SPEED_1G, 20163110ab73SZerun Fu [NFP_MEDIA_10GBASE_KX4] = RTE_ETH_LINK_SPEED_10G, 20173110ab73SZerun Fu [NFP_MEDIA_10GBASE_KR] = RTE_ETH_LINK_SPEED_10G, 20183110ab73SZerun Fu [NFP_MEDIA_10GBASE_CX4] = RTE_ETH_LINK_SPEED_10G, 20193110ab73SZerun Fu [NFP_MEDIA_10GBASE_CR] = RTE_ETH_LINK_SPEED_10G, 20203110ab73SZerun Fu [NFP_MEDIA_10GBASE_SR] = RTE_ETH_LINK_SPEED_10G, 20213110ab73SZerun Fu [NFP_MEDIA_10GBASE_ER] = RTE_ETH_LINK_SPEED_10G, 20223110ab73SZerun Fu [NFP_MEDIA_25GBASE_KR] = RTE_ETH_LINK_SPEED_25G, 20233110ab73SZerun Fu [NFP_MEDIA_25GBASE_KR_S] = RTE_ETH_LINK_SPEED_25G, 20243110ab73SZerun Fu [NFP_MEDIA_25GBASE_CR] = RTE_ETH_LINK_SPEED_25G, 20253110ab73SZerun Fu [NFP_MEDIA_25GBASE_CR_S] = RTE_ETH_LINK_SPEED_25G, 20263110ab73SZerun Fu [NFP_MEDIA_25GBASE_SR] = RTE_ETH_LINK_SPEED_25G, 20273110ab73SZerun Fu [NFP_MEDIA_40GBASE_CR4] = RTE_ETH_LINK_SPEED_40G, 20283110ab73SZerun Fu [NFP_MEDIA_40GBASE_KR4] = RTE_ETH_LINK_SPEED_40G, 20293110ab73SZerun Fu [NFP_MEDIA_40GBASE_SR4] = RTE_ETH_LINK_SPEED_40G, 20303110ab73SZerun Fu [NFP_MEDIA_40GBASE_LR4] = RTE_ETH_LINK_SPEED_40G, 20313110ab73SZerun Fu [NFP_MEDIA_50GBASE_KR] = RTE_ETH_LINK_SPEED_50G, 20323110ab73SZerun Fu [NFP_MEDIA_50GBASE_SR] = RTE_ETH_LINK_SPEED_50G, 20333110ab73SZerun Fu [NFP_MEDIA_50GBASE_CR] = RTE_ETH_LINK_SPEED_50G, 20343110ab73SZerun Fu [NFP_MEDIA_50GBASE_LR] = RTE_ETH_LINK_SPEED_50G, 20353110ab73SZerun Fu [NFP_MEDIA_50GBASE_ER] = RTE_ETH_LINK_SPEED_50G, 20363110ab73SZerun Fu [NFP_MEDIA_50GBASE_FR] = RTE_ETH_LINK_SPEED_50G, 20373110ab73SZerun Fu [NFP_MEDIA_100GBASE_KR4] = RTE_ETH_LINK_SPEED_100G, 20383110ab73SZerun Fu [NFP_MEDIA_100GBASE_SR4] = RTE_ETH_LINK_SPEED_100G, 20393110ab73SZerun Fu [NFP_MEDIA_100GBASE_CR4] = RTE_ETH_LINK_SPEED_100G, 20403110ab73SZerun Fu [NFP_MEDIA_100GBASE_KP4] = RTE_ETH_LINK_SPEED_100G, 20413110ab73SZerun Fu [NFP_MEDIA_100GBASE_CR10] = RTE_ETH_LINK_SPEED_100G, 20423110ab73SZerun Fu [NFP_MEDIA_10GBASE_LR] = RTE_ETH_LINK_SPEED_10G, 20433110ab73SZerun Fu [NFP_MEDIA_25GBASE_LR] = RTE_ETH_LINK_SPEED_25G, 20443110ab73SZerun Fu [NFP_MEDIA_25GBASE_ER] = RTE_ETH_LINK_SPEED_25G 20453110ab73SZerun Fu }; 20463110ab73SZerun Fu 20473110ab73SZerun Fu static int 20483110ab73SZerun Fu nfp_net_speed_capa_get_real(struct nfp_eth_media_buf *media_buf, 20493110ab73SZerun Fu struct nfp_pf_dev *pf_dev) 20503110ab73SZerun Fu { 20513110ab73SZerun Fu uint32_t i; 20523110ab73SZerun Fu uint32_t j; 20533110ab73SZerun Fu uint32_t offset; 20543110ab73SZerun Fu uint32_t speed_capa = 0; 20553110ab73SZerun Fu uint64_t supported_modes; 20563110ab73SZerun Fu 20573110ab73SZerun Fu for (i = 0; i < RTE_DIM(media_buf->supported_modes); i++) { 20583110ab73SZerun Fu supported_modes = media_buf->supported_modes[i]; 20593110ab73SZerun Fu offset = i * UINT64_BIT; 20603110ab73SZerun Fu for (j = 0; j < UINT64_BIT; j++) { 20613110ab73SZerun Fu if (supported_modes == 0) 20623110ab73SZerun Fu break; 20633110ab73SZerun Fu 20643110ab73SZerun Fu if ((supported_modes & 1) != 0) { 20653110ab73SZerun Fu if ((j + offset) >= NFP_MEDIA_LINK_MODES_NUMBER) { 20663110ab73SZerun Fu PMD_DRV_LOG(ERR, "Invalid offset of media table."); 20673110ab73SZerun Fu return -EINVAL; 20683110ab73SZerun Fu } 20693110ab73SZerun Fu 20703110ab73SZerun Fu speed_capa |= nfp_eth_media_table[j + offset]; 20713110ab73SZerun Fu } 20723110ab73SZerun Fu 20733110ab73SZerun Fu supported_modes = supported_modes >> 1; 20743110ab73SZerun Fu } 20753110ab73SZerun Fu } 20763110ab73SZerun Fu 20773110ab73SZerun Fu pf_dev->speed_capa = speed_capa; 20783110ab73SZerun Fu 20793110ab73SZerun Fu return pf_dev->speed_capa == 0 ? -EINVAL : 0; 20803110ab73SZerun Fu } 20813110ab73SZerun Fu 20823110ab73SZerun Fu static int 20835b46a539SPeng Zhang nfp_net_speed_cap_get_one(struct nfp_pf_dev *pf_dev, 20843110ab73SZerun Fu uint32_t port_id) 20853110ab73SZerun Fu { 20863110ab73SZerun Fu int ret; 20873110ab73SZerun Fu struct nfp_nsp *nsp; 20883110ab73SZerun Fu struct nfp_eth_media_buf media_buf; 20893110ab73SZerun Fu 20903110ab73SZerun Fu media_buf.eth_index = pf_dev->nfp_eth_table->ports[port_id].eth_index; 20913110ab73SZerun Fu pf_dev->speed_capa = 0; 20923110ab73SZerun Fu 20933110ab73SZerun Fu nsp = nfp_nsp_open(pf_dev->cpp); 20943110ab73SZerun Fu if (nsp == NULL) { 2095fb86136dSZerun Fu PMD_DRV_LOG(ERR, "Could not get NSP."); 20963110ab73SZerun Fu return -EIO; 20973110ab73SZerun Fu } 20983110ab73SZerun Fu 20993110ab73SZerun Fu ret = nfp_nsp_read_media(nsp, &media_buf, sizeof(media_buf)); 21003110ab73SZerun Fu nfp_nsp_close(nsp); 21013110ab73SZerun Fu if (ret != 0) { 21023110ab73SZerun Fu PMD_DRV_LOG(ERR, "Failed to read media."); 21033110ab73SZerun Fu return ret; 21043110ab73SZerun Fu } 21053110ab73SZerun Fu 21063110ab73SZerun Fu ret = nfp_net_speed_capa_get_real(&media_buf, pf_dev); 21073110ab73SZerun Fu if (ret < 0) { 21083110ab73SZerun Fu PMD_DRV_LOG(ERR, "Speed capability is invalid."); 21093110ab73SZerun Fu return ret; 21103110ab73SZerun Fu } 21113110ab73SZerun Fu 21123110ab73SZerun Fu return 0; 21133110ab73SZerun Fu } 21143110ab73SZerun Fu 21155b46a539SPeng Zhang static int 21165b46a539SPeng Zhang nfp_net_speed_cap_get(struct nfp_pf_dev *pf_dev) 21175b46a539SPeng Zhang { 21185b46a539SPeng Zhang int ret; 21195b46a539SPeng Zhang uint32_t i; 21205b46a539SPeng Zhang uint32_t id; 21215b46a539SPeng Zhang uint32_t count; 21225b46a539SPeng Zhang 21236f708e52SChaoyong He count = pf_dev->total_phyports; 21245b46a539SPeng Zhang for (i = 0; i < count; i++) { 21255b46a539SPeng Zhang id = nfp_function_id_get(pf_dev, i); 21265b46a539SPeng Zhang ret = nfp_net_speed_cap_get_one(pf_dev, id); 21275b46a539SPeng Zhang if (ret != 0) { 21285b46a539SPeng Zhang PMD_INIT_LOG(ERR, "Failed to get port %d speed capability.", id); 21295b46a539SPeng Zhang return ret; 21305b46a539SPeng Zhang } 21315b46a539SPeng Zhang } 21325b46a539SPeng Zhang 21335b46a539SPeng Zhang return 0; 21345b46a539SPeng Zhang } 21355b46a539SPeng Zhang 2136bd4969abSPeng Zhang /* Force the physical port down to clear the possible DMA error */ 2137bd4969abSPeng Zhang static int 21386f708e52SChaoyong He nfp_net_force_port_down(struct nfp_pf_dev *pf_dev) 2139bd4969abSPeng Zhang { 2140bd4969abSPeng Zhang int ret; 2141bd4969abSPeng Zhang uint32_t i; 2142bd4969abSPeng Zhang uint32_t id; 2143bd4969abSPeng Zhang uint32_t index; 2144bd4969abSPeng Zhang uint32_t count; 2145bd4969abSPeng Zhang 21466f708e52SChaoyong He count = pf_dev->total_phyports; 2147bd4969abSPeng Zhang for (i = 0; i < count; i++) { 2148bd4969abSPeng Zhang id = nfp_function_id_get(pf_dev, i); 21496f708e52SChaoyong He index = pf_dev->nfp_eth_table->ports[id].index; 21506f708e52SChaoyong He ret = nfp_eth_set_configured(pf_dev->cpp, index, 0); 2151bd4969abSPeng Zhang if (ret < 0) 2152bd4969abSPeng Zhang return ret; 2153bd4969abSPeng Zhang } 2154bd4969abSPeng Zhang 2155bd4969abSPeng Zhang return 0; 2156bd4969abSPeng Zhang } 2157bd4969abSPeng Zhang 2158c7a6970fSZerun Fu static int 2159e51160adSPeng Zhang nfp_fw_app_primary_init(struct nfp_net_hw_priv *hw_priv) 2160e51160adSPeng Zhang { 2161e51160adSPeng Zhang int ret; 2162e51160adSPeng Zhang struct nfp_pf_dev *pf_dev = hw_priv->pf_dev; 2163e51160adSPeng Zhang 2164e51160adSPeng Zhang switch (pf_dev->app_fw_id) { 2165e51160adSPeng Zhang case NFP_APP_FW_CORE_NIC: 2166b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Initializing coreNIC."); 2167e51160adSPeng Zhang ret = nfp_init_app_fw_nic(hw_priv); 2168e51160adSPeng Zhang if (ret != 0) { 2169e51160adSPeng Zhang PMD_INIT_LOG(ERR, "Could not initialize coreNIC!"); 2170e51160adSPeng Zhang return ret; 2171e51160adSPeng Zhang } 2172e51160adSPeng Zhang break; 2173e51160adSPeng Zhang case NFP_APP_FW_FLOWER_NIC: 2174b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Initializing Flower."); 2175e51160adSPeng Zhang ret = nfp_init_app_fw_flower(hw_priv); 2176e51160adSPeng Zhang if (ret != 0) { 2177e51160adSPeng Zhang PMD_INIT_LOG(ERR, "Could not initialize Flower!"); 2178e51160adSPeng Zhang return ret; 2179e51160adSPeng Zhang } 2180e51160adSPeng Zhang break; 2181e51160adSPeng Zhang default: 2182b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Unsupported Firmware loaded."); 2183e51160adSPeng Zhang ret = -EINVAL; 2184e51160adSPeng Zhang return ret; 2185e51160adSPeng Zhang } 2186e51160adSPeng Zhang 2187e51160adSPeng Zhang return 0; 2188e51160adSPeng Zhang } 2189e51160adSPeng Zhang 2190e51160adSPeng Zhang static int 219120086cb8SPeng Zhang nfp_pf_get_max_vf(struct nfp_pf_dev *pf_dev) 219220086cb8SPeng Zhang { 219320086cb8SPeng Zhang int ret; 219420086cb8SPeng Zhang uint32_t max_vfs; 219520086cb8SPeng Zhang 219620086cb8SPeng Zhang max_vfs = nfp_rtsym_read_le(pf_dev->sym_tbl, "nfd_vf_cfg_max_vfs", &ret); 219720086cb8SPeng Zhang if (ret != 0) 219820086cb8SPeng Zhang return ret; 219920086cb8SPeng Zhang 220020086cb8SPeng Zhang pf_dev->max_vfs = max_vfs; 220120086cb8SPeng Zhang 220220086cb8SPeng Zhang return 0; 220320086cb8SPeng Zhang } 220420086cb8SPeng Zhang 220520086cb8SPeng Zhang static int 220620086cb8SPeng Zhang nfp_pf_get_sriov_vf(struct nfp_pf_dev *pf_dev, 220720086cb8SPeng Zhang const struct nfp_dev_info *dev_info) 220820086cb8SPeng Zhang { 220920086cb8SPeng Zhang int ret; 221020086cb8SPeng Zhang off_t pos; 221120086cb8SPeng Zhang uint16_t offset; 221220086cb8SPeng Zhang uint16_t sriov_vf; 221320086cb8SPeng Zhang 221420086cb8SPeng Zhang /* For 3800 single-PF and 4000 card */ 221520086cb8SPeng Zhang if (!pf_dev->multi_pf.enabled) { 221620086cb8SPeng Zhang pf_dev->sriov_vf = pf_dev->max_vfs; 221720086cb8SPeng Zhang return 0; 221820086cb8SPeng Zhang } 221920086cb8SPeng Zhang 222020086cb8SPeng Zhang pos = rte_pci_find_ext_capability(pf_dev->pci_dev, RTE_PCI_EXT_CAP_ID_SRIOV); 222120086cb8SPeng Zhang if (pos == 0) { 2222b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not get the pci sriov cap."); 222320086cb8SPeng Zhang return -EIO; 222420086cb8SPeng Zhang } 222520086cb8SPeng Zhang 222620086cb8SPeng Zhang /* 222720086cb8SPeng Zhang * Management firmware ensures that sriov capability registers 222820086cb8SPeng Zhang * are initialized correctly. 222920086cb8SPeng Zhang */ 223020086cb8SPeng Zhang ret = rte_pci_read_config(pf_dev->pci_dev, &sriov_vf, sizeof(sriov_vf), 223120086cb8SPeng Zhang pos + RTE_PCI_SRIOV_TOTAL_VF); 223220086cb8SPeng Zhang if (ret < 0) { 2233b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not read the sriov toatl VF."); 223420086cb8SPeng Zhang return -EIO; 223520086cb8SPeng Zhang } 223620086cb8SPeng Zhang 223720086cb8SPeng Zhang /* Offset of first VF is relative to its PF. */ 223820086cb8SPeng Zhang ret = rte_pci_read_config(pf_dev->pci_dev, &offset, sizeof(offset), 223920086cb8SPeng Zhang pos + RTE_PCI_SRIOV_VF_OFFSET); 224020086cb8SPeng Zhang if (ret < 0) { 2241b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not get the VF offset."); 224220086cb8SPeng Zhang return -EIO; 224320086cb8SPeng Zhang } 224420086cb8SPeng Zhang 224520086cb8SPeng Zhang offset += pf_dev->multi_pf.function_id; 224620086cb8SPeng Zhang if (offset < dev_info->pf_num_per_unit) 224720086cb8SPeng Zhang return -ERANGE; 224820086cb8SPeng Zhang 224920086cb8SPeng Zhang offset -= dev_info->pf_num_per_unit; 225020086cb8SPeng Zhang if (offset >= pf_dev->max_vfs || offset + sriov_vf > pf_dev->max_vfs) { 2251b6de4353SZerun Fu PMD_INIT_LOG(ERR, "The pci allocate VF is more than the MAX VF."); 225220086cb8SPeng Zhang return -ERANGE; 225320086cb8SPeng Zhang } 225420086cb8SPeng Zhang 2255d4e160acSPeng Zhang pf_dev->vf_base_id = offset; 225620086cb8SPeng Zhang pf_dev->sriov_vf = sriov_vf; 225720086cb8SPeng Zhang 225820086cb8SPeng Zhang return 0; 225920086cb8SPeng Zhang } 226020086cb8SPeng Zhang 226120086cb8SPeng Zhang static int 226220086cb8SPeng Zhang nfp_net_get_vf_info(struct nfp_pf_dev *pf_dev, 226320086cb8SPeng Zhang const struct nfp_dev_info *dev_info) 226420086cb8SPeng Zhang { 226520086cb8SPeng Zhang int ret; 226620086cb8SPeng Zhang 226720086cb8SPeng Zhang ret = nfp_pf_get_max_vf(pf_dev); 226820086cb8SPeng Zhang if (ret != 0) { 226920086cb8SPeng Zhang if (ret != -ENOENT) { 2270b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Read max VFs failed."); 227120086cb8SPeng Zhang return ret; 227220086cb8SPeng Zhang } 227320086cb8SPeng Zhang 2274b6de4353SZerun Fu PMD_INIT_LOG(WARNING, "The firmware can not support read max VFs."); 227520086cb8SPeng Zhang return 0; 227620086cb8SPeng Zhang } 227720086cb8SPeng Zhang 227820086cb8SPeng Zhang if (pf_dev->max_vfs == 0) 227920086cb8SPeng Zhang return 0; 228020086cb8SPeng Zhang 228120086cb8SPeng Zhang ret = nfp_pf_get_sriov_vf(pf_dev, dev_info); 228220086cb8SPeng Zhang if (ret < 0) 228320086cb8SPeng Zhang return ret; 228420086cb8SPeng Zhang 2285bb24eb38SPeng Zhang pf_dev->queue_per_vf = NFP_QUEUE_PER_VF; 2286bb24eb38SPeng Zhang 228720086cb8SPeng Zhang return 0; 228820086cb8SPeng Zhang } 228920086cb8SPeng Zhang 229020086cb8SPeng Zhang static int 229119542093SPeng Zhang nfp_net_vf_config_init(struct nfp_pf_dev *pf_dev) 229219542093SPeng Zhang { 229319542093SPeng Zhang int ret = 0; 229419542093SPeng Zhang uint32_t min_size; 229519542093SPeng Zhang char vf_bar_name[RTE_ETH_NAME_MAX_LEN]; 229619542093SPeng Zhang char vf_cfg_name[RTE_ETH_NAME_MAX_LEN]; 229719542093SPeng Zhang 229819542093SPeng Zhang if (pf_dev->sriov_vf == 0) 229919542093SPeng Zhang return 0; 230019542093SPeng Zhang 230119bd7cceSChaoyong He min_size = pf_dev->ctrl_bar_size * pf_dev->sriov_vf; 230219542093SPeng Zhang snprintf(vf_bar_name, sizeof(vf_bar_name), "_pf%d_net_vf_bar", 230319542093SPeng Zhang pf_dev->multi_pf.function_id); 230419542093SPeng Zhang pf_dev->vf_bar = nfp_rtsym_map_offset(pf_dev->sym_tbl, vf_bar_name, 230519bd7cceSChaoyong He pf_dev->ctrl_bar_size * pf_dev->vf_base_id, 230619542093SPeng Zhang min_size, &pf_dev->vf_area); 230719542093SPeng Zhang if (pf_dev->vf_bar == NULL) { 230819542093SPeng Zhang PMD_INIT_LOG(ERR, "Failed to get vf cfg."); 230919542093SPeng Zhang return -EIO; 231019542093SPeng Zhang } 231119542093SPeng Zhang 231219542093SPeng Zhang min_size = NFP_NET_VF_CFG_SZ * pf_dev->sriov_vf + NFP_NET_VF_CFG_MB_SZ; 231319542093SPeng Zhang snprintf(vf_cfg_name, sizeof(vf_cfg_name), "_pf%d_net_vf_cfg2", 231419542093SPeng Zhang pf_dev->multi_pf.function_id); 231519542093SPeng Zhang pf_dev->vf_cfg_tbl_bar = nfp_rtsym_map(pf_dev->sym_tbl, vf_cfg_name, 231619542093SPeng Zhang min_size, &pf_dev->vf_cfg_tbl_area); 231719542093SPeng Zhang if (pf_dev->vf_cfg_tbl_bar == NULL) { 231819542093SPeng Zhang PMD_INIT_LOG(ERR, "Failed to get vf configure table."); 231919542093SPeng Zhang ret = -EIO; 232019542093SPeng Zhang goto vf_bar_cleanup; 232119542093SPeng Zhang } 232219542093SPeng Zhang 232319542093SPeng Zhang return 0; 232419542093SPeng Zhang 232519542093SPeng Zhang vf_bar_cleanup: 232619542093SPeng Zhang nfp_cpp_area_release_free(pf_dev->vf_area); 232719542093SPeng Zhang 232819542093SPeng Zhang return ret; 232919542093SPeng Zhang } 233019542093SPeng Zhang 233119542093SPeng Zhang static int 2332a6189a67SJin Liu nfp_pf_init(struct rte_pci_device *pci_dev) 2333646ea79cSHeinrich Kuhn { 23346b4273a0SLong Wu void *sync; 2335e7978635SChaoyong He int ret = 0; 23365c464d6aSJin Liu uint64_t addr; 2337925c27ecSChaoyong He uint32_t cpp_id; 23383b00109dSPeng Zhang uint8_t function_id; 2339a6189a67SJin Liu struct nfp_cpp *cpp; 2340a6189a67SJin Liu struct nfp_pf_dev *pf_dev; 2341a6189a67SJin Liu struct nfp_hwinfo *hwinfo; 234249952141SChaoyong He enum nfp_app_fw_id app_fw_id; 2343a6189a67SJin Liu char name[RTE_ETH_NAME_MAX_LEN]; 2344a6189a67SJin Liu struct nfp_rtsym_table *sym_tbl; 2345ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 23463b00109dSPeng Zhang char app_name[RTE_ETH_NAME_MAX_LEN]; 2347a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table; 23480314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 2349646ea79cSHeinrich Kuhn 2350a6189a67SJin Liu if (pci_dev == NULL) 2351a6189a67SJin Liu return -ENODEV; 2352646ea79cSHeinrich Kuhn 235384aaba5aSChaoyong He if (pci_dev->mem_resource[0].addr == NULL) { 235484aaba5aSChaoyong He PMD_INIT_LOG(ERR, "The address of BAR0 is NULL."); 235584aaba5aSChaoyong He return -ENODEV; 235684aaba5aSChaoyong He } 235784aaba5aSChaoyong He 23580314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 23590314a8ffSChaoyong He if (dev_info == NULL) { 2360b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Not supported device ID."); 23610314a8ffSChaoyong He return -ENODEV; 23620314a8ffSChaoyong He } 23630314a8ffSChaoyong He 2364ff9f5a56SChaoyong He hw_priv = rte_zmalloc(NULL, sizeof(*hw_priv), 0); 2365ff9f5a56SChaoyong He if (hw_priv == NULL) { 2366b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not alloc memory for hw priv data."); 2367ff9f5a56SChaoyong He return -ENOMEM; 2368ff9f5a56SChaoyong He } 2369ff9f5a56SChaoyong He 23708ad2cc8fSPeng Zhang /* Allocate memory for the PF "device" */ 23713b00109dSPeng Zhang function_id = (pci_dev->addr.function) & 0x07; 23723b00109dSPeng Zhang snprintf(name, sizeof(name), "nfp_pf%u", function_id); 23738ad2cc8fSPeng Zhang pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); 23748ad2cc8fSPeng Zhang if (pf_dev == NULL) { 2375b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not allocate memory for the PF device."); 2376ff9f5a56SChaoyong He ret = -ENOMEM; 2377ff9f5a56SChaoyong He goto hw_priv_free; 23788ad2cc8fSPeng Zhang } 23798ad2cc8fSPeng Zhang 23806f708e52SChaoyong He hw_priv->dev_info = dev_info; 23816f708e52SChaoyong He hw_priv->pf_dev = pf_dev; 23826f708e52SChaoyong He 23836b4273a0SLong Wu sync = nfp_sync_alloc(); 23846b4273a0SLong Wu if (sync == NULL) { 23856b4273a0SLong Wu PMD_INIT_LOG(ERR, "Failed to alloc sync zone."); 23866b4273a0SLong Wu ret = -ENOMEM; 23876b4273a0SLong Wu goto pf_cleanup; 23886b4273a0SLong Wu } 23896b4273a0SLong Wu 23906f708e52SChaoyong He pf_dev->sync = sync; 23916f708e52SChaoyong He 2392646ea79cSHeinrich Kuhn /* 2393646ea79cSHeinrich Kuhn * When device bound to UIO, the device could be used, by mistake, 2394646ea79cSHeinrich Kuhn * by two DPDK apps, and the UIO driver does not avoid it. This 2395646ea79cSHeinrich Kuhn * could lead to a serious problem when configuring the NFP CPP 2396646ea79cSHeinrich Kuhn * interface. Here we avoid this telling to the CPP init code to 2397646ea79cSHeinrich Kuhn * use a lock file if UIO is being used. 2398646ea79cSHeinrich Kuhn */ 2399646ea79cSHeinrich Kuhn if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) 24001fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false); 2401646ea79cSHeinrich Kuhn else 24021fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true); 2403646ea79cSHeinrich Kuhn 2404a6189a67SJin Liu if (cpp == NULL) { 2405b6de4353SZerun Fu PMD_INIT_LOG(ERR, "A CPP handle can not be obtained."); 24068ad2cc8fSPeng Zhang ret = -EIO; 24076b4273a0SLong Wu goto sync_free; 2408646ea79cSHeinrich Kuhn } 2409646ea79cSHeinrich Kuhn 24106f708e52SChaoyong He pf_dev->cpp = cpp; 24116f708e52SChaoyong He pf_dev->pci_dev = pci_dev; 24126f708e52SChaoyong He 2413646ea79cSHeinrich Kuhn hwinfo = nfp_hwinfo_read(cpp); 2414a6189a67SJin Liu if (hwinfo == NULL) { 2415b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Error reading hwinfo table."); 2416646ea79cSHeinrich Kuhn ret = -EIO; 2417968ec1c3SChaoyong He goto cpp_cleanup; 2418646ea79cSHeinrich Kuhn } 2419646ea79cSHeinrich Kuhn 24206f708e52SChaoyong He pf_dev->hwinfo = hwinfo; 24216f708e52SChaoyong He 2422968ec1c3SChaoyong He /* Read the number of physical ports from hardware */ 2423646ea79cSHeinrich Kuhn nfp_eth_table = nfp_eth_read_ports(cpp); 2424a6189a67SJin Liu if (nfp_eth_table == NULL) { 2425b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Error reading NFP ethernet table."); 2426646ea79cSHeinrich Kuhn ret = -EIO; 2427646ea79cSHeinrich Kuhn goto hwinfo_cleanup; 2428646ea79cSHeinrich Kuhn } 2429646ea79cSHeinrich Kuhn 243030f9f163SChaoyong He if (nfp_eth_table->count == 0 || nfp_eth_table->count > 8) { 2431b6de4353SZerun Fu PMD_INIT_LOG(ERR, "NFP ethernet table reports wrong ports: %u.", 243230f9f163SChaoyong He nfp_eth_table->count); 243330f9f163SChaoyong He ret = -EIO; 243430f9f163SChaoyong He goto eth_table_cleanup; 243530f9f163SChaoyong He } 243630f9f163SChaoyong He 24376f708e52SChaoyong He pf_dev->nfp_eth_table = nfp_eth_table; 24388ad2cc8fSPeng Zhang pf_dev->multi_pf.enabled = nfp_check_multi_pf_from_nsp(pci_dev, cpp); 24393b00109dSPeng Zhang pf_dev->multi_pf.function_id = function_id; 2440eac7eda4SChaoyong He pf_dev->total_phyports = nfp_net_get_phyports_from_nsp(pf_dev); 24418ad2cc8fSPeng Zhang 24426f708e52SChaoyong He ret = nfp_net_force_port_down(pf_dev); 2443bd4969abSPeng Zhang if (ret != 0) { 2444b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to force port down."); 2445bd4969abSPeng Zhang ret = -EIO; 2446bd4969abSPeng Zhang goto eth_table_cleanup; 24473b00109dSPeng Zhang } 24489e442599SShihong Wang 24491a114cd0SLong Wu ret = nfp_devargs_parse(&pf_dev->devargs, pci_dev->device.devargs); 24501a114cd0SLong Wu if (ret != 0) { 2451b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Error when parsing device args."); 24521a114cd0SLong Wu ret = -EINVAL; 24531a114cd0SLong Wu goto eth_table_cleanup; 24541a114cd0SLong Wu } 2455b301fd73SPeng Zhang 24566f708e52SChaoyong He ret = nfp_net_device_activate(pf_dev); 245708461d7bSPeng Zhang if (ret != 0) { 2458b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to activate the NFP device."); 245908461d7bSPeng Zhang ret = -EIO; 246008461d7bSPeng Zhang goto eth_table_cleanup; 246108461d7bSPeng Zhang } 246208461d7bSPeng Zhang 24636f708e52SChaoyong He ret = nfp_fw_setup(pf_dev, dev_info); 24646f708e52SChaoyong He if (ret != 0) { 2465b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Error when uploading firmware."); 2466646ea79cSHeinrich Kuhn ret = -EIO; 2467646ea79cSHeinrich Kuhn goto eth_table_cleanup; 2468646ea79cSHeinrich Kuhn } 2469646ea79cSHeinrich Kuhn 2470646ea79cSHeinrich Kuhn /* Now the symbol table should be there */ 2471646ea79cSHeinrich Kuhn sym_tbl = nfp_rtsym_table_read(cpp); 2472a6189a67SJin Liu if (sym_tbl == NULL) { 2473b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table."); 2474646ea79cSHeinrich Kuhn ret = -EIO; 24753b00109dSPeng Zhang goto fw_cleanup; 2476646ea79cSHeinrich Kuhn } 2477646ea79cSHeinrich Kuhn 24786f708e52SChaoyong He pf_dev->sym_tbl = sym_tbl; 24796f708e52SChaoyong He 2480968ec1c3SChaoyong He /* Read the app ID of the firmware loaded */ 24813b00109dSPeng Zhang snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id); 24823b00109dSPeng Zhang app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret); 2483e7978635SChaoyong He if (ret != 0) { 2484b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Could not read %s from firmware.", app_name); 2485646ea79cSHeinrich Kuhn ret = -EIO; 2486646ea79cSHeinrich Kuhn goto sym_tbl_cleanup; 2487646ea79cSHeinrich Kuhn } 2488646ea79cSHeinrich Kuhn 24896f708e52SChaoyong He pf_dev->app_fw_id = app_fw_id; 24906f708e52SChaoyong He 2491c7a6970fSZerun Fu /* Write sp_indiff to hw_info */ 2492103134d2SZerun Fu ret = nfp_net_hwinfo_set(function_id, sym_tbl, cpp, app_fw_id); 2493c7a6970fSZerun Fu if (ret != 0) { 2494c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Failed to set hwinfo."); 2495c7a6970fSZerun Fu ret = -EIO; 2496c7a6970fSZerun Fu goto sym_tbl_cleanup; 2497c7a6970fSZerun Fu } 2498c7a6970fSZerun Fu 24995b46a539SPeng Zhang ret = nfp_net_speed_cap_get(pf_dev); 25003110ab73SZerun Fu if (ret != 0) { 25013110ab73SZerun Fu PMD_INIT_LOG(ERR, "Failed to get speed capability."); 25023110ab73SZerun Fu ret = -EIO; 25033110ab73SZerun Fu goto sym_tbl_cleanup; 25043110ab73SZerun Fu } 25053110ab73SZerun Fu 250620086cb8SPeng Zhang /* Get the VF info */ 250720086cb8SPeng Zhang ret = nfp_net_get_vf_info(pf_dev, dev_info); 250820086cb8SPeng Zhang if (ret != 0) { 250920086cb8SPeng Zhang PMD_INIT_LOG(ERR, "Failed to get VF info."); 251020086cb8SPeng Zhang ret = -EIO; 251120086cb8SPeng Zhang goto sym_tbl_cleanup; 251220086cb8SPeng Zhang } 251320086cb8SPeng Zhang 251440688372SChaoyong He /* Configure access to tx/rx vNIC BARs */ 25150314a8ffSChaoyong He addr = nfp_qcp_queue_offset(dev_info, 0); 2516925c27ecSChaoyong He cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0); 25170314a8ffSChaoyong He 2518711e4559SChaoyong He pf_dev->qc_bar = nfp_cpp_map_area(pf_dev->cpp, cpp_id, 25190314a8ffSChaoyong He addr, dev_info->qc_area_sz, &pf_dev->qc_area); 2520711e4559SChaoyong He if (pf_dev->qc_bar == NULL) { 2521b6de4353SZerun Fu PMD_INIT_LOG(ERR, "The nfp_rtsym_map fails for net.qc."); 2522646ea79cSHeinrich Kuhn ret = -EIO; 25238ad2cc8fSPeng Zhang goto sym_tbl_cleanup; 2524646ea79cSHeinrich Kuhn } 2525646ea79cSHeinrich Kuhn 2526b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "The qc_bar address: %p.", pf_dev->qc_bar); 2527646ea79cSHeinrich Kuhn 2528e54d68a0SChaoyong He pf_dev->mac_stats_bar = nfp_rtsym_map(sym_tbl, "_mac_stats", 2529e54d68a0SChaoyong He NFP_MAC_STATS_SIZE * nfp_eth_table->max_index, 2530e54d68a0SChaoyong He &pf_dev->mac_stats_area); 2531e54d68a0SChaoyong He if (pf_dev->mac_stats_bar == NULL) { 2532b6de4353SZerun Fu PMD_INIT_LOG(ERR, "The nfp_rtsym_map fails for _mac_stats."); 2533e54d68a0SChaoyong He goto hwqueues_cleanup; 2534e54d68a0SChaoyong He } 2535e54d68a0SChaoyong He 253619bd7cceSChaoyong He ret = nfp_enable_multi_pf(pf_dev); 253719bd7cceSChaoyong He if (ret != 0) 253819bd7cceSChaoyong He goto mac_stats_cleanup; 253919bd7cceSChaoyong He 254019542093SPeng Zhang ret = nfp_net_vf_config_init(pf_dev); 254119542093SPeng Zhang if (ret != 0) { 254219542093SPeng Zhang PMD_INIT_LOG(ERR, "Failed to init VF config."); 25431dd83476SPeng Zhang goto vf_cfg_tbl_cleanup; 254419bd7cceSChaoyong He } 25451dd83476SPeng Zhang 2546c2b4f0d5SChaoyong He hw_priv->is_pf = true; 2547ff9f5a56SChaoyong He 2548636e133eSPeng Zhang if (!nfp_net_recv_pkt_meta_check_register(hw_priv)) { 2549636e133eSPeng Zhang PMD_INIT_LOG(ERR, "PF register meta check function failed."); 2550636e133eSPeng Zhang ret = -EIO; 2551636e133eSPeng Zhang goto hw_priv_free; 2552636e133eSPeng Zhang } 2553636e133eSPeng Zhang 2554a6189a67SJin Liu /* 2555968ec1c3SChaoyong He * PF initialization has been done at this point. Call app specific 255640688372SChaoyong He * init code now. 2557646ea79cSHeinrich Kuhn */ 2558e51160adSPeng Zhang ret = nfp_fw_app_primary_init(hw_priv); 2559968ec1c3SChaoyong He if (ret != 0) { 2560e51160adSPeng Zhang PMD_INIT_LOG(ERR, "Failed to init hw app primary."); 256119542093SPeng Zhang goto vf_cfg_tbl_cleanup; 2562646ea79cSHeinrich Kuhn } 2563646ea79cSHeinrich Kuhn 256440688372SChaoyong He /* Register the CPP bridge service here for primary use */ 2565c50bf4f0SLong Wu if (pf_dev->devargs.cpp_service_enable) { 2566bab0e6f4SChaoyong He ret = nfp_enable_cpp_service(pf_dev); 25676d0ee64aSLong Wu if (ret != 0) { 25686d0ee64aSLong Wu PMD_INIT_LOG(ERR, "Enable CPP service failed."); 256919542093SPeng Zhang goto vf_cfg_tbl_cleanup; 25706d0ee64aSLong Wu } 2571c50bf4f0SLong Wu } 2572646ea79cSHeinrich Kuhn 2573646ea79cSHeinrich Kuhn return 0; 2574646ea79cSHeinrich Kuhn 257519542093SPeng Zhang vf_cfg_tbl_cleanup: 257619542093SPeng Zhang nfp_net_vf_config_uninit(pf_dev); 2577e54d68a0SChaoyong He mac_stats_cleanup: 2578e54d68a0SChaoyong He nfp_cpp_area_release_free(pf_dev->mac_stats_area); 2579646ea79cSHeinrich Kuhn hwqueues_cleanup: 2580528812a6SChaoyong He nfp_cpp_area_release_free(pf_dev->qc_area); 2581646ea79cSHeinrich Kuhn sym_tbl_cleanup: 2582646ea79cSHeinrich Kuhn free(sym_tbl); 25833b00109dSPeng Zhang fw_cleanup: 25843b00109dSPeng Zhang nfp_fw_unload(cpp); 25853a64e190SChaoyong He if (pf_dev->multi_pf.enabled) { 25868ba461d1SPeng Zhang nfp_net_keepalive_stop(&pf_dev->multi_pf); 2587b67a7b40SPeng Zhang nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id); 2588528812a6SChaoyong He nfp_net_keepalive_uninit(&pf_dev->multi_pf); 25893a64e190SChaoyong He } 2590646ea79cSHeinrich Kuhn eth_table_cleanup: 2591646ea79cSHeinrich Kuhn free(nfp_eth_table); 2592646ea79cSHeinrich Kuhn hwinfo_cleanup: 2593646ea79cSHeinrich Kuhn free(hwinfo); 2594968ec1c3SChaoyong He cpp_cleanup: 2595968ec1c3SChaoyong He nfp_cpp_free(cpp); 25966b4273a0SLong Wu sync_free: 25976b4273a0SLong Wu nfp_sync_free(sync); 25988ad2cc8fSPeng Zhang pf_cleanup: 25998ad2cc8fSPeng Zhang rte_free(pf_dev); 2600ff9f5a56SChaoyong He hw_priv_free: 2601ff9f5a56SChaoyong He rte_free(hw_priv); 26027feb8909SChaoyong He 2603646ea79cSHeinrich Kuhn return ret; 2604646ea79cSHeinrich Kuhn } 2605646ea79cSHeinrich Kuhn 2606d5f39e07SChaoyong He static int 26076484c847SChaoyong He nfp_secondary_net_init(struct rte_eth_dev *eth_dev, 26086484c847SChaoyong He void *para) 26096484c847SChaoyong He { 2610000feb4cSChaoyong He struct nfp_net_hw_priv *hw_priv; 26116484c847SChaoyong He 2612000feb4cSChaoyong He hw_priv = para; 2613000feb4cSChaoyong He nfp_net_ethdev_ops_mount(hw_priv->pf_dev, eth_dev); 26146484c847SChaoyong He 26156484c847SChaoyong He eth_dev->process_private = para; 26166484c847SChaoyong He 26176484c847SChaoyong He return 0; 26186484c847SChaoyong He } 26196484c847SChaoyong He 26206484c847SChaoyong He static int 2621ff9f5a56SChaoyong He nfp_secondary_init_app_fw_nic(struct nfp_net_hw_priv *hw_priv) 2622d5f39e07SChaoyong He { 26238ceb85c3SChaoyong He uint32_t i; 2624d5f39e07SChaoyong He int ret = 0; 26258ceb85c3SChaoyong He uint32_t total_vnics; 2626eac7eda4SChaoyong He char port_name[RTE_ETH_NAME_MAX_LEN]; 2627ff9f5a56SChaoyong He struct nfp_pf_dev *pf_dev = hw_priv->pf_dev; 2628d5f39e07SChaoyong He 2629eac7eda4SChaoyong He total_vnics = nfp_net_get_phyports_from_fw(pf_dev); 2630d5f39e07SChaoyong He 2631d5f39e07SChaoyong He for (i = 0; i < total_vnics; i++) { 2632eac7eda4SChaoyong He nfp_port_name_generate(port_name, sizeof(port_name), i, pf_dev); 2633d5f39e07SChaoyong He 2634b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "Secondary attaching to port %s.", port_name); 26356484c847SChaoyong He ret = rte_eth_dev_create(&pf_dev->pci_dev->device, port_name, 0, 26366484c847SChaoyong He NULL, NULL, nfp_secondary_net_init, hw_priv); 26376484c847SChaoyong He if (ret != 0) { 2638b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Secondary process attach to port %s failed.", port_name); 2639eac7eda4SChaoyong He goto port_cleanup; 2640d5f39e07SChaoyong He } 2641d5f39e07SChaoyong He } 2642d5f39e07SChaoyong He 2643eac7eda4SChaoyong He return 0; 2644eac7eda4SChaoyong He 2645eac7eda4SChaoyong He port_cleanup: 2646eac7eda4SChaoyong He for (uint32_t j = 0; j < i; j++) { 2647eac7eda4SChaoyong He struct rte_eth_dev *eth_dev; 2648eac7eda4SChaoyong He 2649eac7eda4SChaoyong He nfp_port_name_generate(port_name, sizeof(port_name), j, pf_dev); 2650eac7eda4SChaoyong He eth_dev = rte_eth_dev_get_by_name(port_name); 2651eac7eda4SChaoyong He if (eth_dev != NULL) 2652eac7eda4SChaoyong He rte_eth_dev_destroy(eth_dev, NULL); 2653eac7eda4SChaoyong He } 2654eac7eda4SChaoyong He 2655d5f39e07SChaoyong He return ret; 2656d5f39e07SChaoyong He } 2657d5f39e07SChaoyong He 2658e51160adSPeng Zhang static int 2659e51160adSPeng Zhang nfp_fw_app_secondary_init(struct nfp_net_hw_priv *hw_priv) 2660e51160adSPeng Zhang { 2661e51160adSPeng Zhang int ret; 2662e51160adSPeng Zhang struct nfp_pf_dev *pf_dev = hw_priv->pf_dev; 2663e51160adSPeng Zhang 2664e51160adSPeng Zhang switch (pf_dev->app_fw_id) { 2665e51160adSPeng Zhang case NFP_APP_FW_CORE_NIC: 2666b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Initializing coreNIC."); 2667e51160adSPeng Zhang ret = nfp_secondary_init_app_fw_nic(hw_priv); 2668e51160adSPeng Zhang if (ret != 0) { 2669e51160adSPeng Zhang PMD_INIT_LOG(ERR, "Could not initialize coreNIC!"); 2670e51160adSPeng Zhang return ret; 2671e51160adSPeng Zhang } 2672e51160adSPeng Zhang break; 2673e51160adSPeng Zhang case NFP_APP_FW_FLOWER_NIC: 2674b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Initializing Flower."); 2675e51160adSPeng Zhang ret = nfp_secondary_init_app_fw_flower(hw_priv); 2676e51160adSPeng Zhang if (ret != 0) { 2677e51160adSPeng Zhang PMD_INIT_LOG(ERR, "Could not initialize Flower!"); 2678e51160adSPeng Zhang return ret; 2679e51160adSPeng Zhang } 2680e51160adSPeng Zhang break; 2681e51160adSPeng Zhang default: 2682b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Unsupported Firmware loaded."); 2683e51160adSPeng Zhang ret = -EINVAL; 2684e51160adSPeng Zhang return ret; 2685e51160adSPeng Zhang } 2686e51160adSPeng Zhang 2687e51160adSPeng Zhang return 0; 2688e51160adSPeng Zhang } 2689e51160adSPeng Zhang 2690646ea79cSHeinrich Kuhn /* 2691646ea79cSHeinrich Kuhn * When attaching to the NFP4000/6000 PF on a secondary process there 2692646ea79cSHeinrich Kuhn * is no need to initialise the PF again. Only minimal work is required 269340688372SChaoyong He * here. 2694646ea79cSHeinrich Kuhn */ 2695a6189a67SJin Liu static int 2696a6189a67SJin Liu nfp_pf_secondary_init(struct rte_pci_device *pci_dev) 2697646ea79cSHeinrich Kuhn { 26986b4273a0SLong Wu void *sync; 2699968ec1c3SChaoyong He int ret = 0; 2700a6189a67SJin Liu struct nfp_cpp *cpp; 27013b00109dSPeng Zhang uint8_t function_id; 2702016141b1SChaoyong He struct nfp_pf_dev *pf_dev; 2703d5f39e07SChaoyong He enum nfp_app_fw_id app_fw_id; 2704016141b1SChaoyong He char name[RTE_ETH_NAME_MAX_LEN]; 2705a6189a67SJin Liu struct nfp_rtsym_table *sym_tbl; 2706ff9f5a56SChaoyong He struct nfp_net_hw_priv *hw_priv; 27070314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 27083b00109dSPeng Zhang char app_name[RTE_ETH_NAME_MAX_LEN]; 2709646ea79cSHeinrich Kuhn 2710a6189a67SJin Liu if (pci_dev == NULL) 2711646ea79cSHeinrich Kuhn return -ENODEV; 2712646ea79cSHeinrich Kuhn 271384aaba5aSChaoyong He if (pci_dev->mem_resource[0].addr == NULL) { 271484aaba5aSChaoyong He PMD_INIT_LOG(ERR, "The address of BAR0 is NULL."); 271584aaba5aSChaoyong He return -ENODEV; 271684aaba5aSChaoyong He } 271784aaba5aSChaoyong He 27180314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 27190314a8ffSChaoyong He if (dev_info == NULL) { 2720b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Not supported device ID."); 27210314a8ffSChaoyong He return -ENODEV; 27220314a8ffSChaoyong He } 27230314a8ffSChaoyong He 2724ff9f5a56SChaoyong He hw_priv = rte_zmalloc(NULL, sizeof(*hw_priv), 0); 2725ff9f5a56SChaoyong He if (hw_priv == NULL) { 2726b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not alloc memory for hw priv data."); 2727ff9f5a56SChaoyong He return -ENOMEM; 2728ff9f5a56SChaoyong He } 2729ff9f5a56SChaoyong He 2730016141b1SChaoyong He /* Allocate memory for the PF "device" */ 2731eac7eda4SChaoyong He function_id = pci_dev->addr.function & 0x7; 2732016141b1SChaoyong He snprintf(name, sizeof(name), "nfp_pf%d", 0); 2733016141b1SChaoyong He pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); 2734016141b1SChaoyong He if (pf_dev == NULL) { 2735b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not allocate memory for the PF device."); 2736ff9f5a56SChaoyong He ret = -ENOMEM; 2737ff9f5a56SChaoyong He goto hw_priv_free; 2738016141b1SChaoyong He } 2739016141b1SChaoyong He 27406f708e52SChaoyong He hw_priv->pf_dev = pf_dev; 27416f708e52SChaoyong He hw_priv->dev_info = dev_info; 27426f708e52SChaoyong He 27436b4273a0SLong Wu sync = nfp_sync_alloc(); 27446b4273a0SLong Wu if (sync == NULL) { 27456b4273a0SLong Wu PMD_INIT_LOG(ERR, "Failed to alloc sync zone."); 27466b4273a0SLong Wu ret = -ENOMEM; 27476b4273a0SLong Wu goto pf_cleanup; 27486b4273a0SLong Wu } 27496b4273a0SLong Wu 27506f708e52SChaoyong He pf_dev->sync = sync; 27516f708e52SChaoyong He 2752646ea79cSHeinrich Kuhn /* 2753646ea79cSHeinrich Kuhn * When device bound to UIO, the device could be used, by mistake, 2754646ea79cSHeinrich Kuhn * by two DPDK apps, and the UIO driver does not avoid it. This 2755646ea79cSHeinrich Kuhn * could lead to a serious problem when configuring the NFP CPP 2756646ea79cSHeinrich Kuhn * interface. Here we avoid this telling to the CPP init code to 2757646ea79cSHeinrich Kuhn * use a lock file if UIO is being used. 2758646ea79cSHeinrich Kuhn */ 2759646ea79cSHeinrich Kuhn if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) 27601fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false); 2761646ea79cSHeinrich Kuhn else 27621fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true); 2763646ea79cSHeinrich Kuhn 2764a6189a67SJin Liu if (cpp == NULL) { 2765b6de4353SZerun Fu PMD_INIT_LOG(ERR, "A CPP handle can not be obtained."); 2766016141b1SChaoyong He ret = -EIO; 27676b4273a0SLong Wu goto sync_free; 2768646ea79cSHeinrich Kuhn } 2769646ea79cSHeinrich Kuhn 27706f708e52SChaoyong He pf_dev->cpp = cpp; 27716f708e52SChaoyong He pf_dev->pci_dev = pci_dev; 27726f708e52SChaoyong He 2773646ea79cSHeinrich Kuhn /* 2774646ea79cSHeinrich Kuhn * We don't have access to the PF created in the primary process 277540688372SChaoyong He * here so we have to read the number of ports from firmware. 2776646ea79cSHeinrich Kuhn */ 2777646ea79cSHeinrich Kuhn sym_tbl = nfp_rtsym_table_read(cpp); 2778a6189a67SJin Liu if (sym_tbl == NULL) { 2779b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table."); 2780016141b1SChaoyong He ret = -EIO; 2781db8150deSChaoyong He goto cpp_cleanup; 2782646ea79cSHeinrich Kuhn } 2783646ea79cSHeinrich Kuhn 27846f708e52SChaoyong He pf_dev->sym_tbl = sym_tbl; 27856f708e52SChaoyong He 2786eac7eda4SChaoyong He /* Read the number of physical ports from firmware */ 2787eac7eda4SChaoyong He pf_dev->multi_pf.function_id = function_id; 2788eac7eda4SChaoyong He pf_dev->total_phyports = nfp_net_get_phyports_from_fw(pf_dev); 2789eac7eda4SChaoyong He pf_dev->multi_pf.enabled = nfp_check_multi_pf_from_fw(pf_dev->total_phyports); 2790eac7eda4SChaoyong He 2791d5f39e07SChaoyong He /* Read the app ID of the firmware loaded */ 27923b00109dSPeng Zhang snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id); 27933b00109dSPeng Zhang app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret); 2794e7978635SChaoyong He if (ret != 0) { 2795b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Could not read %s from fw.", app_name); 2796016141b1SChaoyong He ret = -EIO; 2797968ec1c3SChaoyong He goto sym_tbl_cleanup; 2798968ec1c3SChaoyong He } 2799646ea79cSHeinrich Kuhn 2800016141b1SChaoyong He pf_dev->app_fw_id = app_fw_id; 2801016141b1SChaoyong He 2802c2b4f0d5SChaoyong He hw_priv->is_pf = true; 2803ff9f5a56SChaoyong He 2804016141b1SChaoyong He /* Call app specific init code now */ 2805e51160adSPeng Zhang ret = nfp_fw_app_secondary_init(hw_priv); 2806d5f39e07SChaoyong He if (ret != 0) { 2807e51160adSPeng Zhang PMD_INIT_LOG(ERR, "Failed to init hw app primary."); 2808d5f39e07SChaoyong He goto sym_tbl_cleanup; 2809646ea79cSHeinrich Kuhn } 2810646ea79cSHeinrich Kuhn 2811016141b1SChaoyong He return 0; 2812016141b1SChaoyong He 2813968ec1c3SChaoyong He sym_tbl_cleanup: 2814968ec1c3SChaoyong He free(sym_tbl); 2815db8150deSChaoyong He cpp_cleanup: 2816db8150deSChaoyong He nfp_cpp_free(cpp); 28176b4273a0SLong Wu sync_free: 28186b4273a0SLong Wu nfp_sync_free(sync); 2819016141b1SChaoyong He pf_cleanup: 2820016141b1SChaoyong He rte_free(pf_dev); 2821ff9f5a56SChaoyong He hw_priv_free: 2822ff9f5a56SChaoyong He rte_free(hw_priv); 2823968ec1c3SChaoyong He 2824968ec1c3SChaoyong He return ret; 2825646ea79cSHeinrich Kuhn } 2826646ea79cSHeinrich Kuhn 2827a6189a67SJin Liu static int 2828a6189a67SJin Liu nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 2829646ea79cSHeinrich Kuhn struct rte_pci_device *dev) 2830646ea79cSHeinrich Kuhn { 2831646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 2832646ea79cSHeinrich Kuhn return nfp_pf_init(dev); 2833646ea79cSHeinrich Kuhn else 2834646ea79cSHeinrich Kuhn return nfp_pf_secondary_init(dev); 2835646ea79cSHeinrich Kuhn } 2836646ea79cSHeinrich Kuhn 2837646ea79cSHeinrich Kuhn static const struct rte_pci_id pci_id_nfp_pf_net_map[] = { 2838646ea79cSHeinrich Kuhn { 2839646ea79cSHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 28405c464d6aSJin Liu PCI_DEVICE_ID_NFP3800_PF_NIC) 28415c464d6aSJin Liu }, 28425c464d6aSJin Liu { 28435c464d6aSJin Liu RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 2844646ea79cSHeinrich Kuhn PCI_DEVICE_ID_NFP4000_PF_NIC) 2845646ea79cSHeinrich Kuhn }, 2846646ea79cSHeinrich Kuhn { 2847646ea79cSHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 2848646ea79cSHeinrich Kuhn PCI_DEVICE_ID_NFP6000_PF_NIC) 2849646ea79cSHeinrich Kuhn }, 2850646ea79cSHeinrich Kuhn { 28515aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 28525aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP3800_PF_NIC) 28535aedd4c3SJames Hershaw }, 28545aedd4c3SJames Hershaw { 28555aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 28565aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP4000_PF_NIC) 28575aedd4c3SJames Hershaw }, 28585aedd4c3SJames Hershaw { 28595aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 28605aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP6000_PF_NIC) 28615aedd4c3SJames Hershaw }, 28625aedd4c3SJames Hershaw { 2863646ea79cSHeinrich Kuhn .vendor_id = 0, 2864646ea79cSHeinrich Kuhn }, 2865646ea79cSHeinrich Kuhn }; 2866646ea79cSHeinrich Kuhn 2867a6189a67SJin Liu static int 2868a6189a67SJin Liu nfp_pci_uninit(struct rte_eth_dev *eth_dev) 2869646ea79cSHeinrich Kuhn { 2870646ea79cSHeinrich Kuhn uint16_t port_id; 287149952141SChaoyong He struct rte_pci_device *pci_dev; 2872646ea79cSHeinrich Kuhn 2873646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 2874646ea79cSHeinrich Kuhn 2875646ea79cSHeinrich Kuhn /* Free up all physical ports under PF */ 2876646ea79cSHeinrich Kuhn RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) 2877646ea79cSHeinrich Kuhn rte_eth_dev_close(port_id); 2878646ea79cSHeinrich Kuhn /* 2879646ea79cSHeinrich Kuhn * Ports can be closed and freed but hotplugging is not 288040688372SChaoyong He * currently supported. 2881646ea79cSHeinrich Kuhn */ 2882646ea79cSHeinrich Kuhn return -ENOTSUP; 2883646ea79cSHeinrich Kuhn } 2884646ea79cSHeinrich Kuhn 2885a6189a67SJin Liu static int 2886a6189a67SJin Liu eth_nfp_pci_remove(struct rte_pci_device *pci_dev) 2887646ea79cSHeinrich Kuhn { 2888646ea79cSHeinrich Kuhn return rte_eth_dev_pci_generic_remove(pci_dev, nfp_pci_uninit); 2889646ea79cSHeinrich Kuhn } 2890646ea79cSHeinrich Kuhn 2891646ea79cSHeinrich Kuhn static struct rte_pci_driver rte_nfp_net_pf_pmd = { 2892646ea79cSHeinrich Kuhn .id_table = pci_id_nfp_pf_net_map, 2893646ea79cSHeinrich Kuhn .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 2894646ea79cSHeinrich Kuhn .probe = nfp_pf_pci_probe, 2895646ea79cSHeinrich Kuhn .remove = eth_nfp_pci_remove, 2896646ea79cSHeinrich Kuhn }; 2897646ea79cSHeinrich Kuhn 2898d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI(NFP_PF_DRIVER_NAME, rte_nfp_net_pf_pmd); 2899d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI_TABLE(NFP_PF_DRIVER_NAME, pci_id_nfp_pf_net_map); 2900d505ee1dSChaoyong He RTE_PMD_REGISTER_KMOD_DEP(NFP_PF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio"); 2901c50bf4f0SLong Wu RTE_PMD_REGISTER_PARAM_STRING(NFP_PF_DRIVER_NAME, 2902c50bf4f0SLong Wu NFP_PF_FORCE_RELOAD_FW "=<0|1>" 2903c50bf4f0SLong Wu NFP_CPP_SERVICE_ENABLE "=<0|1>"); 2904