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> 12646ea79cSHeinrich Kuhn 135a95b024SChaoyong He #include "flower/nfp_flower.h" 145a95b024SChaoyong He #include "nfd3/nfp_nfd3.h" 155a95b024SChaoyong He #include "nfdk/nfp_nfdk.h" 16646ea79cSHeinrich Kuhn #include "nfpcore/nfp_cpp.h" 17*a2bc299dSPeng Zhang #include "nfpcore/nfp_elf.h" 18646ea79cSHeinrich Kuhn #include "nfpcore/nfp_hwinfo.h" 19646ea79cSHeinrich Kuhn #include "nfpcore/nfp_rtsym.h" 20646ea79cSHeinrich Kuhn #include "nfpcore/nfp_nsp.h" 21796f1aecSChaoyong He #include "nfpcore/nfp6000_pcie.h" 228ba461d1SPeng Zhang #include "nfpcore/nfp_resource.h" 236b4273a0SLong Wu #include "nfpcore/nfp_sync.h" 24646ea79cSHeinrich Kuhn 25646ea79cSHeinrich Kuhn #include "nfp_cpp_bridge.h" 2654713740SChang Miao #include "nfp_ipsec.h" 275a95b024SChaoyong He #include "nfp_logs.h" 288153bc6fSChaoyong He #include "nfp_net_flow.h" 29b1880421SChaoyong He 30c7a6970fSZerun Fu /* 64-bit per app capabilities */ 31c7a6970fSZerun Fu #define NFP_NET_APP_CAP_SP_INDIFF RTE_BIT64(0) /* Indifferent to port speed */ 32c7a6970fSZerun Fu 33d505ee1dSChaoyong He #define NFP_PF_DRIVER_NAME net_nfp_pf 34d505ee1dSChaoyong He 35a243128bSChaoyong He static void 36f4d24fe9SChaoyong He nfp_net_pf_read_mac(struct nfp_app_fw_nic *app_fw_nic, 378ceb85c3SChaoyong He uint16_t port) 38646ea79cSHeinrich Kuhn { 3949952141SChaoyong He struct nfp_net_hw *hw; 40646ea79cSHeinrich Kuhn struct nfp_eth_table *nfp_eth_table; 41646ea79cSHeinrich Kuhn 42646ea79cSHeinrich Kuhn /* Grab a pointer to the correct physical port */ 43968ec1c3SChaoyong He hw = app_fw_nic->ports[port]; 44646ea79cSHeinrich Kuhn 45a243128bSChaoyong He nfp_eth_table = app_fw_nic->pf_dev->nfp_eth_table; 46646ea79cSHeinrich Kuhn 47ef759759SChaoyong He rte_ether_addr_copy(&nfp_eth_table->ports[port].mac_addr, &hw->super.mac_addr); 48646ea79cSHeinrich Kuhn } 49646ea79cSHeinrich Kuhn 50009f43d5SZerun Fu static uint32_t 51009f43d5SZerun Fu nfp_net_speed_bitmap2speed(uint32_t speeds_bitmap) 52009f43d5SZerun Fu { 53009f43d5SZerun Fu switch (speeds_bitmap) { 54009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10M_HD: 55009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10M; 56009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10M: 57009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10M; 58009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100M_HD: 59009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100M; 60009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100M: 61009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100M; 62009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_1G: 63009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_1G; 64009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_2_5G: 65009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_2_5G; 66009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_5G: 67009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_5G; 68009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10G: 69009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10G; 70009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_20G: 71009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_20G; 72009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_25G: 73009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_25G; 74009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_40G: 75009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_40G; 76009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_50G: 77009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_50G; 78009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_56G: 79009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_56G; 80009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100G: 81009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100G; 82009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_200G: 83009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_200G; 84009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_400G: 85009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_400G; 86009f43d5SZerun Fu default: 87009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_NONE; 88009f43d5SZerun Fu } 89009f43d5SZerun Fu } 90009f43d5SZerun Fu 91009f43d5SZerun Fu static int 92009f43d5SZerun Fu nfp_net_nfp4000_speed_configure_check(uint16_t port_id, 93009f43d5SZerun Fu uint32_t configure_speed, 94009f43d5SZerun Fu struct nfp_eth_table *nfp_eth_table) 95009f43d5SZerun Fu { 96009f43d5SZerun Fu switch (port_id) { 97009f43d5SZerun Fu case 0: 98009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_25G && 99009f43d5SZerun Fu nfp_eth_table->ports[1].speed == RTE_ETH_SPEED_NUM_10G) { 100009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000."); 101009f43d5SZerun Fu return -ENOTSUP; 102009f43d5SZerun Fu } 103009f43d5SZerun Fu break; 104009f43d5SZerun Fu case 1: 105009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_10G && 106009f43d5SZerun Fu nfp_eth_table->ports[0].speed == RTE_ETH_SPEED_NUM_25G) { 107009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000."); 108009f43d5SZerun Fu return -ENOTSUP; 109009f43d5SZerun Fu } 110009f43d5SZerun Fu break; 111009f43d5SZerun Fu default: 112009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The port id is invalid."); 113009f43d5SZerun Fu return -EINVAL; 114009f43d5SZerun Fu } 115009f43d5SZerun Fu 116009f43d5SZerun Fu return 0; 117009f43d5SZerun Fu } 118009f43d5SZerun Fu 119009f43d5SZerun Fu static int 120009f43d5SZerun Fu nfp_net_speed_configure(struct rte_eth_dev *dev, 121009f43d5SZerun Fu struct nfp_net_hw *net_hw) 122009f43d5SZerun Fu { 123009f43d5SZerun Fu int ret; 124009f43d5SZerun Fu uint32_t speed_capa; 125009f43d5SZerun Fu struct nfp_nsp *nsp; 126009f43d5SZerun Fu uint32_t link_speeds; 127009f43d5SZerun Fu uint32_t configure_speed; 128009f43d5SZerun Fu struct nfp_eth_table_port *eth_port; 129009f43d5SZerun Fu struct nfp_eth_table *nfp_eth_table; 130009f43d5SZerun Fu 131009f43d5SZerun Fu nfp_eth_table = net_hw->pf_dev->nfp_eth_table; 132009f43d5SZerun Fu eth_port = &nfp_eth_table->ports[net_hw->idx]; 133009f43d5SZerun Fu 134009f43d5SZerun Fu speed_capa = net_hw->pf_dev->speed_capa; 135009f43d5SZerun Fu if (speed_capa == 0) { 136009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Speed_capa is invalid."); 137009f43d5SZerun Fu return -EINVAL; 138009f43d5SZerun Fu } 139009f43d5SZerun Fu 140009f43d5SZerun Fu link_speeds = dev->data->dev_conf.link_speeds; 141009f43d5SZerun Fu configure_speed = nfp_net_speed_bitmap2speed(speed_capa & link_speeds); 142009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_NONE && 143009f43d5SZerun Fu link_speeds != RTE_ETH_LINK_SPEED_AUTONEG) { 144009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Configured speed is invalid."); 145009f43d5SZerun Fu return -EINVAL; 146009f43d5SZerun Fu } 147009f43d5SZerun Fu 148009f43d5SZerun Fu /* NFP4000 does not allow the port 0 25Gbps and port 1 10Gbps at the same time. */ 149009f43d5SZerun Fu if (net_hw->device_id == PCI_DEVICE_ID_NFP4000_PF_NIC) { 150009f43d5SZerun Fu ret = nfp_net_nfp4000_speed_configure_check(net_hw->idx, 151009f43d5SZerun Fu configure_speed, nfp_eth_table); 152009f43d5SZerun Fu if (ret != 0) { 153009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure speed for NFP4000."); 154009f43d5SZerun Fu return ret; 155009f43d5SZerun Fu } 156009f43d5SZerun Fu } 157009f43d5SZerun Fu 158009f43d5SZerun Fu nsp = nfp_eth_config_start(net_hw->cpp, eth_port->index); 159009f43d5SZerun Fu if (nsp == NULL) { 160009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Couldn't get NSP."); 161009f43d5SZerun Fu return -EIO; 162009f43d5SZerun Fu } 163009f43d5SZerun Fu 164009f43d5SZerun Fu if (link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { 165009f43d5SZerun Fu if (eth_port->supp_aneg) { 166009f43d5SZerun Fu ret = nfp_eth_set_aneg(nsp, NFP_ANEG_AUTO); 167009f43d5SZerun Fu if (ret != 0) { 168009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set ANEG enable."); 169009f43d5SZerun Fu goto config_cleanup; 170009f43d5SZerun Fu } 171009f43d5SZerun Fu } 172009f43d5SZerun Fu } else { 173009f43d5SZerun Fu ret = nfp_eth_set_aneg(nsp, NFP_ANEG_DISABLED); 174009f43d5SZerun Fu if (ret != 0) { 175009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set ANEG disable."); 176009f43d5SZerun Fu goto config_cleanup; 177009f43d5SZerun Fu } 178009f43d5SZerun Fu 179009f43d5SZerun Fu ret = nfp_eth_set_speed(nsp, configure_speed); 180009f43d5SZerun Fu if (ret != 0) { 181009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set speed."); 182009f43d5SZerun Fu goto config_cleanup; 183009f43d5SZerun Fu } 184009f43d5SZerun Fu } 185009f43d5SZerun Fu 186009f43d5SZerun Fu return nfp_eth_config_commit_end(nsp); 187009f43d5SZerun Fu 188009f43d5SZerun Fu config_cleanup: 189009f43d5SZerun Fu nfp_eth_config_cleanup_end(nsp); 190009f43d5SZerun Fu 191009f43d5SZerun Fu return ret; 192009f43d5SZerun Fu } 193009f43d5SZerun Fu 194646ea79cSHeinrich Kuhn static int 195646ea79cSHeinrich Kuhn nfp_net_start(struct rte_eth_dev *dev) 196646ea79cSHeinrich Kuhn { 19749952141SChaoyong He int ret; 19849952141SChaoyong He uint16_t i; 19972d1dea6SChaoyong He struct nfp_hw *hw; 20049952141SChaoyong He uint32_t new_ctrl; 201acb6bebfSChaoyong He struct nfp_cpp *cpp; 20249952141SChaoyong He uint32_t update = 0; 2032e7c3612SQin Ke uint32_t cap_extend; 20449952141SChaoyong He uint32_t intr_vector; 20549952141SChaoyong He uint32_t ctrl_extend = 0; 20672d1dea6SChaoyong He struct nfp_net_hw *net_hw; 207646ea79cSHeinrich Kuhn struct nfp_pf_dev *pf_dev; 208646ea79cSHeinrich Kuhn struct rte_eth_rxmode *rxmode; 20949952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 21049952141SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 21149952141SChaoyong He struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 212646ea79cSHeinrich Kuhn 2139d723baaSChaoyong He net_hw = dev->data->dev_private; 21465f6915dSChaoyong He pf_dev = net_hw->pf_dev; 215968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 21672d1dea6SChaoyong He hw = &net_hw->super; 217646ea79cSHeinrich Kuhn 218646ea79cSHeinrich Kuhn /* Disabling queues just in case... */ 219646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 220646ea79cSHeinrich Kuhn 221646ea79cSHeinrich Kuhn /* Enabling the required queues in the device */ 222646ea79cSHeinrich Kuhn nfp_net_enable_queues(dev); 223646ea79cSHeinrich Kuhn 224009f43d5SZerun Fu /* Configure the port speed and the auto-negotiation mode. */ 225009f43d5SZerun Fu ret = nfp_net_speed_configure(dev, net_hw); 226009f43d5SZerun Fu if (ret < 0) { 227009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set the speed and auto-negotiation mode."); 228009f43d5SZerun Fu return ret; 229009f43d5SZerun Fu } 230009f43d5SZerun Fu 23140688372SChaoyong He /* Check and configure queue intr-vector mapping */ 232646ea79cSHeinrich Kuhn if (dev->data->dev_conf.intr_conf.rxq != 0) { 233968ec1c3SChaoyong He if (app_fw_nic->multiport) { 234646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt is not supported " 235646ea79cSHeinrich Kuhn "with NFP multiport PF"); 236646ea79cSHeinrich Kuhn return -EINVAL; 237646ea79cSHeinrich Kuhn } 238b0c496abSChaoyong He 239f4d24fe9SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 240646ea79cSHeinrich Kuhn /* 241646ea79cSHeinrich Kuhn * Better not to share LSC with RX interrupts. 24240688372SChaoyong He * Unregistering LSC interrupt handler. 243646ea79cSHeinrich Kuhn */ 244e7978635SChaoyong He rte_intr_callback_unregister(intr_handle, 245646ea79cSHeinrich Kuhn nfp_net_dev_interrupt_handler, (void *)dev); 246646ea79cSHeinrich Kuhn 247646ea79cSHeinrich Kuhn if (dev->data->nb_rx_queues > 1) { 248646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt only " 249646ea79cSHeinrich Kuhn "supports 1 queue with UIO"); 250646ea79cSHeinrich Kuhn return -EIO; 251646ea79cSHeinrich Kuhn } 252646ea79cSHeinrich Kuhn } 253b0c496abSChaoyong He 254646ea79cSHeinrich Kuhn intr_vector = dev->data->nb_rx_queues; 255c01e5c0cSChaoyong He if (rte_intr_efd_enable(intr_handle, intr_vector) != 0) 256646ea79cSHeinrich Kuhn return -1; 257646ea79cSHeinrich Kuhn 258646ea79cSHeinrich Kuhn nfp_configure_rx_interrupt(dev, intr_handle); 259646ea79cSHeinrich Kuhn update = NFP_NET_CFG_UPDATE_MSIX; 260646ea79cSHeinrich Kuhn } 261646ea79cSHeinrich Kuhn 262dbad6f64SPeng Zhang /* Checking MTU set */ 26372d1dea6SChaoyong He if (dev->data->mtu > net_hw->flbufsz) { 264dbad6f64SPeng Zhang PMD_INIT_LOG(ERR, "MTU (%u) can't be larger than the current NFP_FRAME_SIZE (%u)", 26572d1dea6SChaoyong He dev->data->mtu, net_hw->flbufsz); 266dbad6f64SPeng Zhang return -ERANGE; 267dbad6f64SPeng Zhang } 268dbad6f64SPeng Zhang 269646ea79cSHeinrich Kuhn rte_intr_enable(intr_handle); 270646ea79cSHeinrich Kuhn 271646ea79cSHeinrich Kuhn new_ctrl = nfp_check_offloads(dev); 272646ea79cSHeinrich Kuhn 273646ea79cSHeinrich Kuhn /* Writing configuration parameters in the device */ 27472d1dea6SChaoyong He nfp_net_params_setup(net_hw); 275646ea79cSHeinrich Kuhn 276c4de52ecSChaoyong He rxmode = &dev->data->dev_conf.rxmode; 277c01e5c0cSChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS) != 0) { 278646ea79cSHeinrich Kuhn nfp_net_rss_config_default(dev); 279646ea79cSHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_RSS; 28072d1dea6SChaoyong He new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap); 281646ea79cSHeinrich Kuhn } 282646ea79cSHeinrich Kuhn 283646ea79cSHeinrich Kuhn /* Enable device */ 284646ea79cSHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; 285646ea79cSHeinrich Kuhn 286646ea79cSHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING; 287646ea79cSHeinrich Kuhn 288c55abf61SChaoyong He /* Enable vxlan */ 28972d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_VXLAN) != 0) { 290c55abf61SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_VXLAN; 291c55abf61SChaoyong He update |= NFP_NET_CFG_UPDATE_VXLAN; 292c925a157SFei Qin } 293c55abf61SChaoyong He 29472d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0) 295646ea79cSHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; 296646ea79cSHeinrich Kuhn 29772d1dea6SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) 298646ea79cSHeinrich Kuhn return -EIO; 299646ea79cSHeinrich Kuhn 3001e80c074SChaoyong He hw->ctrl = new_ctrl; 3011e80c074SChaoyong He 3022e7c3612SQin Ke /* Enable packet type offload by extend ctrl word1. */ 30372d1dea6SChaoyong He cap_extend = hw->cap_ext; 3042e7c3612SQin Ke if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0) 3052e7c3612SQin Ke ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE; 3062e7c3612SQin Ke 30754713740SChang Miao if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) 3089177c800SChaoyong He ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC | 3099177c800SChaoyong He NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP | 3109177c800SChaoyong He NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP; 31154713740SChang Miao 3128153bc6fSChaoyong He /* Enable flow steer by extend ctrl word1. */ 3138153bc6fSChaoyong He if ((cap_extend & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) 3148153bc6fSChaoyong He ctrl_extend |= NFP_NET_CFG_CTRL_FLOW_STEER; 3158153bc6fSChaoyong He 3162e7c3612SQin Ke update = NFP_NET_CFG_UPDATE_GEN; 31772d1dea6SChaoyong He if (nfp_ext_reconfig(hw, ctrl_extend, update) != 0) 3182e7c3612SQin Ke return -EIO; 3192e7c3612SQin Ke 32072d1dea6SChaoyong He hw->ctrl_ext = ctrl_extend; 321b4b6988aSChaoyong He 322646ea79cSHeinrich Kuhn /* 323646ea79cSHeinrich Kuhn * Allocating rte mbufs for configured rx queues. 32440688372SChaoyong He * This requires queues being enabled before. 325646ea79cSHeinrich Kuhn */ 326c01e5c0cSChaoyong He if (nfp_net_rx_freelist_setup(dev) != 0) { 327646ea79cSHeinrich Kuhn ret = -ENOMEM; 328646ea79cSHeinrich Kuhn goto error; 329646ea79cSHeinrich Kuhn } 330646ea79cSHeinrich Kuhn 331646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 332acb6bebfSChaoyong He cpp = net_hw->cpp; 333646ea79cSHeinrich Kuhn else 334acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 335acb6bebfSChaoyong He 336acb6bebfSChaoyong He /* Configure the physical port up */ 337acb6bebfSChaoyong He nfp_eth_set_configured(cpp, net_hw->nfp_idx, 1); 338646ea79cSHeinrich Kuhn 339c46216e7SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 340c46216e7SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 341c46216e7SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 342c46216e7SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 343c46216e7SJie Hai 344646ea79cSHeinrich Kuhn return 0; 345646ea79cSHeinrich Kuhn 346646ea79cSHeinrich Kuhn error: 347646ea79cSHeinrich Kuhn /* 348646ea79cSHeinrich Kuhn * An error returned by this function should mean the app 349646ea79cSHeinrich Kuhn * exiting and then the system releasing all the memory 350646ea79cSHeinrich Kuhn * allocated even memory coming from hugepages. 351646ea79cSHeinrich Kuhn * 352646ea79cSHeinrich Kuhn * The device could be enabled at this point with some queues 353646ea79cSHeinrich Kuhn * ready for getting packets. This is true if the call to 354646ea79cSHeinrich Kuhn * nfp_net_rx_freelist_setup() succeeds for some queues but 355646ea79cSHeinrich Kuhn * fails for subsequent queues. 356646ea79cSHeinrich Kuhn * 357646ea79cSHeinrich Kuhn * This should make the app exiting but better if we tell the 358646ea79cSHeinrich Kuhn * device first. 359646ea79cSHeinrich Kuhn */ 360646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 361646ea79cSHeinrich Kuhn 362646ea79cSHeinrich Kuhn return ret; 363646ea79cSHeinrich Kuhn } 364646ea79cSHeinrich Kuhn 365646ea79cSHeinrich Kuhn /* Set the link up. */ 366646ea79cSHeinrich Kuhn static int 367646ea79cSHeinrich Kuhn nfp_net_set_link_up(struct rte_eth_dev *dev) 368646ea79cSHeinrich Kuhn { 369acb6bebfSChaoyong He struct nfp_cpp *cpp; 370646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 371646ea79cSHeinrich Kuhn 3729d723baaSChaoyong He hw = dev->data->dev_private; 373646ea79cSHeinrich Kuhn 374646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 375acb6bebfSChaoyong He cpp = hw->cpp; 376646ea79cSHeinrich Kuhn else 377acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 378acb6bebfSChaoyong He 379acb6bebfSChaoyong He return nfp_eth_set_configured(cpp, hw->nfp_idx, 1); 380646ea79cSHeinrich Kuhn } 381646ea79cSHeinrich Kuhn 382646ea79cSHeinrich Kuhn /* Set the link down. */ 383646ea79cSHeinrich Kuhn static int 384646ea79cSHeinrich Kuhn nfp_net_set_link_down(struct rte_eth_dev *dev) 385646ea79cSHeinrich Kuhn { 386acb6bebfSChaoyong He struct nfp_cpp *cpp; 387646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 388646ea79cSHeinrich Kuhn 3899d723baaSChaoyong He hw = dev->data->dev_private; 390646ea79cSHeinrich Kuhn 391646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 392acb6bebfSChaoyong He cpp = hw->cpp; 393646ea79cSHeinrich Kuhn else 394acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 395acb6bebfSChaoyong He 396acb6bebfSChaoyong He return nfp_eth_set_configured(cpp, hw->nfp_idx, 0); 397646ea79cSHeinrich Kuhn } 398646ea79cSHeinrich Kuhn 3993b00109dSPeng Zhang static uint8_t 4003b00109dSPeng Zhang nfp_function_id_get(const struct nfp_pf_dev *pf_dev, 4013b00109dSPeng Zhang uint8_t phy_port) 4023b00109dSPeng Zhang { 4033b00109dSPeng Zhang if (pf_dev->multi_pf.enabled) 4043b00109dSPeng Zhang return pf_dev->multi_pf.function_id; 4053b00109dSPeng Zhang 4063b00109dSPeng Zhang return phy_port; 4073b00109dSPeng Zhang } 4083b00109dSPeng Zhang 4098ba461d1SPeng Zhang static void 4108ba461d1SPeng Zhang nfp_net_beat_timer(void *arg) 4118ba461d1SPeng Zhang { 4128ba461d1SPeng Zhang uint64_t cur_sec; 4138ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf = arg; 4148ba461d1SPeng Zhang 4158ba461d1SPeng Zhang cur_sec = rte_rdtsc(); 4168ba461d1SPeng Zhang nn_writeq(cur_sec, multi_pf->beat_addr + NFP_BEAT_OFFSET(multi_pf->function_id)); 4178ba461d1SPeng Zhang 4188ba461d1SPeng Zhang /* Beat once per second. */ 4198ba461d1SPeng Zhang if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer, 4208ba461d1SPeng Zhang (void *)multi_pf) < 0) { 4218ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Error setting alarm"); 4228ba461d1SPeng Zhang } 4238ba461d1SPeng Zhang } 4248ba461d1SPeng Zhang 4258ba461d1SPeng Zhang static int 4268ba461d1SPeng Zhang nfp_net_keepalive_init(struct nfp_cpp *cpp, 4278ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 4288ba461d1SPeng Zhang { 4298ba461d1SPeng Zhang uint8_t *base; 4308ba461d1SPeng Zhang uint64_t addr; 4318ba461d1SPeng Zhang uint32_t size; 4328ba461d1SPeng Zhang uint32_t cpp_id; 4338ba461d1SPeng Zhang struct nfp_resource *res; 4348ba461d1SPeng Zhang 4358ba461d1SPeng Zhang res = nfp_resource_acquire(cpp, NFP_RESOURCE_KEEPALIVE); 4368ba461d1SPeng Zhang if (res == NULL) 4378ba461d1SPeng Zhang return -EIO; 4388ba461d1SPeng Zhang 4398ba461d1SPeng Zhang cpp_id = nfp_resource_cpp_id(res); 4408ba461d1SPeng Zhang addr = nfp_resource_address(res); 4418ba461d1SPeng Zhang size = nfp_resource_size(res); 4428ba461d1SPeng Zhang 4438ba461d1SPeng Zhang nfp_resource_release(res); 4448ba461d1SPeng Zhang 4458ba461d1SPeng Zhang /* Allocate a fixed area for keepalive. */ 4468ba461d1SPeng Zhang base = nfp_cpp_map_area(cpp, cpp_id, addr, size, &multi_pf->beat_area); 4478ba461d1SPeng Zhang if (base == NULL) { 4488ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Failed to map area for keepalive."); 4498ba461d1SPeng Zhang return -EIO; 4508ba461d1SPeng Zhang } 4518ba461d1SPeng Zhang 4528ba461d1SPeng Zhang multi_pf->beat_addr = base; 4538ba461d1SPeng Zhang 4548ba461d1SPeng Zhang return 0; 4558ba461d1SPeng Zhang } 4568ba461d1SPeng Zhang 4578ba461d1SPeng Zhang static void 4588ba461d1SPeng Zhang nfp_net_keepalive_uninit(struct nfp_multi_pf *multi_pf) 4598ba461d1SPeng Zhang { 4608ba461d1SPeng Zhang nfp_cpp_area_release_free(multi_pf->beat_area); 4618ba461d1SPeng Zhang } 4628ba461d1SPeng Zhang 4638ba461d1SPeng Zhang static int 4648ba461d1SPeng Zhang nfp_net_keepalive_start(struct nfp_multi_pf *multi_pf) 4658ba461d1SPeng Zhang { 4668ba461d1SPeng Zhang if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer, 4678ba461d1SPeng Zhang (void *)multi_pf) < 0) { 4688ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Error setting alarm"); 4698ba461d1SPeng Zhang return -EIO; 4708ba461d1SPeng Zhang } 4718ba461d1SPeng Zhang 4728ba461d1SPeng Zhang return 0; 4738ba461d1SPeng Zhang } 4748ba461d1SPeng Zhang 4758ba461d1SPeng Zhang static void 476b67a7b40SPeng Zhang nfp_net_keepalive_clear(uint8_t *beat_addr, 477b67a7b40SPeng Zhang uint8_t function_id) 478b67a7b40SPeng Zhang { 479b67a7b40SPeng Zhang nn_writeq(0, beat_addr + NFP_BEAT_OFFSET(function_id)); 480b67a7b40SPeng Zhang } 481b67a7b40SPeng Zhang 482b67a7b40SPeng Zhang static void 483b67a7b40SPeng Zhang nfp_net_keepalive_clear_others(const struct nfp_dev_info *dev_info, 484b67a7b40SPeng Zhang struct nfp_multi_pf *multi_pf) 485b67a7b40SPeng Zhang { 486b67a7b40SPeng Zhang uint8_t port_num; 487b67a7b40SPeng Zhang 488b67a7b40SPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 489b67a7b40SPeng Zhang if (port_num == multi_pf->function_id) 490b67a7b40SPeng Zhang continue; 491b67a7b40SPeng Zhang 492b67a7b40SPeng Zhang nfp_net_keepalive_clear(multi_pf->beat_addr, port_num); 493b67a7b40SPeng Zhang } 494b67a7b40SPeng Zhang } 495b67a7b40SPeng Zhang 496b67a7b40SPeng Zhang static void 4978ba461d1SPeng Zhang nfp_net_keepalive_stop(struct nfp_multi_pf *multi_pf) 4988ba461d1SPeng Zhang { 4998ba461d1SPeng Zhang /* Cancel keepalive for multiple PF setup */ 5008ba461d1SPeng Zhang rte_eal_alarm_cancel(nfp_net_beat_timer, (void *)multi_pf); 5018ba461d1SPeng Zhang } 5028ba461d1SPeng Zhang 5038b8f116bSChaoyong He static void 5048b8f116bSChaoyong He nfp_net_uninit(struct rte_eth_dev *eth_dev) 5058b8f116bSChaoyong He { 5068b8f116bSChaoyong He struct nfp_net_hw *net_hw; 5078b8f116bSChaoyong He 5088b8f116bSChaoyong He net_hw = eth_dev->data->dev_private; 5098153bc6fSChaoyong He 5108153bc6fSChaoyong He if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) 5118153bc6fSChaoyong He nfp_net_flow_priv_uninit(net_hw->pf_dev, net_hw->idx); 5128153bc6fSChaoyong He 5138b8f116bSChaoyong He rte_free(net_hw->eth_xstats_base); 5148b8f116bSChaoyong He nfp_ipsec_uninit(eth_dev); 5158b8f116bSChaoyong He if (net_hw->mac_stats_area != NULL) 5168b8f116bSChaoyong He nfp_cpp_area_release_free(net_hw->mac_stats_area); 5178b8f116bSChaoyong He } 5188b8f116bSChaoyong He 51966d5f53dSChaoyong He static void 52066d5f53dSChaoyong He nfp_cleanup_port_app_fw_nic(struct nfp_pf_dev *pf_dev, 52166d5f53dSChaoyong He uint8_t id) 52266d5f53dSChaoyong He { 52366d5f53dSChaoyong He struct rte_eth_dev *eth_dev; 52466d5f53dSChaoyong He struct nfp_app_fw_nic *app_fw_nic; 52566d5f53dSChaoyong He 52666d5f53dSChaoyong He app_fw_nic = pf_dev->app_fw_priv; 52766d5f53dSChaoyong He if (app_fw_nic->ports[id] != NULL) { 52866d5f53dSChaoyong He eth_dev = app_fw_nic->ports[id]->eth_dev; 52966d5f53dSChaoyong He if (eth_dev != NULL) 53066d5f53dSChaoyong He nfp_net_uninit(eth_dev); 53166d5f53dSChaoyong He 53266d5f53dSChaoyong He app_fw_nic->ports[id] = NULL; 53366d5f53dSChaoyong He } 53466d5f53dSChaoyong He } 53566d5f53dSChaoyong He 53666d5f53dSChaoyong He static void 53766d5f53dSChaoyong He nfp_uninit_app_fw_nic(struct nfp_pf_dev *pf_dev) 53866d5f53dSChaoyong He { 53966d5f53dSChaoyong He nfp_cpp_area_release_free(pf_dev->ctrl_area); 54066d5f53dSChaoyong He rte_free(pf_dev->app_fw_priv); 54166d5f53dSChaoyong He } 54266d5f53dSChaoyong He 54366d5f53dSChaoyong He void 54466d5f53dSChaoyong He nfp_pf_uninit(struct nfp_pf_dev *pf_dev) 54566d5f53dSChaoyong He { 54666d5f53dSChaoyong He nfp_cpp_area_release_free(pf_dev->qc_area); 54766d5f53dSChaoyong He free(pf_dev->sym_tbl); 54866d5f53dSChaoyong He if (pf_dev->multi_pf.enabled) { 54966d5f53dSChaoyong He nfp_net_keepalive_stop(&pf_dev->multi_pf); 550b67a7b40SPeng Zhang nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id); 55166d5f53dSChaoyong He nfp_net_keepalive_uninit(&pf_dev->multi_pf); 55266d5f53dSChaoyong He } 55366d5f53dSChaoyong He free(pf_dev->nfp_eth_table); 55466d5f53dSChaoyong He free(pf_dev->hwinfo); 55566d5f53dSChaoyong He nfp_cpp_free(pf_dev->cpp); 5566b4273a0SLong Wu nfp_sync_free(pf_dev->sync); 55766d5f53dSChaoyong He rte_free(pf_dev); 55866d5f53dSChaoyong He } 55966d5f53dSChaoyong He 56066d5f53dSChaoyong He static int 56166d5f53dSChaoyong He nfp_pf_secondary_uninit(struct nfp_pf_dev *pf_dev) 56266d5f53dSChaoyong He { 56366d5f53dSChaoyong He free(pf_dev->sym_tbl); 56466d5f53dSChaoyong He nfp_cpp_free(pf_dev->cpp); 5656b4273a0SLong Wu nfp_sync_free(pf_dev->sync); 56666d5f53dSChaoyong He rte_free(pf_dev); 56766d5f53dSChaoyong He 56866d5f53dSChaoyong He return 0; 56966d5f53dSChaoyong He } 57066d5f53dSChaoyong He 571646ea79cSHeinrich Kuhn /* Reset and stop device. The device can not be restarted. */ 572646ea79cSHeinrich Kuhn static int 573646ea79cSHeinrich Kuhn nfp_net_close(struct rte_eth_dev *dev) 574646ea79cSHeinrich Kuhn { 5758ceb85c3SChaoyong He uint8_t i; 5763b00109dSPeng Zhang uint8_t id; 57749952141SChaoyong He struct nfp_net_hw *hw; 57849952141SChaoyong He struct nfp_pf_dev *pf_dev; 57949952141SChaoyong He struct rte_pci_device *pci_dev; 58049952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 581646ea79cSHeinrich Kuhn 58266d5f53dSChaoyong He /* 58366d5f53dSChaoyong He * In secondary process, a released eth device can be found by its name 58466d5f53dSChaoyong He * in shared memory. 58566d5f53dSChaoyong He * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the 58666d5f53dSChaoyong He * eth device has been released. 58766d5f53dSChaoyong He */ 58866d5f53dSChaoyong He if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 58966d5f53dSChaoyong He if (dev->state == RTE_ETH_DEV_UNUSED) 590646ea79cSHeinrich Kuhn return 0; 591646ea79cSHeinrich Kuhn 59266d5f53dSChaoyong He nfp_pf_secondary_uninit(dev->process_private); 59366d5f53dSChaoyong He return 0; 59466d5f53dSChaoyong He } 59566d5f53dSChaoyong He 5969d723baaSChaoyong He hw = dev->data->dev_private; 59765f6915dSChaoyong He pf_dev = hw->pf_dev; 598646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(dev); 599968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 600646ea79cSHeinrich Kuhn 601646ea79cSHeinrich Kuhn /* 602646ea79cSHeinrich Kuhn * We assume that the DPDK application is stopping all the 603646ea79cSHeinrich Kuhn * threads/queues before calling the device close function. 604646ea79cSHeinrich Kuhn */ 605646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 606646ea79cSHeinrich Kuhn 607646ea79cSHeinrich Kuhn /* Clear queues */ 6081c8d02bbSJin Liu nfp_net_close_tx_queue(dev); 6091c8d02bbSJin Liu nfp_net_close_rx_queue(dev); 610646ea79cSHeinrich Kuhn 611851f03e1SHeinrich Kuhn /* Cancel possible impending LSC work here before releasing the port */ 612f4d24fe9SChaoyong He rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev); 613851f03e1SHeinrich Kuhn 614646ea79cSHeinrich Kuhn /* Only free PF resources after all physical ports have been closed */ 615646ea79cSHeinrich Kuhn /* Mark this port as unused and free device priv resources */ 616f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_LSC, 0xff); 61766d5f53dSChaoyong He 61866d5f53dSChaoyong He if (pf_dev->app_fw_id != NFP_APP_FW_CORE_NIC) 61966d5f53dSChaoyong He return -EINVAL; 62066d5f53dSChaoyong He 62166d5f53dSChaoyong He nfp_cleanup_port_app_fw_nic(pf_dev, hw->idx); 622646ea79cSHeinrich Kuhn 623968ec1c3SChaoyong He for (i = 0; i < app_fw_nic->total_phyports; i++) { 6243b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 6253b00109dSPeng Zhang 626646ea79cSHeinrich Kuhn /* Check to see if ports are still in use */ 6273b00109dSPeng Zhang if (app_fw_nic->ports[id] != NULL) 628646ea79cSHeinrich Kuhn return 0; 629646ea79cSHeinrich Kuhn } 630646ea79cSHeinrich Kuhn 63166d5f53dSChaoyong He /* Enable in nfp_net_start() */ 632d61138d4SHarman Kalra rte_intr_disable(pci_dev->intr_handle); 633646ea79cSHeinrich Kuhn 63466d5f53dSChaoyong He /* Register in nfp_net_init() */ 635d61138d4SHarman Kalra rte_intr_callback_unregister(pci_dev->intr_handle, 636a6189a67SJin Liu nfp_net_dev_interrupt_handler, (void *)dev); 637646ea79cSHeinrich Kuhn 63866d5f53dSChaoyong He nfp_uninit_app_fw_nic(pf_dev); 63966d5f53dSChaoyong He nfp_pf_uninit(pf_dev); 64066d5f53dSChaoyong He 641646ea79cSHeinrich Kuhn return 0; 642646ea79cSHeinrich Kuhn } 643646ea79cSHeinrich Kuhn 644c55abf61SChaoyong He static int 645c55abf61SChaoyong He nfp_net_find_vxlan_idx(struct nfp_net_hw *hw, 646c55abf61SChaoyong He uint16_t port, 647c55abf61SChaoyong He uint32_t *idx) 648c55abf61SChaoyong He { 649c55abf61SChaoyong He uint32_t i; 650c55abf61SChaoyong He int free_idx = -1; 651c55abf61SChaoyong He 652c55abf61SChaoyong He for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i++) { 653c55abf61SChaoyong He if (hw->vxlan_ports[i] == port) { 654c55abf61SChaoyong He free_idx = i; 655c55abf61SChaoyong He break; 656c55abf61SChaoyong He } 657c55abf61SChaoyong He 658c55abf61SChaoyong He if (hw->vxlan_usecnt[i] == 0) { 659c55abf61SChaoyong He free_idx = i; 660c55abf61SChaoyong He break; 661c55abf61SChaoyong He } 662c55abf61SChaoyong He } 663c55abf61SChaoyong He 664c55abf61SChaoyong He if (free_idx == -1) 665c55abf61SChaoyong He return -EINVAL; 666c55abf61SChaoyong He 667c55abf61SChaoyong He *idx = free_idx; 668c55abf61SChaoyong He 669c55abf61SChaoyong He return 0; 670c55abf61SChaoyong He } 671c55abf61SChaoyong He 672c55abf61SChaoyong He static int 673c55abf61SChaoyong He nfp_udp_tunnel_port_add(struct rte_eth_dev *dev, 674c55abf61SChaoyong He struct rte_eth_udp_tunnel *tunnel_udp) 675c55abf61SChaoyong He { 676c55abf61SChaoyong He int ret; 677c55abf61SChaoyong He uint32_t idx; 678c55abf61SChaoyong He uint16_t vxlan_port; 679c55abf61SChaoyong He struct nfp_net_hw *hw; 680c55abf61SChaoyong He enum rte_eth_tunnel_type tnl_type; 681c55abf61SChaoyong He 6829d723baaSChaoyong He hw = dev->data->dev_private; 683c55abf61SChaoyong He vxlan_port = tunnel_udp->udp_port; 684c55abf61SChaoyong He tnl_type = tunnel_udp->prot_type; 685c55abf61SChaoyong He 686c55abf61SChaoyong He if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) { 687c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Not VXLAN tunnel"); 688c55abf61SChaoyong He return -ENOTSUP; 689c55abf61SChaoyong He } 690c55abf61SChaoyong He 691c55abf61SChaoyong He ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx); 692c55abf61SChaoyong He if (ret != 0) { 693c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed find valid vxlan idx"); 694c55abf61SChaoyong He return -EINVAL; 695c55abf61SChaoyong He } 696c55abf61SChaoyong He 697c55abf61SChaoyong He if (hw->vxlan_usecnt[idx] == 0) { 698c55abf61SChaoyong He ret = nfp_net_set_vxlan_port(hw, idx, vxlan_port); 699c55abf61SChaoyong He if (ret != 0) { 700c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed set vxlan port"); 701c55abf61SChaoyong He return -EINVAL; 702c55abf61SChaoyong He } 703c55abf61SChaoyong He } 704c55abf61SChaoyong He 705c55abf61SChaoyong He hw->vxlan_usecnt[idx]++; 706c55abf61SChaoyong He 707c55abf61SChaoyong He return 0; 708c55abf61SChaoyong He } 709c55abf61SChaoyong He 710c55abf61SChaoyong He static int 711c55abf61SChaoyong He nfp_udp_tunnel_port_del(struct rte_eth_dev *dev, 712c55abf61SChaoyong He struct rte_eth_udp_tunnel *tunnel_udp) 713c55abf61SChaoyong He { 714c55abf61SChaoyong He int ret; 715c55abf61SChaoyong He uint32_t idx; 716c55abf61SChaoyong He uint16_t vxlan_port; 717c55abf61SChaoyong He struct nfp_net_hw *hw; 718c55abf61SChaoyong He enum rte_eth_tunnel_type tnl_type; 719c55abf61SChaoyong He 7209d723baaSChaoyong He hw = dev->data->dev_private; 721c55abf61SChaoyong He vxlan_port = tunnel_udp->udp_port; 722c55abf61SChaoyong He tnl_type = tunnel_udp->prot_type; 723c55abf61SChaoyong He 724c55abf61SChaoyong He if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) { 725c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Not VXLAN tunnel"); 726c55abf61SChaoyong He return -ENOTSUP; 727c55abf61SChaoyong He } 728c55abf61SChaoyong He 729c55abf61SChaoyong He ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx); 730c55abf61SChaoyong He if (ret != 0 || hw->vxlan_usecnt[idx] == 0) { 731c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed find valid vxlan idx"); 732c55abf61SChaoyong He return -EINVAL; 733c55abf61SChaoyong He } 734c55abf61SChaoyong He 735c55abf61SChaoyong He hw->vxlan_usecnt[idx]--; 736c55abf61SChaoyong He 737c55abf61SChaoyong He if (hw->vxlan_usecnt[idx] == 0) { 738c55abf61SChaoyong He ret = nfp_net_set_vxlan_port(hw, idx, 0); 739c55abf61SChaoyong He if (ret != 0) { 740c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed set vxlan port"); 741c55abf61SChaoyong He return -EINVAL; 742c55abf61SChaoyong He } 743c55abf61SChaoyong He } 744c55abf61SChaoyong He 745c55abf61SChaoyong He return 0; 746c55abf61SChaoyong He } 747c55abf61SChaoyong He 748646ea79cSHeinrich Kuhn /* Initialise and register driver with DPDK Application */ 7498d961320SJin Liu static const struct eth_dev_ops nfp_net_eth_dev_ops = { 750646ea79cSHeinrich Kuhn .dev_configure = nfp_net_configure, 751646ea79cSHeinrich Kuhn .dev_start = nfp_net_start, 752646ea79cSHeinrich Kuhn .dev_stop = nfp_net_stop, 753646ea79cSHeinrich Kuhn .dev_set_link_up = nfp_net_set_link_up, 754646ea79cSHeinrich Kuhn .dev_set_link_down = nfp_net_set_link_down, 755646ea79cSHeinrich Kuhn .dev_close = nfp_net_close, 756646ea79cSHeinrich Kuhn .promiscuous_enable = nfp_net_promisc_enable, 757646ea79cSHeinrich Kuhn .promiscuous_disable = nfp_net_promisc_disable, 7584a86c36bSQin Ke .allmulticast_enable = nfp_net_allmulticast_enable, 7594a86c36bSQin Ke .allmulticast_disable = nfp_net_allmulticast_disable, 760646ea79cSHeinrich Kuhn .link_update = nfp_net_link_update, 761646ea79cSHeinrich Kuhn .stats_get = nfp_net_stats_get, 762646ea79cSHeinrich Kuhn .stats_reset = nfp_net_stats_reset, 763f26e8239SJames Hershaw .xstats_get = nfp_net_xstats_get, 764f26e8239SJames Hershaw .xstats_reset = nfp_net_xstats_reset, 765f26e8239SJames Hershaw .xstats_get_names = nfp_net_xstats_get_names, 766f26e8239SJames Hershaw .xstats_get_by_id = nfp_net_xstats_get_by_id, 767f26e8239SJames Hershaw .xstats_get_names_by_id = nfp_net_xstats_get_names_by_id, 768646ea79cSHeinrich Kuhn .dev_infos_get = nfp_net_infos_get, 769646ea79cSHeinrich Kuhn .dev_supported_ptypes_get = nfp_net_supported_ptypes_get, 770646ea79cSHeinrich Kuhn .mtu_set = nfp_net_dev_mtu_set, 7710a94d6bcSJin Liu .mac_addr_set = nfp_net_set_mac_addr, 772646ea79cSHeinrich Kuhn .vlan_offload_set = nfp_net_vlan_offload_set, 773646ea79cSHeinrich Kuhn .reta_update = nfp_net_reta_update, 774646ea79cSHeinrich Kuhn .reta_query = nfp_net_reta_query, 775646ea79cSHeinrich Kuhn .rss_hash_update = nfp_net_rss_hash_update, 776646ea79cSHeinrich Kuhn .rss_hash_conf_get = nfp_net_rss_hash_conf_get, 777646ea79cSHeinrich Kuhn .rx_queue_setup = nfp_net_rx_queue_setup, 778646ea79cSHeinrich Kuhn .rx_queue_release = nfp_net_rx_queue_release, 7798d961320SJin Liu .tx_queue_setup = nfp_net_tx_queue_setup, 78052ddc4c2SJin Liu .tx_queue_release = nfp_net_tx_queue_release, 78152ddc4c2SJin Liu .rx_queue_intr_enable = nfp_rx_queue_intr_enable, 78252ddc4c2SJin Liu .rx_queue_intr_disable = nfp_rx_queue_intr_disable, 783c55abf61SChaoyong He .udp_tunnel_port_add = nfp_udp_tunnel_port_add, 784c55abf61SChaoyong He .udp_tunnel_port_del = nfp_udp_tunnel_port_del, 785128c8ad9SChaoyong He .fw_version_get = nfp_net_firmware_version_get, 78651d15e82SZerun Fu .flow_ctrl_get = nfp_net_flow_ctrl_get, 78768aa3537SZerun Fu .flow_ctrl_set = nfp_net_flow_ctrl_set, 7880b9079d2SChaoyong He .flow_ops_get = nfp_net_flow_ops_get, 7890786add9SZerun Fu .fec_get_capability = nfp_net_fec_get_capability, 790c6835a32SZerun Fu .fec_get = nfp_net_fec_get, 79137bd1b84SZerun Fu .fec_set = nfp_net_fec_set, 79252ddc4c2SJin Liu }; 79352ddc4c2SJin Liu 794ee8ca64eSChaoyong He static inline void 795ee8ca64eSChaoyong He nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, 796ee8ca64eSChaoyong He struct rte_eth_dev *eth_dev) 797266470b2SJin Liu { 798ee8ca64eSChaoyong He if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 799ee8ca64eSChaoyong He eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts; 800ee8ca64eSChaoyong He else 801ee8ca64eSChaoyong He eth_dev->tx_pkt_burst = nfp_net_nfdk_xmit_pkts; 802266470b2SJin Liu 8038d961320SJin Liu eth_dev->dev_ops = &nfp_net_eth_dev_ops; 804266470b2SJin Liu eth_dev->rx_queue_count = nfp_net_rx_queue_count; 805266470b2SJin Liu eth_dev->rx_pkt_burst = &nfp_net_recv_pkts; 806266470b2SJin Liu } 807266470b2SJin Liu 808646ea79cSHeinrich Kuhn static int 809646ea79cSHeinrich Kuhn nfp_net_init(struct rte_eth_dev *eth_dev) 810646ea79cSHeinrich Kuhn { 81149952141SChaoyong He int err; 81249952141SChaoyong He uint16_t port; 8130314a8ffSChaoyong He uint64_t rx_base; 8140314a8ffSChaoyong He uint64_t tx_base; 8154a9bb682SChaoyong He struct nfp_hw *hw; 8164a9bb682SChaoyong He struct nfp_net_hw *net_hw; 81749952141SChaoyong He struct nfp_pf_dev *pf_dev; 81849952141SChaoyong He struct rte_pci_device *pci_dev; 81949952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 820646ea79cSHeinrich Kuhn 821646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 82265f6915dSChaoyong He net_hw = eth_dev->data->dev_private; 823646ea79cSHeinrich Kuhn 824646ea79cSHeinrich Kuhn /* Use backpointer here to the PF of this eth_dev */ 82565f6915dSChaoyong He pf_dev = net_hw->pf_dev; 826646ea79cSHeinrich Kuhn 827968ec1c3SChaoyong He /* Use backpointer to the CoreNIC app struct */ 828968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 829968ec1c3SChaoyong He 830646ea79cSHeinrich Kuhn port = ((struct nfp_net_hw *)eth_dev->data->dev_private)->idx; 8318ceb85c3SChaoyong He if (port > 7) { 832646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "Port value is wrong"); 833646ea79cSHeinrich Kuhn return -ENODEV; 834646ea79cSHeinrich Kuhn } 835646ea79cSHeinrich Kuhn 8364a9bb682SChaoyong He hw = &net_hw->super; 837646ea79cSHeinrich Kuhn 838030b2b19SChaoyong He PMD_INIT_LOG(DEBUG, "Working with physical port number: %hu, " 8394a9bb682SChaoyong He "NFP internal port number: %d", port, net_hw->nfp_idx); 840646ea79cSHeinrich Kuhn 841646ea79cSHeinrich Kuhn rte_eth_copy_pci_info(eth_dev, pci_dev); 842646ea79cSHeinrich Kuhn 8438ad2cc8fSPeng Zhang if (port == 0 || pf_dev->multi_pf.enabled) { 844f26e8239SJames Hershaw uint32_t min_size; 845f26e8239SJames Hershaw 8464a9bb682SChaoyong He hw->ctrl_bar = pf_dev->ctrl_bar; 8474a9bb682SChaoyong He min_size = NFP_MAC_STATS_SIZE * net_hw->pf_dev->nfp_eth_table->max_index; 8484a9bb682SChaoyong He net_hw->mac_stats_bar = nfp_rtsym_map(net_hw->pf_dev->sym_tbl, "_mac_stats", 8494a9bb682SChaoyong He min_size, &net_hw->mac_stats_area); 8504a9bb682SChaoyong He if (net_hw->mac_stats_bar == NULL) { 851f26e8239SJames Hershaw PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for _mac_stats_bar"); 852f26e8239SJames Hershaw return -EIO; 853f26e8239SJames Hershaw } 854b0c496abSChaoyong He 8554a9bb682SChaoyong He net_hw->mac_stats = net_hw->mac_stats_bar; 856646ea79cSHeinrich Kuhn } else { 857a6189a67SJin Liu /* Use port offset in pf ctrl_bar for this ports control bar */ 8584a9bb682SChaoyong He hw->ctrl_bar = pf_dev->ctrl_bar + (port * NFP_NET_CFG_BAR_SZ); 8594a9bb682SChaoyong He net_hw->mac_stats = app_fw_nic->ports[0]->mac_stats_bar + 8604a9bb682SChaoyong He (net_hw->nfp_idx * NFP_MAC_STATS_SIZE); 861646ea79cSHeinrich Kuhn } 862646ea79cSHeinrich Kuhn 8634a9bb682SChaoyong He PMD_INIT_LOG(DEBUG, "ctrl bar: %p", hw->ctrl_bar); 8644a9bb682SChaoyong He PMD_INIT_LOG(DEBUG, "MAC stats: %p", net_hw->mac_stats); 865646ea79cSHeinrich Kuhn 8664a9bb682SChaoyong He err = nfp_net_common_init(pci_dev, net_hw); 867cd4397ebSPeng Zhang if (err != 0) 86836994566SChaoyong He goto free_area; 869fd392f84SPeng Zhang 870eecdfcc1SShihong Wang err = nfp_net_tlv_caps_parse(eth_dev); 871eecdfcc1SShihong Wang if (err != 0) { 872eecdfcc1SShihong Wang PMD_INIT_LOG(ERR, "Failed to parser TLV caps"); 873eecdfcc1SShihong Wang return err; 87436994566SChaoyong He goto free_area; 875eecdfcc1SShihong Wang } 876eecdfcc1SShihong Wang 87754713740SChang Miao err = nfp_ipsec_init(eth_dev); 87854713740SChang Miao if (err != 0) { 87954713740SChang Miao PMD_INIT_LOG(ERR, "Failed to init IPsec module"); 88036994566SChaoyong He goto free_area; 88154713740SChang Miao } 88254713740SChang Miao 8834a9bb682SChaoyong He nfp_net_ethdev_ops_mount(net_hw, eth_dev); 884266470b2SJin Liu 8854a9bb682SChaoyong He net_hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) * 886f26e8239SJames Hershaw nfp_net_xstats_size(eth_dev), 0); 8874a9bb682SChaoyong He if (net_hw->eth_xstats_base == NULL) { 888f26e8239SJames Hershaw PMD_INIT_LOG(ERR, "no memory for xstats base values on device %s!", 889f26e8239SJames Hershaw pci_dev->device.name); 89036994566SChaoyong He err = -ENOMEM; 89136994566SChaoyong He goto ipsec_exit; 892f26e8239SJames Hershaw } 893f26e8239SJames Hershaw 894646ea79cSHeinrich Kuhn /* Work out where in the BAR the queues start. */ 8954a9bb682SChaoyong He tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 8964a9bb682SChaoyong He rx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ); 897646ea79cSHeinrich Kuhn 8984a9bb682SChaoyong He net_hw->tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ; 8994a9bb682SChaoyong He net_hw->rx_bar = pf_dev->qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ; 9004a9bb682SChaoyong He eth_dev->data->dev_private = net_hw; 901646ea79cSHeinrich Kuhn 902646ea79cSHeinrich Kuhn PMD_INIT_LOG(DEBUG, "ctrl_bar: %p, tx_bar: %p, rx_bar: %p", 9034a9bb682SChaoyong He hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar); 904646ea79cSHeinrich Kuhn 9054a9bb682SChaoyong He nfp_net_cfg_queue_setup(net_hw); 9064a9bb682SChaoyong He net_hw->mtu = RTE_ETHER_MTU; 907646ea79cSHeinrich Kuhn 908646ea79cSHeinrich Kuhn /* VLAN insertion is incompatible with LSOv2 */ 9094a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0) 9104a9bb682SChaoyong He hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN; 911646ea79cSHeinrich Kuhn 9124a9bb682SChaoyong He nfp_net_log_device_information(net_hw); 913646ea79cSHeinrich Kuhn 914646ea79cSHeinrich Kuhn /* Initializing spinlock for reconfigs */ 9154a9bb682SChaoyong He rte_spinlock_init(&hw->reconfig_lock); 916646ea79cSHeinrich Kuhn 917646ea79cSHeinrich Kuhn /* Allocating memory for mac addr */ 918f4d24fe9SChaoyong He eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0); 919646ea79cSHeinrich Kuhn if (eth_dev->data->mac_addrs == NULL) { 920646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Failed to space for MAC address"); 92136994566SChaoyong He err = -ENOMEM; 92236994566SChaoyong He goto xstats_free; 923646ea79cSHeinrich Kuhn } 924646ea79cSHeinrich Kuhn 925968ec1c3SChaoyong He nfp_net_pf_read_mac(app_fw_nic, port); 926503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 927646ea79cSHeinrich Kuhn 9284a9bb682SChaoyong He if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) { 929a6189a67SJin Liu PMD_INIT_LOG(INFO, "Using random mac address for port %d", port); 930646ea79cSHeinrich Kuhn /* Using random mac addresses for VFs */ 9314a9bb682SChaoyong He rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]); 932503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 933646ea79cSHeinrich Kuhn } 934646ea79cSHeinrich Kuhn 935646ea79cSHeinrich Kuhn /* Copying mac address to DPDK eth_dev struct */ 9364a9bb682SChaoyong He rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs); 937646ea79cSHeinrich Kuhn 9384a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) 939646ea79cSHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR; 940646ea79cSHeinrich Kuhn 941646ea79cSHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 942646ea79cSHeinrich Kuhn 943030b2b19SChaoyong He PMD_INIT_LOG(INFO, "port %d VendorID=%#x DeviceID=%#x " 944c2c4f87bSAman Deep Singh "mac=" RTE_ETHER_ADDR_PRT_FMT, 945646ea79cSHeinrich Kuhn eth_dev->data->port_id, pci_dev->id.vendor_id, 946646ea79cSHeinrich Kuhn pci_dev->id.device_id, 9474a9bb682SChaoyong He RTE_ETHER_ADDR_BYTES(&hw->mac_addr)); 948646ea79cSHeinrich Kuhn 949646ea79cSHeinrich Kuhn /* Registering LSC interrupt handler */ 950d61138d4SHarman Kalra rte_intr_callback_register(pci_dev->intr_handle, 951a6189a67SJin Liu nfp_net_dev_interrupt_handler, (void *)eth_dev); 952646ea79cSHeinrich Kuhn /* Telling the firmware about the LSC interrupt entry */ 9534a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); 95494d0631aSPeng Zhang /* Unmask the LSC interrupt */ 95594d0631aSPeng Zhang nfp_net_irq_unmask(eth_dev); 956646ea79cSHeinrich Kuhn /* Recording current stats counters values */ 957646ea79cSHeinrich Kuhn nfp_net_stats_reset(eth_dev); 958646ea79cSHeinrich Kuhn 9598153bc6fSChaoyong He if ((hw->cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) { 9608153bc6fSChaoyong He err = nfp_net_flow_priv_init(pf_dev, port); 9618153bc6fSChaoyong He if (err != 0) { 9628153bc6fSChaoyong He PMD_INIT_LOG(ERR, "Init net flow priv failed"); 9638153bc6fSChaoyong He goto xstats_free; 9648153bc6fSChaoyong He } 9658153bc6fSChaoyong He } 9668153bc6fSChaoyong He 967646ea79cSHeinrich Kuhn return 0; 96836994566SChaoyong He 96936994566SChaoyong He xstats_free: 97036994566SChaoyong He rte_free(net_hw->eth_xstats_base); 97136994566SChaoyong He ipsec_exit: 97236994566SChaoyong He nfp_ipsec_uninit(eth_dev); 97336994566SChaoyong He free_area: 97436994566SChaoyong He if (net_hw->mac_stats_area != NULL) 97536994566SChaoyong He nfp_cpp_area_release_free(net_hw->mac_stats_area); 97636994566SChaoyong He 97736994566SChaoyong He return err; 978646ea79cSHeinrich Kuhn } 979646ea79cSHeinrich Kuhn 980646ea79cSHeinrich Kuhn #define DEFAULT_FW_PATH "/lib/firmware/netronome" 981646ea79cSHeinrich Kuhn 982646ea79cSHeinrich Kuhn static int 983ebfb540eSPeng Zhang nfp_fw_get_name(struct rte_pci_device *dev, 984f4d24fe9SChaoyong He struct nfp_nsp *nsp, 985ebfb540eSPeng Zhang char *card, 986ebfb540eSPeng Zhang char *fw_name, 987ebfb540eSPeng Zhang size_t fw_size) 988646ea79cSHeinrich Kuhn { 98949952141SChaoyong He char serial[40]; 990ff627b74SChaoyong He uint16_t interface; 991ff627b74SChaoyong He uint32_t cpp_serial_len; 992ff627b74SChaoyong He const uint8_t *cpp_serial; 99349952141SChaoyong He struct nfp_cpp *cpp = nfp_nsp_cpp(nsp); 994ff627b74SChaoyong He 995ff627b74SChaoyong He cpp_serial_len = nfp_cpp_serial(cpp, &cpp_serial); 996ff627b74SChaoyong He if (cpp_serial_len != NFP_SERIAL_LEN) 997ff627b74SChaoyong He return -ERANGE; 998ff627b74SChaoyong He 999ff627b74SChaoyong He interface = nfp_cpp_interface(cpp); 1000646ea79cSHeinrich Kuhn 1001646ea79cSHeinrich Kuhn /* Looking for firmware file in order of priority */ 1002646ea79cSHeinrich Kuhn 1003646ea79cSHeinrich Kuhn /* First try to find a firmware image specific for this device */ 1004646ea79cSHeinrich Kuhn snprintf(serial, sizeof(serial), 1005646ea79cSHeinrich Kuhn "serial-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 1006ff627b74SChaoyong He cpp_serial[0], cpp_serial[1], cpp_serial[2], cpp_serial[3], 1007ff627b74SChaoyong He cpp_serial[4], cpp_serial[5], interface >> 8, interface & 0xff); 1008ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/%s.nffw", DEFAULT_FW_PATH, serial); 1009646ea79cSHeinrich Kuhn 1010646ea79cSHeinrich Kuhn PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); 1011ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1012ebfb540eSPeng Zhang return 0; 1013b0c496abSChaoyong He 1014646ea79cSHeinrich Kuhn /* Then try the PCI name */ 1015ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/pci-%s.nffw", DEFAULT_FW_PATH, 10163ddb4cc0SPeng Zhang dev->name); 1017646ea79cSHeinrich Kuhn 1018646ea79cSHeinrich Kuhn PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); 1019ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1020ebfb540eSPeng Zhang return 0; 1021646ea79cSHeinrich Kuhn 1022646ea79cSHeinrich Kuhn /* Finally try the card type and media */ 1023ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/%s", DEFAULT_FW_PATH, card); 1024646ea79cSHeinrich Kuhn PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); 1025ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1026ebfb540eSPeng Zhang return 0; 1027c01e5c0cSChaoyong He 1028646ea79cSHeinrich Kuhn return -ENOENT; 1029ebfb540eSPeng Zhang } 1030646ea79cSHeinrich Kuhn 1031ebfb540eSPeng Zhang static int 1032ebfb540eSPeng Zhang nfp_fw_upload(struct nfp_nsp *nsp, 1033ebfb540eSPeng Zhang char *fw_name) 1034ebfb540eSPeng Zhang { 1035ebfb540eSPeng Zhang int err; 1036ebfb540eSPeng Zhang void *fw_buf; 1037ebfb540eSPeng Zhang size_t fsize; 1038ebfb540eSPeng Zhang 1039ebfb540eSPeng Zhang err = rte_firmware_read(fw_name, &fw_buf, &fsize); 1040ebfb540eSPeng Zhang if (err != 0) { 1041ebfb540eSPeng Zhang PMD_DRV_LOG(ERR, "firmware %s not found!", fw_name); 1042ebfb540eSPeng Zhang return -ENOENT; 1043ebfb540eSPeng Zhang } 1044ebfb540eSPeng Zhang 1045646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu", 1046646ea79cSHeinrich Kuhn fw_name, fsize); 1047646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Uploading the firmware ..."); 10482e634b03SPeng Zhang if (nfp_nsp_load_fw(nsp, fw_buf, fsize) < 0) { 10492e634b03SPeng Zhang free(fw_buf); 10502e634b03SPeng Zhang PMD_DRV_LOG(ERR, "Firmware load failed."); 10512e634b03SPeng Zhang return -EIO; 10522e634b03SPeng Zhang } 10532e634b03SPeng Zhang 1054646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Done"); 1055646ea79cSHeinrich Kuhn 1056646ea79cSHeinrich Kuhn free(fw_buf); 1057646ea79cSHeinrich Kuhn 1058646ea79cSHeinrich Kuhn return 0; 1059646ea79cSHeinrich Kuhn } 1060646ea79cSHeinrich Kuhn 10613b00109dSPeng Zhang static void 10623b00109dSPeng Zhang nfp_fw_unload(struct nfp_cpp *cpp) 10633b00109dSPeng Zhang { 10643b00109dSPeng Zhang struct nfp_nsp *nsp; 10653b00109dSPeng Zhang 10663b00109dSPeng Zhang nsp = nfp_nsp_open(cpp); 10673b00109dSPeng Zhang if (nsp == NULL) 10683b00109dSPeng Zhang return; 10693b00109dSPeng Zhang 10703b00109dSPeng Zhang nfp_nsp_device_soft_reset(nsp); 10713b00109dSPeng Zhang nfp_nsp_close(nsp); 10723b00109dSPeng Zhang } 10733b00109dSPeng Zhang 1074646ea79cSHeinrich Kuhn static int 1075*a2bc299dSPeng Zhang nfp_fw_check_change(struct nfp_cpp *cpp, 1076*a2bc299dSPeng Zhang char *fw_name, 1077*a2bc299dSPeng Zhang bool *fw_changed) 1078*a2bc299dSPeng Zhang { 1079*a2bc299dSPeng Zhang int ret; 1080*a2bc299dSPeng Zhang struct nfp_net_hw hw; 1081*a2bc299dSPeng Zhang uint32_t new_version = 0; 1082*a2bc299dSPeng Zhang uint32_t old_version = 0; 1083*a2bc299dSPeng Zhang 1084*a2bc299dSPeng Zhang ret = nfp_elf_get_fw_version(&new_version, fw_name); 1085*a2bc299dSPeng Zhang if (ret != 0) 1086*a2bc299dSPeng Zhang return ret; 1087*a2bc299dSPeng Zhang 1088*a2bc299dSPeng Zhang hw.cpp = cpp; 1089*a2bc299dSPeng Zhang nfp_net_get_fw_version(&hw, &old_version); 1090*a2bc299dSPeng Zhang 1091*a2bc299dSPeng Zhang if (new_version != old_version) { 1092*a2bc299dSPeng Zhang PMD_DRV_LOG(INFO, "FW version is changed, new %u, old %u", 1093*a2bc299dSPeng Zhang new_version, old_version); 1094*a2bc299dSPeng Zhang *fw_changed = true; 1095*a2bc299dSPeng Zhang } else { 1096*a2bc299dSPeng Zhang PMD_DRV_LOG(INFO, "FW version is not changed and is %u", new_version); 1097*a2bc299dSPeng Zhang *fw_changed = false; 1098*a2bc299dSPeng Zhang } 1099*a2bc299dSPeng Zhang 1100*a2bc299dSPeng Zhang return 0; 1101*a2bc299dSPeng Zhang } 1102*a2bc299dSPeng Zhang 1103*a2bc299dSPeng Zhang static int 1104ebfb540eSPeng Zhang nfp_fw_reload(struct nfp_nsp *nsp, 1105ebfb540eSPeng Zhang char *fw_name) 11068ba461d1SPeng Zhang { 11078ba461d1SPeng Zhang int err; 11088ba461d1SPeng Zhang 11098ba461d1SPeng Zhang nfp_nsp_device_soft_reset(nsp); 1110ebfb540eSPeng Zhang err = nfp_fw_upload(nsp, fw_name); 11118ba461d1SPeng Zhang if (err != 0) 11128ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "NFP firmware load failed"); 11138ba461d1SPeng Zhang 11148ba461d1SPeng Zhang return err; 11158ba461d1SPeng Zhang } 11168ba461d1SPeng Zhang 1117a99ca614SPeng Zhang static bool 1118a99ca614SPeng Zhang nfp_fw_skip_load(const struct nfp_dev_info *dev_info, 11198ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 11208ba461d1SPeng Zhang { 112174397a7aSPeng Zhang uint8_t i; 112274397a7aSPeng Zhang uint64_t tmp_beat; 11238ba461d1SPeng Zhang uint32_t port_num; 11248b9a83eaSPeng Zhang uint8_t in_use = 0; 112574397a7aSPeng Zhang uint64_t beat[dev_info->pf_num_per_unit]; 112674397a7aSPeng Zhang uint32_t offset[dev_info->pf_num_per_unit]; 11278b9a83eaSPeng Zhang uint8_t abnormal = dev_info->pf_num_per_unit; 112874397a7aSPeng Zhang 112974397a7aSPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 113074397a7aSPeng Zhang offset[port_num] = NFP_BEAT_OFFSET(port_num); 113174397a7aSPeng Zhang beat[port_num] = nn_readq(multi_pf->beat_addr + offset[port_num]); 11328b9a83eaSPeng Zhang if (beat[port_num] == 0) 11338b9a83eaSPeng Zhang abnormal--; 113474397a7aSPeng Zhang } 11358ba461d1SPeng Zhang 11368b9a83eaSPeng Zhang if (abnormal == 0) 11378b9a83eaSPeng Zhang return true; 11388b9a83eaSPeng Zhang 113974397a7aSPeng Zhang for (i = 0; i < 3; i++) { 114074397a7aSPeng Zhang sleep(1); 11418ba461d1SPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 11428ba461d1SPeng Zhang if (port_num == multi_pf->function_id) 11438ba461d1SPeng Zhang continue; 11448ba461d1SPeng Zhang 11458b9a83eaSPeng Zhang if (beat[port_num] == 0) 11468b9a83eaSPeng Zhang continue; 11478b9a83eaSPeng Zhang 114874397a7aSPeng Zhang tmp_beat = nn_readq(multi_pf->beat_addr + offset[port_num]); 11498b9a83eaSPeng Zhang if (tmp_beat != beat[port_num]) { 11508b9a83eaSPeng Zhang in_use++; 11518b9a83eaSPeng Zhang abnormal--; 11528b9a83eaSPeng Zhang beat[port_num] = 0; 11538b9a83eaSPeng Zhang } 11548b9a83eaSPeng Zhang } 11558b9a83eaSPeng Zhang 11568b9a83eaSPeng Zhang if (abnormal == 0) 1157a99ca614SPeng Zhang return true; 11588ba461d1SPeng Zhang } 11598b9a83eaSPeng Zhang 11608b9a83eaSPeng Zhang if (in_use != 0) { 11618b9a83eaSPeng Zhang PMD_DRV_LOG(WARNING, "Abnormal %u != 0, the nic has port which is exit abnormally.", 11628b9a83eaSPeng Zhang abnormal); 11638b9a83eaSPeng Zhang return true; 11648ba461d1SPeng Zhang } 11658ba461d1SPeng Zhang 1166a99ca614SPeng Zhang return false; 11678ba461d1SPeng Zhang } 1168*a2bc299dSPeng Zhang static int 1169*a2bc299dSPeng Zhang nfp_fw_reload_for_single_pf(struct nfp_nsp *nsp, 1170*a2bc299dSPeng Zhang char *fw_name, 1171*a2bc299dSPeng Zhang struct nfp_cpp *cpp) 1172*a2bc299dSPeng Zhang { 1173*a2bc299dSPeng Zhang int ret; 1174*a2bc299dSPeng Zhang bool fw_changed = true; 1175*a2bc299dSPeng Zhang 1176*a2bc299dSPeng Zhang if (nfp_nsp_fw_loaded(nsp)) { 1177*a2bc299dSPeng Zhang ret = nfp_fw_check_change(cpp, fw_name, &fw_changed); 1178*a2bc299dSPeng Zhang if (ret != 0) 1179*a2bc299dSPeng Zhang return ret; 1180*a2bc299dSPeng Zhang } 1181*a2bc299dSPeng Zhang 1182*a2bc299dSPeng Zhang if (!fw_changed) 1183*a2bc299dSPeng Zhang return 0; 1184*a2bc299dSPeng Zhang 1185*a2bc299dSPeng Zhang ret = nfp_fw_reload(nsp, fw_name); 1186*a2bc299dSPeng Zhang if (ret != 0) 1187*a2bc299dSPeng Zhang return ret; 1188*a2bc299dSPeng Zhang 1189*a2bc299dSPeng Zhang return 0; 1190*a2bc299dSPeng Zhang } 11918ba461d1SPeng Zhang 11928ba461d1SPeng Zhang static int 1193*a2bc299dSPeng Zhang nfp_fw_reload_for_multi_pf(struct nfp_nsp *nsp, 1194ebfb540eSPeng Zhang char *fw_name, 11958ba461d1SPeng Zhang struct nfp_cpp *cpp, 11968ba461d1SPeng Zhang const struct nfp_dev_info *dev_info, 11978ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 11988ba461d1SPeng Zhang { 11998ba461d1SPeng Zhang int err; 1200*a2bc299dSPeng Zhang bool fw_changed = true; 1201a99ca614SPeng Zhang bool skip_load_fw = false; 12028ba461d1SPeng Zhang 12038ba461d1SPeng Zhang err = nfp_net_keepalive_init(cpp, multi_pf); 12048ba461d1SPeng Zhang if (err != 0) { 1205a99ca614SPeng Zhang PMD_DRV_LOG(ERR, "NFP init beat failed"); 12068ba461d1SPeng Zhang return err; 12078ba461d1SPeng Zhang } 12088ba461d1SPeng Zhang 12098ba461d1SPeng Zhang err = nfp_net_keepalive_start(multi_pf); 12108ba461d1SPeng Zhang if (err != 0) { 12118ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "NFP write beat failed"); 1212*a2bc299dSPeng Zhang goto keepalive_uninit; 12138ba461d1SPeng Zhang } 12148ba461d1SPeng Zhang 1215*a2bc299dSPeng Zhang if (nfp_nsp_fw_loaded(nsp)) { 1216*a2bc299dSPeng Zhang err = nfp_fw_check_change(cpp, fw_name, &fw_changed); 1217*a2bc299dSPeng Zhang if (err != 0) 1218*a2bc299dSPeng Zhang goto keepalive_stop; 1219*a2bc299dSPeng Zhang } 1220*a2bc299dSPeng Zhang 1221*a2bc299dSPeng Zhang if (!fw_changed) 1222a99ca614SPeng Zhang skip_load_fw = nfp_fw_skip_load(dev_info, multi_pf); 1223a99ca614SPeng Zhang 1224a99ca614SPeng Zhang if (skip_load_fw) 1225a99ca614SPeng Zhang return 0; 1226a99ca614SPeng Zhang 1227a99ca614SPeng Zhang err = nfp_fw_reload(nsp, fw_name); 1228*a2bc299dSPeng Zhang if (err != 0) 1229*a2bc299dSPeng Zhang goto keepalive_stop; 12308ba461d1SPeng Zhang 1231b67a7b40SPeng Zhang nfp_net_keepalive_clear_others(dev_info, multi_pf); 1232b67a7b40SPeng Zhang 1233a99ca614SPeng Zhang return 0; 1234*a2bc299dSPeng Zhang 1235*a2bc299dSPeng Zhang keepalive_stop: 1236*a2bc299dSPeng Zhang nfp_net_keepalive_stop(multi_pf); 1237*a2bc299dSPeng Zhang keepalive_uninit: 1238*a2bc299dSPeng Zhang nfp_net_keepalive_uninit(multi_pf); 1239*a2bc299dSPeng Zhang 1240*a2bc299dSPeng Zhang return err; 1241a99ca614SPeng Zhang } 1242a99ca614SPeng Zhang 12438ba461d1SPeng Zhang static int 1244a6189a67SJin Liu nfp_fw_setup(struct rte_pci_device *dev, 1245a6189a67SJin Liu struct nfp_cpp *cpp, 1246a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table, 12478ba461d1SPeng Zhang struct nfp_hwinfo *hwinfo, 12488ba461d1SPeng Zhang const struct nfp_dev_info *dev_info, 12498ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 1250646ea79cSHeinrich Kuhn { 125149952141SChaoyong He int err; 1252ebfb540eSPeng Zhang char fw_name[125]; 125349952141SChaoyong He char card_desc[100]; 1254646ea79cSHeinrich Kuhn struct nfp_nsp *nsp; 1255646ea79cSHeinrich Kuhn const char *nfp_fw_model; 1256646ea79cSHeinrich Kuhn 125706be30d4SPeng Zhang nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "nffw.partno"); 125806be30d4SPeng Zhang if (nfp_fw_model == NULL) 1259646ea79cSHeinrich Kuhn nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "assembly.partno"); 1260646ea79cSHeinrich Kuhn 1261c01e5c0cSChaoyong He if (nfp_fw_model != NULL) { 1262646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "firmware model found: %s", nfp_fw_model); 1263646ea79cSHeinrich Kuhn } else { 1264646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "firmware model NOT found"); 1265646ea79cSHeinrich Kuhn return -EIO; 1266646ea79cSHeinrich Kuhn } 1267646ea79cSHeinrich Kuhn 1268646ea79cSHeinrich Kuhn if (nfp_eth_table->count == 0 || nfp_eth_table->count > 8) { 1269646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "NFP ethernet table reports wrong ports: %u", 1270646ea79cSHeinrich Kuhn nfp_eth_table->count); 1271646ea79cSHeinrich Kuhn return -EIO; 1272646ea79cSHeinrich Kuhn } 1273646ea79cSHeinrich Kuhn 1274646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "NFP ethernet port table reports %u ports", 1275646ea79cSHeinrich Kuhn nfp_eth_table->count); 1276646ea79cSHeinrich Kuhn 1277646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Port speed: %u", nfp_eth_table->ports[0].speed); 1278646ea79cSHeinrich Kuhn 1279646ea79cSHeinrich Kuhn snprintf(card_desc, sizeof(card_desc), "nic_%s_%dx%d.nffw", 1280646ea79cSHeinrich Kuhn nfp_fw_model, nfp_eth_table->count, 1281646ea79cSHeinrich Kuhn nfp_eth_table->ports[0].speed / 1000); 1282646ea79cSHeinrich Kuhn 1283646ea79cSHeinrich Kuhn nsp = nfp_nsp_open(cpp); 1284a6189a67SJin Liu if (nsp == NULL) { 1285646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle"); 1286646ea79cSHeinrich Kuhn return -EIO; 1287646ea79cSHeinrich Kuhn } 1288646ea79cSHeinrich Kuhn 1289ebfb540eSPeng Zhang err = nfp_fw_get_name(dev, nsp, card_desc, fw_name, sizeof(fw_name)); 1290ebfb540eSPeng Zhang if (err != 0) { 1291ebfb540eSPeng Zhang PMD_DRV_LOG(ERR, "Can't find suitable firmware."); 1292ebfb540eSPeng Zhang nfp_nsp_close(nsp); 1293ebfb540eSPeng Zhang return err; 1294ebfb540eSPeng Zhang } 1295ebfb540eSPeng Zhang 12968ba461d1SPeng Zhang if (multi_pf->enabled) 1297*a2bc299dSPeng Zhang err = nfp_fw_reload_for_multi_pf(nsp, fw_name, cpp, dev_info, multi_pf); 12988ba461d1SPeng Zhang else 1299*a2bc299dSPeng Zhang err = nfp_fw_reload_for_single_pf(nsp, fw_name, cpp); 1300646ea79cSHeinrich Kuhn 1301646ea79cSHeinrich Kuhn nfp_nsp_close(nsp); 1302646ea79cSHeinrich Kuhn return err; 1303646ea79cSHeinrich Kuhn } 1304646ea79cSHeinrich Kuhn 13058ad2cc8fSPeng Zhang static inline bool 1306a508fa23SPeng Zhang nfp_check_multi_pf_from_fw(uint32_t total_vnics) 1307a508fa23SPeng Zhang { 1308a508fa23SPeng Zhang if (total_vnics == 1) 1309a508fa23SPeng Zhang return true; 1310a508fa23SPeng Zhang 1311a508fa23SPeng Zhang return false; 1312a508fa23SPeng Zhang } 1313a508fa23SPeng Zhang 1314a508fa23SPeng Zhang static inline bool 13158ad2cc8fSPeng Zhang nfp_check_multi_pf_from_nsp(struct rte_pci_device *pci_dev, 13168ad2cc8fSPeng Zhang struct nfp_cpp *cpp) 13178ad2cc8fSPeng Zhang { 13188ad2cc8fSPeng Zhang bool flag; 13198ad2cc8fSPeng Zhang struct nfp_nsp *nsp; 13208ad2cc8fSPeng Zhang 13218ad2cc8fSPeng Zhang nsp = nfp_nsp_open(cpp); 13228ad2cc8fSPeng Zhang if (nsp == NULL) { 13238ad2cc8fSPeng Zhang PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle"); 13248ad2cc8fSPeng Zhang return false; 13258ad2cc8fSPeng Zhang } 13268ad2cc8fSPeng Zhang 13278ad2cc8fSPeng Zhang flag = (nfp_nsp_get_abi_ver_major(nsp) > 0) && 13288ad2cc8fSPeng Zhang (pci_dev->id.device_id == PCI_DEVICE_ID_NFP3800_PF_NIC); 13298ad2cc8fSPeng Zhang 13308ad2cc8fSPeng Zhang nfp_nsp_close(nsp); 13318ad2cc8fSPeng Zhang return flag; 13328ad2cc8fSPeng Zhang } 13338ad2cc8fSPeng Zhang 1334a6189a67SJin Liu static int 133595f978efSPeng Zhang nfp_enable_multi_pf(struct nfp_pf_dev *pf_dev) 133695f978efSPeng Zhang { 133795f978efSPeng Zhang int err = 0; 133895f978efSPeng Zhang uint64_t tx_base; 133995f978efSPeng Zhang uint8_t *ctrl_bar; 134095f978efSPeng Zhang struct nfp_hw *hw; 134195f978efSPeng Zhang uint32_t cap_extend; 134295f978efSPeng Zhang struct nfp_net_hw net_hw; 134395f978efSPeng Zhang struct nfp_cpp_area *area; 134495f978efSPeng Zhang char name[RTE_ETH_NAME_MAX_LEN]; 134595f978efSPeng Zhang 134695f978efSPeng Zhang memset(&net_hw, 0, sizeof(struct nfp_net_hw)); 134795f978efSPeng Zhang 134895f978efSPeng Zhang /* Map the symbol table */ 134995f978efSPeng Zhang snprintf(name, sizeof(name), "_pf%u_net_bar0", 135095f978efSPeng Zhang pf_dev->multi_pf.function_id); 135195f978efSPeng Zhang ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, name, NFP_NET_CFG_BAR_SZ, 135295f978efSPeng Zhang &area); 135395f978efSPeng Zhang if (ctrl_bar == NULL) { 135495f978efSPeng Zhang PMD_INIT_LOG(ERR, "Failed to find data vNIC memory symbol"); 135595f978efSPeng Zhang return -ENODEV; 135695f978efSPeng Zhang } 135795f978efSPeng Zhang 135895f978efSPeng Zhang hw = &net_hw.super; 135995f978efSPeng Zhang hw->ctrl_bar = ctrl_bar; 136095f978efSPeng Zhang 136195f978efSPeng Zhang cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1); 136295f978efSPeng Zhang if ((cap_extend & NFP_NET_CFG_CTRL_MULTI_PF) == 0) { 136395f978efSPeng Zhang PMD_INIT_LOG(ERR, "Loaded firmware doesn't support multiple PF"); 136495f978efSPeng Zhang err = -EINVAL; 136595f978efSPeng Zhang goto end; 136695f978efSPeng Zhang } 136795f978efSPeng Zhang 136895f978efSPeng Zhang tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 136995f978efSPeng Zhang net_hw.tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ; 137095f978efSPeng Zhang nfp_net_cfg_queue_setup(&net_hw); 137195f978efSPeng Zhang rte_spinlock_init(&hw->reconfig_lock); 137295f978efSPeng Zhang nfp_ext_reconfig(&net_hw.super, NFP_NET_CFG_CTRL_MULTI_PF, NFP_NET_CFG_UPDATE_GEN); 137395f978efSPeng Zhang end: 137495f978efSPeng Zhang nfp_cpp_area_release_free(area); 137595f978efSPeng Zhang return err; 137695f978efSPeng Zhang } 137795f978efSPeng Zhang 137895f978efSPeng Zhang static int 13790314a8ffSChaoyong He nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev, 13800314a8ffSChaoyong He const struct nfp_dev_info *dev_info) 1381646ea79cSHeinrich Kuhn { 13828ceb85c3SChaoyong He uint8_t i; 13833b00109dSPeng Zhang uint8_t id; 1384e7978635SChaoyong He int ret = 0; 13858ceb85c3SChaoyong He uint32_t total_vnics; 1386646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 1387968ec1c3SChaoyong He unsigned int numa_node; 1388646ea79cSHeinrich Kuhn struct rte_eth_dev *eth_dev; 1389968ec1c3SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 1390a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table; 13913b00109dSPeng Zhang char bar_name[RTE_ETH_NAME_MAX_LEN]; 1392646ea79cSHeinrich Kuhn char port_name[RTE_ETH_NAME_MAX_LEN]; 13933b00109dSPeng Zhang char vnic_name[RTE_ETH_NAME_MAX_LEN]; 1394646ea79cSHeinrich Kuhn 1395968ec1c3SChaoyong He nfp_eth_table = pf_dev->nfp_eth_table; 1396968ec1c3SChaoyong He PMD_INIT_LOG(INFO, "Total physical ports: %d", nfp_eth_table->count); 13973b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, 0); 1398968ec1c3SChaoyong He 1399968ec1c3SChaoyong He /* Allocate memory for the CoreNIC app */ 1400968ec1c3SChaoyong He app_fw_nic = rte_zmalloc("nfp_app_fw_nic", sizeof(*app_fw_nic), 0); 1401968ec1c3SChaoyong He if (app_fw_nic == NULL) 1402968ec1c3SChaoyong He return -ENOMEM; 1403968ec1c3SChaoyong He 1404968ec1c3SChaoyong He /* Point the app_fw_priv pointer in the PF to the coreNIC app */ 1405968ec1c3SChaoyong He pf_dev->app_fw_priv = app_fw_nic; 1406968ec1c3SChaoyong He 1407968ec1c3SChaoyong He /* Read the number of vNIC's created for the PF */ 14083b00109dSPeng Zhang snprintf(vnic_name, sizeof(vnic_name), "nfd_cfg_pf%u_num_ports", id); 14093b00109dSPeng Zhang total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, vnic_name, &ret); 1410e7978635SChaoyong He if (ret != 0 || total_vnics == 0 || total_vnics > 8) { 14113b00109dSPeng Zhang PMD_INIT_LOG(ERR, "%s symbol with wrong value", vnic_name); 1412968ec1c3SChaoyong He ret = -ENODEV; 1413968ec1c3SChaoyong He goto app_cleanup; 1414968ec1c3SChaoyong He } 1415968ec1c3SChaoyong He 1416a508fa23SPeng Zhang if (pf_dev->multi_pf.enabled) { 1417a508fa23SPeng Zhang if (!nfp_check_multi_pf_from_fw(total_vnics)) { 1418a508fa23SPeng Zhang PMD_INIT_LOG(ERR, "NSP report multipf, but FW report not multipf"); 1419a508fa23SPeng Zhang ret = -ENODEV; 1420a508fa23SPeng Zhang goto app_cleanup; 1421a508fa23SPeng Zhang } 1422a508fa23SPeng Zhang } else { 1423968ec1c3SChaoyong He /* 1424968ec1c3SChaoyong He * For coreNIC the number of vNICs exposed should be the same as the 142540688372SChaoyong He * number of physical ports. 1426968ec1c3SChaoyong He */ 14278ceb85c3SChaoyong He if (total_vnics != nfp_eth_table->count) { 1428968ec1c3SChaoyong He PMD_INIT_LOG(ERR, "Total physical ports do not match number of vNICs"); 1429968ec1c3SChaoyong He ret = -ENODEV; 1430968ec1c3SChaoyong He goto app_cleanup; 1431968ec1c3SChaoyong He } 1432a508fa23SPeng Zhang } 1433968ec1c3SChaoyong He 1434968ec1c3SChaoyong He /* Populate coreNIC app properties */ 1435968ec1c3SChaoyong He app_fw_nic->total_phyports = total_vnics; 1436968ec1c3SChaoyong He app_fw_nic->pf_dev = pf_dev; 1437968ec1c3SChaoyong He if (total_vnics > 1) 1438968ec1c3SChaoyong He app_fw_nic->multiport = true; 1439968ec1c3SChaoyong He 1440968ec1c3SChaoyong He /* Map the symbol table */ 14413b00109dSPeng Zhang snprintf(bar_name, sizeof(bar_name), "_pf%u_net_bar0", id); 14423b00109dSPeng Zhang pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, bar_name, 1443d5e9fc86SChaoyong He app_fw_nic->total_phyports * NFP_NET_CFG_BAR_SZ, 1444d5e9fc86SChaoyong He &pf_dev->ctrl_area); 1445968ec1c3SChaoyong He if (pf_dev->ctrl_bar == NULL) { 14463b00109dSPeng Zhang PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for %s", bar_name); 1447968ec1c3SChaoyong He ret = -EIO; 1448968ec1c3SChaoyong He goto app_cleanup; 1449968ec1c3SChaoyong He } 1450968ec1c3SChaoyong He 1451968ec1c3SChaoyong He PMD_INIT_LOG(DEBUG, "ctrl bar: %p", pf_dev->ctrl_bar); 1452968ec1c3SChaoyong He 1453968ec1c3SChaoyong He /* Loop through all physical ports on PF */ 1454968ec1c3SChaoyong He numa_node = rte_socket_id(); 1455968ec1c3SChaoyong He for (i = 0; i < app_fw_nic->total_phyports; i++) { 1456c92c83d4SPeng Zhang if (pf_dev->multi_pf.enabled) 1457c92c83d4SPeng Zhang snprintf(port_name, sizeof(port_name), "%s", 1458c92c83d4SPeng Zhang pf_dev->pci_dev->device.name); 1459c92c83d4SPeng Zhang else 14603b00109dSPeng Zhang snprintf(port_name, sizeof(port_name), "%s_port%u", 1461c92c83d4SPeng Zhang pf_dev->pci_dev->device.name, i); 1462646ea79cSHeinrich Kuhn 1463646ea79cSHeinrich Kuhn /* Allocate a eth_dev for this phyport */ 1464646ea79cSHeinrich Kuhn eth_dev = rte_eth_dev_allocate(port_name); 1465a6189a67SJin Liu if (eth_dev == NULL) { 1466646ea79cSHeinrich Kuhn ret = -ENODEV; 1467646ea79cSHeinrich Kuhn goto port_cleanup; 1468646ea79cSHeinrich Kuhn } 1469646ea79cSHeinrich Kuhn 1470646ea79cSHeinrich Kuhn /* Allocate memory for this phyport */ 1471f4d24fe9SChaoyong He eth_dev->data->dev_private = rte_zmalloc_socket(port_name, 1472f4d24fe9SChaoyong He sizeof(struct nfp_net_hw), 1473646ea79cSHeinrich Kuhn RTE_CACHE_LINE_SIZE, numa_node); 1474a6189a67SJin Liu if (eth_dev->data->dev_private == NULL) { 1475646ea79cSHeinrich Kuhn ret = -ENOMEM; 1476646ea79cSHeinrich Kuhn rte_eth_dev_release_port(eth_dev); 1477646ea79cSHeinrich Kuhn goto port_cleanup; 1478646ea79cSHeinrich Kuhn } 1479646ea79cSHeinrich Kuhn 14809d723baaSChaoyong He hw = eth_dev->data->dev_private; 1481c92c83d4SPeng Zhang id = nfp_function_id_get(pf_dev, i); 1482646ea79cSHeinrich Kuhn 1483646ea79cSHeinrich Kuhn /* Add this device to the PF's array of physical ports */ 14843b00109dSPeng Zhang app_fw_nic->ports[id] = hw; 1485646ea79cSHeinrich Kuhn 14860314a8ffSChaoyong He hw->dev_info = dev_info; 1487646ea79cSHeinrich Kuhn hw->pf_dev = pf_dev; 1488646ea79cSHeinrich Kuhn hw->cpp = pf_dev->cpp; 1489646ea79cSHeinrich Kuhn hw->eth_dev = eth_dev; 14903b00109dSPeng Zhang hw->idx = id; 14913b00109dSPeng Zhang hw->nfp_idx = nfp_eth_table->ports[id].index; 1492646ea79cSHeinrich Kuhn 1493646ea79cSHeinrich Kuhn eth_dev->device = &pf_dev->pci_dev->device; 1494646ea79cSHeinrich Kuhn 149540688372SChaoyong He /* 149640688372SChaoyong He * Ctrl/tx/rx BAR mappings and remaining init happens in 149740688372SChaoyong He * @nfp_net_init() 1498646ea79cSHeinrich Kuhn */ 1499646ea79cSHeinrich Kuhn ret = nfp_net_init(eth_dev); 1500c01e5c0cSChaoyong He if (ret != 0) { 1501646ea79cSHeinrich Kuhn ret = -ENODEV; 1502646ea79cSHeinrich Kuhn goto port_cleanup; 1503646ea79cSHeinrich Kuhn } 1504646ea79cSHeinrich Kuhn 1505646ea79cSHeinrich Kuhn rte_eth_dev_probing_finish(eth_dev); 1506646ea79cSHeinrich Kuhn 1507646ea79cSHeinrich Kuhn } /* End loop, all ports on this PF */ 1508968ec1c3SChaoyong He 1509968ec1c3SChaoyong He return 0; 1510646ea79cSHeinrich Kuhn 1511646ea79cSHeinrich Kuhn port_cleanup: 1512968ec1c3SChaoyong He for (i = 0; i < app_fw_nic->total_phyports; i++) { 15133b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 15148153bc6fSChaoyong He hw = app_fw_nic->ports[id]; 15153b00109dSPeng Zhang 15168153bc6fSChaoyong He if (hw != NULL && hw->eth_dev != NULL) { 15178153bc6fSChaoyong He nfp_net_uninit(hw->eth_dev); 15188153bc6fSChaoyong He rte_eth_dev_release_port(hw->eth_dev); 1519646ea79cSHeinrich Kuhn } 1520646ea79cSHeinrich Kuhn } 15218b8f116bSChaoyong He nfp_cpp_area_release_free(pf_dev->ctrl_area); 1522968ec1c3SChaoyong He app_cleanup: 1523968ec1c3SChaoyong He rte_free(app_fw_nic); 1524a6189a67SJin Liu 1525646ea79cSHeinrich Kuhn return ret; 1526646ea79cSHeinrich Kuhn } 1527646ea79cSHeinrich Kuhn 1528a6189a67SJin Liu static int 1529c7a6970fSZerun Fu nfp_net_hwinfo_set(uint8_t function_id, 1530c7a6970fSZerun Fu struct nfp_rtsym_table *sym_tbl, 1531c7a6970fSZerun Fu struct nfp_cpp *cpp) 1532c7a6970fSZerun Fu { 1533c7a6970fSZerun Fu int ret = 0; 1534c7a6970fSZerun Fu uint64_t app_cap; 1535c7a6970fSZerun Fu uint8_t sp_indiff; 1536c7a6970fSZerun Fu struct nfp_nsp *nsp; 1537c7a6970fSZerun Fu char hw_info[RTE_ETH_NAME_MAX_LEN]; 1538c7a6970fSZerun Fu char app_cap_name[RTE_ETH_NAME_MAX_LEN]; 1539c7a6970fSZerun Fu 1540c7a6970fSZerun Fu /* Read the app capabilities of the firmware loaded */ 1541c7a6970fSZerun Fu snprintf(app_cap_name, sizeof(app_cap_name), "_pf%u_net_app_cap", function_id); 1542c7a6970fSZerun Fu app_cap = nfp_rtsym_read_le(sym_tbl, app_cap_name, &ret); 1543c7a6970fSZerun Fu if (ret != 0) { 1544c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Couldn't read app_fw_cap from firmware."); 1545c7a6970fSZerun Fu return ret; 1546c7a6970fSZerun Fu } 1547c7a6970fSZerun Fu 1548c7a6970fSZerun Fu /* Calculate the value of sp_indiff and write to hw_info */ 1549c7a6970fSZerun Fu sp_indiff = app_cap & NFP_NET_APP_CAP_SP_INDIFF; 1550c7a6970fSZerun Fu snprintf(hw_info, sizeof(hw_info), "sp_indiff=%u", sp_indiff); 1551c7a6970fSZerun Fu 1552c7a6970fSZerun Fu nsp = nfp_nsp_open(cpp); 1553c7a6970fSZerun Fu if (nsp == NULL) { 1554c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Couldn't get NSP."); 1555c7a6970fSZerun Fu return -EIO; 1556c7a6970fSZerun Fu } 1557c7a6970fSZerun Fu 1558c7a6970fSZerun Fu ret = nfp_nsp_hwinfo_set(nsp, hw_info, sizeof(hw_info)); 1559c7a6970fSZerun Fu nfp_nsp_close(nsp); 1560c7a6970fSZerun Fu if (ret != 0) { 1561c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Failed to set parameter to hwinfo."); 1562c7a6970fSZerun Fu return ret; 1563c7a6970fSZerun Fu } 1564c7a6970fSZerun Fu 1565c7a6970fSZerun Fu return 0; 1566c7a6970fSZerun Fu } 1567c7a6970fSZerun Fu 15683110ab73SZerun Fu const uint32_t nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = { 15693110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10M] = RTE_ETH_LINK_SPEED_10M, 15703110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10M_HD] = RTE_ETH_LINK_SPEED_10M_HD, 15713110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_100M] = RTE_ETH_LINK_SPEED_100M, 15723110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_100M_HD] = RTE_ETH_LINK_SPEED_100M_HD, 15733110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_1G] = RTE_ETH_LINK_SPEED_1G, 15743110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_2P5G] = RTE_ETH_LINK_SPEED_2_5G, 15753110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_5G] = RTE_ETH_LINK_SPEED_5G, 15763110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10G] = RTE_ETH_LINK_SPEED_10G, 15773110ab73SZerun Fu [NFP_MEDIA_1000BASE_CX] = RTE_ETH_LINK_SPEED_1G, 15783110ab73SZerun Fu [NFP_MEDIA_1000BASE_KX] = RTE_ETH_LINK_SPEED_1G, 15793110ab73SZerun Fu [NFP_MEDIA_10GBASE_KX4] = RTE_ETH_LINK_SPEED_10G, 15803110ab73SZerun Fu [NFP_MEDIA_10GBASE_KR] = RTE_ETH_LINK_SPEED_10G, 15813110ab73SZerun Fu [NFP_MEDIA_10GBASE_CX4] = RTE_ETH_LINK_SPEED_10G, 15823110ab73SZerun Fu [NFP_MEDIA_10GBASE_CR] = RTE_ETH_LINK_SPEED_10G, 15833110ab73SZerun Fu [NFP_MEDIA_10GBASE_SR] = RTE_ETH_LINK_SPEED_10G, 15843110ab73SZerun Fu [NFP_MEDIA_10GBASE_ER] = RTE_ETH_LINK_SPEED_10G, 15853110ab73SZerun Fu [NFP_MEDIA_25GBASE_KR] = RTE_ETH_LINK_SPEED_25G, 15863110ab73SZerun Fu [NFP_MEDIA_25GBASE_KR_S] = RTE_ETH_LINK_SPEED_25G, 15873110ab73SZerun Fu [NFP_MEDIA_25GBASE_CR] = RTE_ETH_LINK_SPEED_25G, 15883110ab73SZerun Fu [NFP_MEDIA_25GBASE_CR_S] = RTE_ETH_LINK_SPEED_25G, 15893110ab73SZerun Fu [NFP_MEDIA_25GBASE_SR] = RTE_ETH_LINK_SPEED_25G, 15903110ab73SZerun Fu [NFP_MEDIA_40GBASE_CR4] = RTE_ETH_LINK_SPEED_40G, 15913110ab73SZerun Fu [NFP_MEDIA_40GBASE_KR4] = RTE_ETH_LINK_SPEED_40G, 15923110ab73SZerun Fu [NFP_MEDIA_40GBASE_SR4] = RTE_ETH_LINK_SPEED_40G, 15933110ab73SZerun Fu [NFP_MEDIA_40GBASE_LR4] = RTE_ETH_LINK_SPEED_40G, 15943110ab73SZerun Fu [NFP_MEDIA_50GBASE_KR] = RTE_ETH_LINK_SPEED_50G, 15953110ab73SZerun Fu [NFP_MEDIA_50GBASE_SR] = RTE_ETH_LINK_SPEED_50G, 15963110ab73SZerun Fu [NFP_MEDIA_50GBASE_CR] = RTE_ETH_LINK_SPEED_50G, 15973110ab73SZerun Fu [NFP_MEDIA_50GBASE_LR] = RTE_ETH_LINK_SPEED_50G, 15983110ab73SZerun Fu [NFP_MEDIA_50GBASE_ER] = RTE_ETH_LINK_SPEED_50G, 15993110ab73SZerun Fu [NFP_MEDIA_50GBASE_FR] = RTE_ETH_LINK_SPEED_50G, 16003110ab73SZerun Fu [NFP_MEDIA_100GBASE_KR4] = RTE_ETH_LINK_SPEED_100G, 16013110ab73SZerun Fu [NFP_MEDIA_100GBASE_SR4] = RTE_ETH_LINK_SPEED_100G, 16023110ab73SZerun Fu [NFP_MEDIA_100GBASE_CR4] = RTE_ETH_LINK_SPEED_100G, 16033110ab73SZerun Fu [NFP_MEDIA_100GBASE_KP4] = RTE_ETH_LINK_SPEED_100G, 16043110ab73SZerun Fu [NFP_MEDIA_100GBASE_CR10] = RTE_ETH_LINK_SPEED_100G, 16053110ab73SZerun Fu [NFP_MEDIA_10GBASE_LR] = RTE_ETH_LINK_SPEED_10G, 16063110ab73SZerun Fu [NFP_MEDIA_25GBASE_LR] = RTE_ETH_LINK_SPEED_25G, 16073110ab73SZerun Fu [NFP_MEDIA_25GBASE_ER] = RTE_ETH_LINK_SPEED_25G 16083110ab73SZerun Fu }; 16093110ab73SZerun Fu 16103110ab73SZerun Fu static int 16113110ab73SZerun Fu nfp_net_speed_capa_get_real(struct nfp_eth_media_buf *media_buf, 16123110ab73SZerun Fu struct nfp_pf_dev *pf_dev) 16133110ab73SZerun Fu { 16143110ab73SZerun Fu uint32_t i; 16153110ab73SZerun Fu uint32_t j; 16163110ab73SZerun Fu uint32_t offset; 16173110ab73SZerun Fu uint32_t speed_capa = 0; 16183110ab73SZerun Fu uint64_t supported_modes; 16193110ab73SZerun Fu 16203110ab73SZerun Fu for (i = 0; i < RTE_DIM(media_buf->supported_modes); i++) { 16213110ab73SZerun Fu supported_modes = media_buf->supported_modes[i]; 16223110ab73SZerun Fu offset = i * UINT64_BIT; 16233110ab73SZerun Fu for (j = 0; j < UINT64_BIT; j++) { 16243110ab73SZerun Fu if (supported_modes == 0) 16253110ab73SZerun Fu break; 16263110ab73SZerun Fu 16273110ab73SZerun Fu if ((supported_modes & 1) != 0) { 16283110ab73SZerun Fu if ((j + offset) >= NFP_MEDIA_LINK_MODES_NUMBER) { 16293110ab73SZerun Fu PMD_DRV_LOG(ERR, "Invalid offset of media table."); 16303110ab73SZerun Fu return -EINVAL; 16313110ab73SZerun Fu } 16323110ab73SZerun Fu 16333110ab73SZerun Fu speed_capa |= nfp_eth_media_table[j + offset]; 16343110ab73SZerun Fu } 16353110ab73SZerun Fu 16363110ab73SZerun Fu supported_modes = supported_modes >> 1; 16373110ab73SZerun Fu } 16383110ab73SZerun Fu } 16393110ab73SZerun Fu 16403110ab73SZerun Fu pf_dev->speed_capa = speed_capa; 16413110ab73SZerun Fu 16423110ab73SZerun Fu return pf_dev->speed_capa == 0 ? -EINVAL : 0; 16433110ab73SZerun Fu } 16443110ab73SZerun Fu 16453110ab73SZerun Fu static int 16463110ab73SZerun Fu nfp_net_speed_capa_get(struct nfp_pf_dev *pf_dev, 16473110ab73SZerun Fu uint32_t port_id) 16483110ab73SZerun Fu { 16493110ab73SZerun Fu int ret; 16503110ab73SZerun Fu struct nfp_nsp *nsp; 16513110ab73SZerun Fu struct nfp_eth_media_buf media_buf; 16523110ab73SZerun Fu 16533110ab73SZerun Fu media_buf.eth_index = pf_dev->nfp_eth_table->ports[port_id].eth_index; 16543110ab73SZerun Fu pf_dev->speed_capa = 0; 16553110ab73SZerun Fu 16563110ab73SZerun Fu nsp = nfp_nsp_open(pf_dev->cpp); 16573110ab73SZerun Fu if (nsp == NULL) { 16583110ab73SZerun Fu PMD_DRV_LOG(ERR, "Couldn't get NSP."); 16593110ab73SZerun Fu return -EIO; 16603110ab73SZerun Fu } 16613110ab73SZerun Fu 16623110ab73SZerun Fu ret = nfp_nsp_read_media(nsp, &media_buf, sizeof(media_buf)); 16633110ab73SZerun Fu nfp_nsp_close(nsp); 16643110ab73SZerun Fu if (ret != 0) { 16653110ab73SZerun Fu PMD_DRV_LOG(ERR, "Failed to read media."); 16663110ab73SZerun Fu return ret; 16673110ab73SZerun Fu } 16683110ab73SZerun Fu 16693110ab73SZerun Fu ret = nfp_net_speed_capa_get_real(&media_buf, pf_dev); 16703110ab73SZerun Fu if (ret < 0) { 16713110ab73SZerun Fu PMD_DRV_LOG(ERR, "Speed capability is invalid."); 16723110ab73SZerun Fu return ret; 16733110ab73SZerun Fu } 16743110ab73SZerun Fu 16753110ab73SZerun Fu return 0; 16763110ab73SZerun Fu } 16773110ab73SZerun Fu 1678c7a6970fSZerun Fu static int 1679a6189a67SJin Liu nfp_pf_init(struct rte_pci_device *pci_dev) 1680646ea79cSHeinrich Kuhn { 16816b4273a0SLong Wu void *sync; 16829e442599SShihong Wang uint32_t i; 16833b00109dSPeng Zhang uint32_t id; 1684e7978635SChaoyong He int ret = 0; 16855c464d6aSJin Liu uint64_t addr; 16863b00109dSPeng Zhang uint32_t index; 1687925c27ecSChaoyong He uint32_t cpp_id; 16883b00109dSPeng Zhang uint8_t function_id; 1689a6189a67SJin Liu struct nfp_cpp *cpp; 1690a6189a67SJin Liu struct nfp_pf_dev *pf_dev; 1691a6189a67SJin Liu struct nfp_hwinfo *hwinfo; 169249952141SChaoyong He enum nfp_app_fw_id app_fw_id; 1693a6189a67SJin Liu char name[RTE_ETH_NAME_MAX_LEN]; 1694a6189a67SJin Liu struct nfp_rtsym_table *sym_tbl; 16953b00109dSPeng Zhang char app_name[RTE_ETH_NAME_MAX_LEN]; 1696a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table; 16970314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 1698646ea79cSHeinrich Kuhn 1699a6189a67SJin Liu if (pci_dev == NULL) 1700a6189a67SJin Liu return -ENODEV; 1701646ea79cSHeinrich Kuhn 170284aaba5aSChaoyong He if (pci_dev->mem_resource[0].addr == NULL) { 170384aaba5aSChaoyong He PMD_INIT_LOG(ERR, "The address of BAR0 is NULL."); 170484aaba5aSChaoyong He return -ENODEV; 170584aaba5aSChaoyong He } 170684aaba5aSChaoyong He 17070314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 17080314a8ffSChaoyong He if (dev_info == NULL) { 17090314a8ffSChaoyong He PMD_INIT_LOG(ERR, "Not supported device ID"); 17100314a8ffSChaoyong He return -ENODEV; 17110314a8ffSChaoyong He } 17120314a8ffSChaoyong He 17138ad2cc8fSPeng Zhang /* Allocate memory for the PF "device" */ 17143b00109dSPeng Zhang function_id = (pci_dev->addr.function) & 0x07; 17153b00109dSPeng Zhang snprintf(name, sizeof(name), "nfp_pf%u", function_id); 17168ad2cc8fSPeng Zhang pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); 17178ad2cc8fSPeng Zhang if (pf_dev == NULL) { 17188ad2cc8fSPeng Zhang PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device"); 17198ad2cc8fSPeng Zhang return -ENOMEM; 17208ad2cc8fSPeng Zhang } 17218ad2cc8fSPeng Zhang 17226b4273a0SLong Wu sync = nfp_sync_alloc(); 17236b4273a0SLong Wu if (sync == NULL) { 17246b4273a0SLong Wu PMD_INIT_LOG(ERR, "Failed to alloc sync zone."); 17256b4273a0SLong Wu ret = -ENOMEM; 17266b4273a0SLong Wu goto pf_cleanup; 17276b4273a0SLong Wu } 17286b4273a0SLong Wu 1729646ea79cSHeinrich Kuhn /* 1730646ea79cSHeinrich Kuhn * When device bound to UIO, the device could be used, by mistake, 1731646ea79cSHeinrich Kuhn * by two DPDK apps, and the UIO driver does not avoid it. This 1732646ea79cSHeinrich Kuhn * could lead to a serious problem when configuring the NFP CPP 1733646ea79cSHeinrich Kuhn * interface. Here we avoid this telling to the CPP init code to 1734646ea79cSHeinrich Kuhn * use a lock file if UIO is being used. 1735646ea79cSHeinrich Kuhn */ 1736646ea79cSHeinrich Kuhn if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) 17371fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false); 1738646ea79cSHeinrich Kuhn else 17391fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true); 1740646ea79cSHeinrich Kuhn 1741a6189a67SJin Liu if (cpp == NULL) { 1742646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "A CPP handle can not be obtained"); 17438ad2cc8fSPeng Zhang ret = -EIO; 17446b4273a0SLong Wu goto sync_free; 1745646ea79cSHeinrich Kuhn } 1746646ea79cSHeinrich Kuhn 1747646ea79cSHeinrich Kuhn hwinfo = nfp_hwinfo_read(cpp); 1748a6189a67SJin Liu if (hwinfo == NULL) { 1749646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Error reading hwinfo table"); 1750646ea79cSHeinrich Kuhn ret = -EIO; 1751968ec1c3SChaoyong He goto cpp_cleanup; 1752646ea79cSHeinrich Kuhn } 1753646ea79cSHeinrich Kuhn 1754968ec1c3SChaoyong He /* Read the number of physical ports from hardware */ 1755646ea79cSHeinrich Kuhn nfp_eth_table = nfp_eth_read_ports(cpp); 1756a6189a67SJin Liu if (nfp_eth_table == NULL) { 1757646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Error reading NFP ethernet table"); 1758646ea79cSHeinrich Kuhn ret = -EIO; 1759646ea79cSHeinrich Kuhn goto hwinfo_cleanup; 1760646ea79cSHeinrich Kuhn } 1761646ea79cSHeinrich Kuhn 17628ad2cc8fSPeng Zhang pf_dev->multi_pf.enabled = nfp_check_multi_pf_from_nsp(pci_dev, cpp); 17633b00109dSPeng Zhang pf_dev->multi_pf.function_id = function_id; 17648ad2cc8fSPeng Zhang 17659e442599SShihong Wang /* Force the physical port down to clear the possible DMA error */ 17663b00109dSPeng Zhang for (i = 0; i < nfp_eth_table->count; i++) { 17673b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 17683b00109dSPeng Zhang index = nfp_eth_table->ports[id].index; 17693b00109dSPeng Zhang nfp_eth_set_configured(cpp, index, 0); 17703b00109dSPeng Zhang } 17719e442599SShihong Wang 17728ba461d1SPeng Zhang if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo, 17738ba461d1SPeng Zhang dev_info, &pf_dev->multi_pf) != 0) { 1774646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Error when uploading firmware"); 1775646ea79cSHeinrich Kuhn ret = -EIO; 1776646ea79cSHeinrich Kuhn goto eth_table_cleanup; 1777646ea79cSHeinrich Kuhn } 1778646ea79cSHeinrich Kuhn 1779646ea79cSHeinrich Kuhn /* Now the symbol table should be there */ 1780646ea79cSHeinrich Kuhn sym_tbl = nfp_rtsym_table_read(cpp); 1781a6189a67SJin Liu if (sym_tbl == NULL) { 1782f4d24fe9SChaoyong He PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table"); 1783646ea79cSHeinrich Kuhn ret = -EIO; 17843b00109dSPeng Zhang goto fw_cleanup; 1785646ea79cSHeinrich Kuhn } 1786646ea79cSHeinrich Kuhn 1787968ec1c3SChaoyong He /* Read the app ID of the firmware loaded */ 17883b00109dSPeng Zhang snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id); 17893b00109dSPeng Zhang app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret); 1790e7978635SChaoyong He if (ret != 0) { 17913b00109dSPeng Zhang PMD_INIT_LOG(ERR, "Couldn't read %s from firmware", app_name); 1792646ea79cSHeinrich Kuhn ret = -EIO; 1793646ea79cSHeinrich Kuhn goto sym_tbl_cleanup; 1794646ea79cSHeinrich Kuhn } 1795646ea79cSHeinrich Kuhn 1796c7a6970fSZerun Fu /* Write sp_indiff to hw_info */ 1797c7a6970fSZerun Fu ret = nfp_net_hwinfo_set(function_id, sym_tbl, cpp); 1798c7a6970fSZerun Fu if (ret != 0) { 1799c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Failed to set hwinfo."); 1800c7a6970fSZerun Fu ret = -EIO; 1801c7a6970fSZerun Fu goto sym_tbl_cleanup; 1802c7a6970fSZerun Fu } 1803c7a6970fSZerun Fu 1804646ea79cSHeinrich Kuhn /* Populate the newly created PF device */ 1805968ec1c3SChaoyong He pf_dev->app_fw_id = app_fw_id; 1806646ea79cSHeinrich Kuhn pf_dev->cpp = cpp; 1807646ea79cSHeinrich Kuhn pf_dev->hwinfo = hwinfo; 1808646ea79cSHeinrich Kuhn pf_dev->sym_tbl = sym_tbl; 1809646ea79cSHeinrich Kuhn pf_dev->pci_dev = pci_dev; 1810968ec1c3SChaoyong He pf_dev->nfp_eth_table = nfp_eth_table; 18116b4273a0SLong Wu pf_dev->sync = sync; 1812646ea79cSHeinrich Kuhn 18133110ab73SZerun Fu /* Get the speed capability */ 18143110ab73SZerun Fu for (i = 0; i < nfp_eth_table->count; i++) { 18153110ab73SZerun Fu id = nfp_function_id_get(pf_dev, i); 18163110ab73SZerun Fu ret = nfp_net_speed_capa_get(pf_dev, id); 18173110ab73SZerun Fu if (ret != 0) { 18183110ab73SZerun Fu PMD_INIT_LOG(ERR, "Failed to get speed capability."); 18193110ab73SZerun Fu ret = -EIO; 18203110ab73SZerun Fu goto sym_tbl_cleanup; 18213110ab73SZerun Fu } 18223110ab73SZerun Fu } 18233110ab73SZerun Fu 182440688372SChaoyong He /* Configure access to tx/rx vNIC BARs */ 18250314a8ffSChaoyong He addr = nfp_qcp_queue_offset(dev_info, 0); 1826925c27ecSChaoyong He cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0); 18270314a8ffSChaoyong He 1828711e4559SChaoyong He pf_dev->qc_bar = nfp_cpp_map_area(pf_dev->cpp, cpp_id, 18290314a8ffSChaoyong He addr, dev_info->qc_area_sz, &pf_dev->qc_area); 1830711e4559SChaoyong He if (pf_dev->qc_bar == NULL) { 1831646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for net.qc"); 1832646ea79cSHeinrich Kuhn ret = -EIO; 18338ad2cc8fSPeng Zhang goto sym_tbl_cleanup; 1834646ea79cSHeinrich Kuhn } 1835646ea79cSHeinrich Kuhn 1836030b2b19SChaoyong He PMD_INIT_LOG(DEBUG, "qc_bar address: %p", pf_dev->qc_bar); 1837646ea79cSHeinrich Kuhn 1838a6189a67SJin Liu /* 1839968ec1c3SChaoyong He * PF initialization has been done at this point. Call app specific 184040688372SChaoyong He * init code now. 1841646ea79cSHeinrich Kuhn */ 1842968ec1c3SChaoyong He switch (pf_dev->app_fw_id) { 1843968ec1c3SChaoyong He case NFP_APP_FW_CORE_NIC: 184495f978efSPeng Zhang if (pf_dev->multi_pf.enabled) { 184595f978efSPeng Zhang ret = nfp_enable_multi_pf(pf_dev); 184695f978efSPeng Zhang if (ret != 0) 184795f978efSPeng Zhang goto hwqueues_cleanup; 184895f978efSPeng Zhang } 184995f978efSPeng Zhang 1850968ec1c3SChaoyong He PMD_INIT_LOG(INFO, "Initializing coreNIC"); 18510314a8ffSChaoyong He ret = nfp_init_app_fw_nic(pf_dev, dev_info); 1852968ec1c3SChaoyong He if (ret != 0) { 1853968ec1c3SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize coreNIC!"); 1854968ec1c3SChaoyong He goto hwqueues_cleanup; 1855968ec1c3SChaoyong He } 1856968ec1c3SChaoyong He break; 1857b1880421SChaoyong He case NFP_APP_FW_FLOWER_NIC: 1858b1880421SChaoyong He PMD_INIT_LOG(INFO, "Initializing Flower"); 18590314a8ffSChaoyong He ret = nfp_init_app_fw_flower(pf_dev, dev_info); 1860b1880421SChaoyong He if (ret != 0) { 1861b1880421SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize Flower!"); 1862b1880421SChaoyong He goto hwqueues_cleanup; 1863b1880421SChaoyong He } 1864b1880421SChaoyong He break; 1865968ec1c3SChaoyong He default: 1866968ec1c3SChaoyong He PMD_INIT_LOG(ERR, "Unsupported Firmware loaded"); 1867968ec1c3SChaoyong He ret = -EINVAL; 1868646ea79cSHeinrich Kuhn goto hwqueues_cleanup; 1869646ea79cSHeinrich Kuhn } 1870646ea79cSHeinrich Kuhn 187140688372SChaoyong He /* Register the CPP bridge service here for primary use */ 1872bab0e6f4SChaoyong He ret = nfp_enable_cpp_service(pf_dev); 1873dee23e6cSChaoyong He if (ret != 0) 1874dee23e6cSChaoyong He PMD_INIT_LOG(INFO, "Enable cpp service failed."); 1875646ea79cSHeinrich Kuhn 1876646ea79cSHeinrich Kuhn return 0; 1877646ea79cSHeinrich Kuhn 1878646ea79cSHeinrich Kuhn hwqueues_cleanup: 1879528812a6SChaoyong He nfp_cpp_area_release_free(pf_dev->qc_area); 1880646ea79cSHeinrich Kuhn sym_tbl_cleanup: 1881646ea79cSHeinrich Kuhn free(sym_tbl); 18823b00109dSPeng Zhang fw_cleanup: 18833b00109dSPeng Zhang nfp_fw_unload(cpp); 18848ba461d1SPeng Zhang nfp_net_keepalive_stop(&pf_dev->multi_pf); 1885b67a7b40SPeng Zhang nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id); 1886528812a6SChaoyong He nfp_net_keepalive_uninit(&pf_dev->multi_pf); 1887646ea79cSHeinrich Kuhn eth_table_cleanup: 1888646ea79cSHeinrich Kuhn free(nfp_eth_table); 1889646ea79cSHeinrich Kuhn hwinfo_cleanup: 1890646ea79cSHeinrich Kuhn free(hwinfo); 1891968ec1c3SChaoyong He cpp_cleanup: 1892968ec1c3SChaoyong He nfp_cpp_free(cpp); 18936b4273a0SLong Wu sync_free: 18946b4273a0SLong Wu nfp_sync_free(sync); 18958ad2cc8fSPeng Zhang pf_cleanup: 18968ad2cc8fSPeng Zhang rte_free(pf_dev); 18977feb8909SChaoyong He 1898646ea79cSHeinrich Kuhn return ret; 1899646ea79cSHeinrich Kuhn } 1900646ea79cSHeinrich Kuhn 1901d5f39e07SChaoyong He static int 1902016141b1SChaoyong He nfp_secondary_init_app_fw_nic(struct nfp_pf_dev *pf_dev) 1903d5f39e07SChaoyong He { 19048ceb85c3SChaoyong He uint32_t i; 1905d5f39e07SChaoyong He int err = 0; 1906d5f39e07SChaoyong He int ret = 0; 19073b00109dSPeng Zhang uint8_t function_id; 19088ceb85c3SChaoyong He uint32_t total_vnics; 1909d5f39e07SChaoyong He struct nfp_net_hw *hw; 19103b00109dSPeng Zhang char pf_name[RTE_ETH_NAME_MAX_LEN]; 1911d5f39e07SChaoyong He 1912d5f39e07SChaoyong He /* Read the number of vNIC's created for the PF */ 19133b00109dSPeng Zhang function_id = (pf_dev->pci_dev->addr.function) & 0x07; 19143b00109dSPeng Zhang snprintf(pf_name, sizeof(pf_name), "nfd_cfg_pf%u_num_ports", function_id); 19153b00109dSPeng Zhang total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, pf_name, &err); 19168ceb85c3SChaoyong He if (err != 0 || total_vnics == 0 || total_vnics > 8) { 19173b00109dSPeng Zhang PMD_INIT_LOG(ERR, "%s symbol with wrong value", pf_name); 1918d5f39e07SChaoyong He return -ENODEV; 1919d5f39e07SChaoyong He } 1920d5f39e07SChaoyong He 1921d5f39e07SChaoyong He for (i = 0; i < total_vnics; i++) { 1922d5f39e07SChaoyong He struct rte_eth_dev *eth_dev; 1923d5f39e07SChaoyong He char port_name[RTE_ETH_NAME_MAX_LEN]; 19243b00109dSPeng Zhang 19253b00109dSPeng Zhang if (nfp_check_multi_pf_from_fw(total_vnics)) 1926c92c83d4SPeng Zhang snprintf(port_name, sizeof(port_name), "%s", 1927c92c83d4SPeng Zhang pf_dev->pci_dev->device.name); 1928c92c83d4SPeng Zhang else 19298ceb85c3SChaoyong He snprintf(port_name, sizeof(port_name), "%s_port%u", 1930c92c83d4SPeng Zhang pf_dev->pci_dev->device.name, i); 1931d5f39e07SChaoyong He 1932d5f39e07SChaoyong He PMD_INIT_LOG(DEBUG, "Secondary attaching to port %s", port_name); 1933d5f39e07SChaoyong He eth_dev = rte_eth_dev_attach_secondary(port_name); 1934d5f39e07SChaoyong He if (eth_dev == NULL) { 1935d5f39e07SChaoyong He PMD_INIT_LOG(ERR, "Secondary process attach to port %s failed", port_name); 1936d5f39e07SChaoyong He ret = -ENODEV; 1937d5f39e07SChaoyong He break; 1938d5f39e07SChaoyong He } 1939d5f39e07SChaoyong He 1940acb6bebfSChaoyong He eth_dev->process_private = pf_dev; 19419d723baaSChaoyong He hw = eth_dev->data->dev_private; 1942ee8ca64eSChaoyong He nfp_net_ethdev_ops_mount(hw, eth_dev); 1943d5f39e07SChaoyong He 1944d5f39e07SChaoyong He rte_eth_dev_probing_finish(eth_dev); 1945d5f39e07SChaoyong He } 1946d5f39e07SChaoyong He 1947d5f39e07SChaoyong He return ret; 1948d5f39e07SChaoyong He } 1949d5f39e07SChaoyong He 1950646ea79cSHeinrich Kuhn /* 1951646ea79cSHeinrich Kuhn * When attaching to the NFP4000/6000 PF on a secondary process there 1952646ea79cSHeinrich Kuhn * is no need to initialise the PF again. Only minimal work is required 195340688372SChaoyong He * here. 1954646ea79cSHeinrich Kuhn */ 1955a6189a67SJin Liu static int 1956a6189a67SJin Liu nfp_pf_secondary_init(struct rte_pci_device *pci_dev) 1957646ea79cSHeinrich Kuhn { 19586b4273a0SLong Wu void *sync; 1959968ec1c3SChaoyong He int ret = 0; 1960a6189a67SJin Liu struct nfp_cpp *cpp; 19613b00109dSPeng Zhang uint8_t function_id; 1962016141b1SChaoyong He struct nfp_pf_dev *pf_dev; 1963d5f39e07SChaoyong He enum nfp_app_fw_id app_fw_id; 1964016141b1SChaoyong He char name[RTE_ETH_NAME_MAX_LEN]; 1965a6189a67SJin Liu struct nfp_rtsym_table *sym_tbl; 19660314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 19673b00109dSPeng Zhang char app_name[RTE_ETH_NAME_MAX_LEN]; 1968646ea79cSHeinrich Kuhn 1969a6189a67SJin Liu if (pci_dev == NULL) 1970646ea79cSHeinrich Kuhn return -ENODEV; 1971646ea79cSHeinrich Kuhn 197284aaba5aSChaoyong He if (pci_dev->mem_resource[0].addr == NULL) { 197384aaba5aSChaoyong He PMD_INIT_LOG(ERR, "The address of BAR0 is NULL."); 197484aaba5aSChaoyong He return -ENODEV; 197584aaba5aSChaoyong He } 197684aaba5aSChaoyong He 19770314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 19780314a8ffSChaoyong He if (dev_info == NULL) { 19790314a8ffSChaoyong He PMD_INIT_LOG(ERR, "Not supported device ID"); 19800314a8ffSChaoyong He return -ENODEV; 19810314a8ffSChaoyong He } 19820314a8ffSChaoyong He 1983016141b1SChaoyong He /* Allocate memory for the PF "device" */ 1984016141b1SChaoyong He snprintf(name, sizeof(name), "nfp_pf%d", 0); 1985016141b1SChaoyong He pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); 1986016141b1SChaoyong He if (pf_dev == NULL) { 1987016141b1SChaoyong He PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device"); 1988016141b1SChaoyong He return -ENOMEM; 1989016141b1SChaoyong He } 1990016141b1SChaoyong He 19916b4273a0SLong Wu sync = nfp_sync_alloc(); 19926b4273a0SLong Wu if (sync == NULL) { 19936b4273a0SLong Wu PMD_INIT_LOG(ERR, "Failed to alloc sync zone."); 19946b4273a0SLong Wu ret = -ENOMEM; 19956b4273a0SLong Wu goto pf_cleanup; 19966b4273a0SLong Wu } 19976b4273a0SLong Wu 1998646ea79cSHeinrich Kuhn /* 1999646ea79cSHeinrich Kuhn * When device bound to UIO, the device could be used, by mistake, 2000646ea79cSHeinrich Kuhn * by two DPDK apps, and the UIO driver does not avoid it. This 2001646ea79cSHeinrich Kuhn * could lead to a serious problem when configuring the NFP CPP 2002646ea79cSHeinrich Kuhn * interface. Here we avoid this telling to the CPP init code to 2003646ea79cSHeinrich Kuhn * use a lock file if UIO is being used. 2004646ea79cSHeinrich Kuhn */ 2005646ea79cSHeinrich Kuhn if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) 20061fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false); 2007646ea79cSHeinrich Kuhn else 20081fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true); 2009646ea79cSHeinrich Kuhn 2010a6189a67SJin Liu if (cpp == NULL) { 2011646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "A CPP handle can not be obtained"); 2012016141b1SChaoyong He ret = -EIO; 20136b4273a0SLong Wu goto sync_free; 2014646ea79cSHeinrich Kuhn } 2015646ea79cSHeinrich Kuhn 2016646ea79cSHeinrich Kuhn /* 2017646ea79cSHeinrich Kuhn * We don't have access to the PF created in the primary process 201840688372SChaoyong He * here so we have to read the number of ports from firmware. 2019646ea79cSHeinrich Kuhn */ 2020646ea79cSHeinrich Kuhn sym_tbl = nfp_rtsym_table_read(cpp); 2021a6189a67SJin Liu if (sym_tbl == NULL) { 2022f4d24fe9SChaoyong He PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table"); 2023016141b1SChaoyong He ret = -EIO; 20246b4273a0SLong Wu goto sync_free; 2025646ea79cSHeinrich Kuhn } 2026646ea79cSHeinrich Kuhn 2027d5f39e07SChaoyong He /* Read the app ID of the firmware loaded */ 20283b00109dSPeng Zhang function_id = pci_dev->addr.function & 0x7; 20293b00109dSPeng Zhang snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id); 20303b00109dSPeng Zhang app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret); 2031e7978635SChaoyong He if (ret != 0) { 20323b00109dSPeng Zhang PMD_INIT_LOG(ERR, "Couldn't read %s from fw", app_name); 2033016141b1SChaoyong He ret = -EIO; 2034968ec1c3SChaoyong He goto sym_tbl_cleanup; 2035968ec1c3SChaoyong He } 2036646ea79cSHeinrich Kuhn 2037016141b1SChaoyong He /* Populate the newly created PF device */ 2038016141b1SChaoyong He pf_dev->app_fw_id = app_fw_id; 2039016141b1SChaoyong He pf_dev->cpp = cpp; 2040016141b1SChaoyong He pf_dev->sym_tbl = sym_tbl; 2041016141b1SChaoyong He pf_dev->pci_dev = pci_dev; 20426b4273a0SLong Wu pf_dev->sync = sync; 2043016141b1SChaoyong He 2044016141b1SChaoyong He /* Call app specific init code now */ 2045d5f39e07SChaoyong He switch (app_fw_id) { 2046d5f39e07SChaoyong He case NFP_APP_FW_CORE_NIC: 2047d5f39e07SChaoyong He PMD_INIT_LOG(INFO, "Initializing coreNIC"); 2048016141b1SChaoyong He ret = nfp_secondary_init_app_fw_nic(pf_dev); 2049d5f39e07SChaoyong He if (ret != 0) { 2050d5f39e07SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize coreNIC!"); 2051d5f39e07SChaoyong He goto sym_tbl_cleanup; 2052646ea79cSHeinrich Kuhn } 2053d5f39e07SChaoyong He break; 2054b1880421SChaoyong He case NFP_APP_FW_FLOWER_NIC: 2055b1880421SChaoyong He PMD_INIT_LOG(INFO, "Initializing Flower"); 2056016141b1SChaoyong He ret = nfp_secondary_init_app_fw_flower(pf_dev); 2057b1880421SChaoyong He if (ret != 0) { 2058b1880421SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize Flower!"); 2059b1880421SChaoyong He goto sym_tbl_cleanup; 2060b1880421SChaoyong He } 2061b1880421SChaoyong He break; 2062d5f39e07SChaoyong He default: 2063d5f39e07SChaoyong He PMD_INIT_LOG(ERR, "Unsupported Firmware loaded"); 2064d5f39e07SChaoyong He ret = -EINVAL; 2065d5f39e07SChaoyong He goto sym_tbl_cleanup; 2066646ea79cSHeinrich Kuhn } 2067646ea79cSHeinrich Kuhn 2068016141b1SChaoyong He return 0; 2069016141b1SChaoyong He 2070968ec1c3SChaoyong He sym_tbl_cleanup: 2071968ec1c3SChaoyong He free(sym_tbl); 20726b4273a0SLong Wu sync_free: 20736b4273a0SLong Wu nfp_sync_free(sync); 2074016141b1SChaoyong He pf_cleanup: 2075016141b1SChaoyong He rte_free(pf_dev); 2076968ec1c3SChaoyong He 2077968ec1c3SChaoyong He return ret; 2078646ea79cSHeinrich Kuhn } 2079646ea79cSHeinrich Kuhn 2080a6189a67SJin Liu static int 2081a6189a67SJin Liu nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 2082646ea79cSHeinrich Kuhn struct rte_pci_device *dev) 2083646ea79cSHeinrich Kuhn { 2084646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 2085646ea79cSHeinrich Kuhn return nfp_pf_init(dev); 2086646ea79cSHeinrich Kuhn else 2087646ea79cSHeinrich Kuhn return nfp_pf_secondary_init(dev); 2088646ea79cSHeinrich Kuhn } 2089646ea79cSHeinrich Kuhn 2090646ea79cSHeinrich Kuhn static const struct rte_pci_id pci_id_nfp_pf_net_map[] = { 2091646ea79cSHeinrich Kuhn { 2092646ea79cSHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 20935c464d6aSJin Liu PCI_DEVICE_ID_NFP3800_PF_NIC) 20945c464d6aSJin Liu }, 20955c464d6aSJin Liu { 20965c464d6aSJin Liu RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 2097646ea79cSHeinrich Kuhn PCI_DEVICE_ID_NFP4000_PF_NIC) 2098646ea79cSHeinrich Kuhn }, 2099646ea79cSHeinrich Kuhn { 2100646ea79cSHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 2101646ea79cSHeinrich Kuhn PCI_DEVICE_ID_NFP6000_PF_NIC) 2102646ea79cSHeinrich Kuhn }, 2103646ea79cSHeinrich Kuhn { 21045aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 21055aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP3800_PF_NIC) 21065aedd4c3SJames Hershaw }, 21075aedd4c3SJames Hershaw { 21085aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 21095aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP4000_PF_NIC) 21105aedd4c3SJames Hershaw }, 21115aedd4c3SJames Hershaw { 21125aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 21135aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP6000_PF_NIC) 21145aedd4c3SJames Hershaw }, 21155aedd4c3SJames Hershaw { 2116646ea79cSHeinrich Kuhn .vendor_id = 0, 2117646ea79cSHeinrich Kuhn }, 2118646ea79cSHeinrich Kuhn }; 2119646ea79cSHeinrich Kuhn 2120a6189a67SJin Liu static int 2121a6189a67SJin Liu nfp_pci_uninit(struct rte_eth_dev *eth_dev) 2122646ea79cSHeinrich Kuhn { 2123646ea79cSHeinrich Kuhn uint16_t port_id; 212449952141SChaoyong He struct rte_pci_device *pci_dev; 2125646ea79cSHeinrich Kuhn 2126646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 2127646ea79cSHeinrich Kuhn 2128646ea79cSHeinrich Kuhn /* Free up all physical ports under PF */ 2129646ea79cSHeinrich Kuhn RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) 2130646ea79cSHeinrich Kuhn rte_eth_dev_close(port_id); 2131646ea79cSHeinrich Kuhn /* 2132646ea79cSHeinrich Kuhn * Ports can be closed and freed but hotplugging is not 213340688372SChaoyong He * currently supported. 2134646ea79cSHeinrich Kuhn */ 2135646ea79cSHeinrich Kuhn return -ENOTSUP; 2136646ea79cSHeinrich Kuhn } 2137646ea79cSHeinrich Kuhn 2138a6189a67SJin Liu static int 2139a6189a67SJin Liu eth_nfp_pci_remove(struct rte_pci_device *pci_dev) 2140646ea79cSHeinrich Kuhn { 2141646ea79cSHeinrich Kuhn return rte_eth_dev_pci_generic_remove(pci_dev, nfp_pci_uninit); 2142646ea79cSHeinrich Kuhn } 2143646ea79cSHeinrich Kuhn 2144646ea79cSHeinrich Kuhn static struct rte_pci_driver rte_nfp_net_pf_pmd = { 2145646ea79cSHeinrich Kuhn .id_table = pci_id_nfp_pf_net_map, 2146646ea79cSHeinrich Kuhn .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 2147646ea79cSHeinrich Kuhn .probe = nfp_pf_pci_probe, 2148646ea79cSHeinrich Kuhn .remove = eth_nfp_pci_remove, 2149646ea79cSHeinrich Kuhn }; 2150646ea79cSHeinrich Kuhn 2151d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI(NFP_PF_DRIVER_NAME, rte_nfp_net_pf_pmd); 2152d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI_TABLE(NFP_PF_DRIVER_NAME, pci_id_nfp_pf_net_map); 2153d505ee1dSChaoyong He RTE_PMD_REGISTER_KMOD_DEP(NFP_PF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio"); 2154