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" 17646ea79cSHeinrich Kuhn #include "nfpcore/nfp_hwinfo.h" 18646ea79cSHeinrich Kuhn #include "nfpcore/nfp_rtsym.h" 19646ea79cSHeinrich Kuhn #include "nfpcore/nfp_nsp.h" 20796f1aecSChaoyong He #include "nfpcore/nfp6000_pcie.h" 218ba461d1SPeng Zhang #include "nfpcore/nfp_resource.h" 22646ea79cSHeinrich Kuhn 23646ea79cSHeinrich Kuhn #include "nfp_cpp_bridge.h" 2454713740SChang Miao #include "nfp_ipsec.h" 255a95b024SChaoyong He #include "nfp_logs.h" 268153bc6fSChaoyong He #include "nfp_net_flow.h" 27b1880421SChaoyong He 28c7a6970fSZerun Fu /* 64-bit per app capabilities */ 29c7a6970fSZerun Fu #define NFP_NET_APP_CAP_SP_INDIFF RTE_BIT64(0) /* Indifferent to port speed */ 30c7a6970fSZerun Fu 31d505ee1dSChaoyong He #define NFP_PF_DRIVER_NAME net_nfp_pf 32d505ee1dSChaoyong He 33a243128bSChaoyong He static void 34f4d24fe9SChaoyong He nfp_net_pf_read_mac(struct nfp_app_fw_nic *app_fw_nic, 358ceb85c3SChaoyong He uint16_t port) 36646ea79cSHeinrich Kuhn { 3749952141SChaoyong He struct nfp_net_hw *hw; 38646ea79cSHeinrich Kuhn struct nfp_eth_table *nfp_eth_table; 39646ea79cSHeinrich Kuhn 40646ea79cSHeinrich Kuhn /* Grab a pointer to the correct physical port */ 41968ec1c3SChaoyong He hw = app_fw_nic->ports[port]; 42646ea79cSHeinrich Kuhn 43a243128bSChaoyong He nfp_eth_table = app_fw_nic->pf_dev->nfp_eth_table; 44646ea79cSHeinrich Kuhn 45ef759759SChaoyong He rte_ether_addr_copy(&nfp_eth_table->ports[port].mac_addr, &hw->super.mac_addr); 46646ea79cSHeinrich Kuhn } 47646ea79cSHeinrich Kuhn 48009f43d5SZerun Fu static uint32_t 49009f43d5SZerun Fu nfp_net_speed_bitmap2speed(uint32_t speeds_bitmap) 50009f43d5SZerun Fu { 51009f43d5SZerun Fu switch (speeds_bitmap) { 52009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10M_HD: 53009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10M; 54009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10M: 55009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10M; 56009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100M_HD: 57009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100M; 58009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100M: 59009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100M; 60009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_1G: 61009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_1G; 62009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_2_5G: 63009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_2_5G; 64009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_5G: 65009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_5G; 66009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_10G: 67009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_10G; 68009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_20G: 69009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_20G; 70009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_25G: 71009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_25G; 72009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_40G: 73009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_40G; 74009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_50G: 75009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_50G; 76009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_56G: 77009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_56G; 78009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_100G: 79009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_100G; 80009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_200G: 81009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_200G; 82009f43d5SZerun Fu case RTE_ETH_LINK_SPEED_400G: 83009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_400G; 84009f43d5SZerun Fu default: 85009f43d5SZerun Fu return RTE_ETH_SPEED_NUM_NONE; 86009f43d5SZerun Fu } 87009f43d5SZerun Fu } 88009f43d5SZerun Fu 89009f43d5SZerun Fu static int 90009f43d5SZerun Fu nfp_net_nfp4000_speed_configure_check(uint16_t port_id, 91009f43d5SZerun Fu uint32_t configure_speed, 92009f43d5SZerun Fu struct nfp_eth_table *nfp_eth_table) 93009f43d5SZerun Fu { 94009f43d5SZerun Fu switch (port_id) { 95009f43d5SZerun Fu case 0: 96009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_25G && 97009f43d5SZerun Fu nfp_eth_table->ports[1].speed == RTE_ETH_SPEED_NUM_10G) { 98009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000."); 99009f43d5SZerun Fu return -ENOTSUP; 100009f43d5SZerun Fu } 101009f43d5SZerun Fu break; 102009f43d5SZerun Fu case 1: 103009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_10G && 104009f43d5SZerun Fu nfp_eth_table->ports[0].speed == RTE_ETH_SPEED_NUM_25G) { 105009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The speed configuration is not supported for NFP4000."); 106009f43d5SZerun Fu return -ENOTSUP; 107009f43d5SZerun Fu } 108009f43d5SZerun Fu break; 109009f43d5SZerun Fu default: 110009f43d5SZerun Fu PMD_DRV_LOG(ERR, "The port id is invalid."); 111009f43d5SZerun Fu return -EINVAL; 112009f43d5SZerun Fu } 113009f43d5SZerun Fu 114009f43d5SZerun Fu return 0; 115009f43d5SZerun Fu } 116009f43d5SZerun Fu 117009f43d5SZerun Fu static int 118009f43d5SZerun Fu nfp_net_speed_configure(struct rte_eth_dev *dev, 119009f43d5SZerun Fu struct nfp_net_hw *net_hw) 120009f43d5SZerun Fu { 121009f43d5SZerun Fu int ret; 122009f43d5SZerun Fu uint32_t speed_capa; 123009f43d5SZerun Fu struct nfp_nsp *nsp; 124009f43d5SZerun Fu uint32_t link_speeds; 125009f43d5SZerun Fu uint32_t configure_speed; 126009f43d5SZerun Fu struct nfp_eth_table_port *eth_port; 127009f43d5SZerun Fu struct nfp_eth_table *nfp_eth_table; 128009f43d5SZerun Fu 129009f43d5SZerun Fu nfp_eth_table = net_hw->pf_dev->nfp_eth_table; 130009f43d5SZerun Fu eth_port = &nfp_eth_table->ports[net_hw->idx]; 131009f43d5SZerun Fu 132009f43d5SZerun Fu speed_capa = net_hw->pf_dev->speed_capa; 133009f43d5SZerun Fu if (speed_capa == 0) { 134009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Speed_capa is invalid."); 135009f43d5SZerun Fu return -EINVAL; 136009f43d5SZerun Fu } 137009f43d5SZerun Fu 138009f43d5SZerun Fu link_speeds = dev->data->dev_conf.link_speeds; 139009f43d5SZerun Fu configure_speed = nfp_net_speed_bitmap2speed(speed_capa & link_speeds); 140009f43d5SZerun Fu if (configure_speed == RTE_ETH_SPEED_NUM_NONE && 141009f43d5SZerun Fu link_speeds != RTE_ETH_LINK_SPEED_AUTONEG) { 142009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Configured speed is invalid."); 143009f43d5SZerun Fu return -EINVAL; 144009f43d5SZerun Fu } 145009f43d5SZerun Fu 146009f43d5SZerun Fu /* NFP4000 does not allow the port 0 25Gbps and port 1 10Gbps at the same time. */ 147009f43d5SZerun Fu if (net_hw->device_id == PCI_DEVICE_ID_NFP4000_PF_NIC) { 148009f43d5SZerun Fu ret = nfp_net_nfp4000_speed_configure_check(net_hw->idx, 149009f43d5SZerun Fu configure_speed, nfp_eth_table); 150009f43d5SZerun Fu if (ret != 0) { 151009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to configure speed for NFP4000."); 152009f43d5SZerun Fu return ret; 153009f43d5SZerun Fu } 154009f43d5SZerun Fu } 155009f43d5SZerun Fu 156009f43d5SZerun Fu nsp = nfp_eth_config_start(net_hw->cpp, eth_port->index); 157009f43d5SZerun Fu if (nsp == NULL) { 158009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Couldn't get NSP."); 159009f43d5SZerun Fu return -EIO; 160009f43d5SZerun Fu } 161009f43d5SZerun Fu 162009f43d5SZerun Fu if (link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { 163009f43d5SZerun Fu if (eth_port->supp_aneg) { 164009f43d5SZerun Fu ret = nfp_eth_set_aneg(nsp, NFP_ANEG_AUTO); 165009f43d5SZerun Fu if (ret != 0) { 166009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set ANEG enable."); 167009f43d5SZerun Fu goto config_cleanup; 168009f43d5SZerun Fu } 169009f43d5SZerun Fu } 170009f43d5SZerun Fu } else { 171009f43d5SZerun Fu ret = nfp_eth_set_aneg(nsp, NFP_ANEG_DISABLED); 172009f43d5SZerun Fu if (ret != 0) { 173009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set ANEG disable."); 174009f43d5SZerun Fu goto config_cleanup; 175009f43d5SZerun Fu } 176009f43d5SZerun Fu 177009f43d5SZerun Fu ret = nfp_eth_set_speed(nsp, configure_speed); 178009f43d5SZerun Fu if (ret != 0) { 179009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set speed."); 180009f43d5SZerun Fu goto config_cleanup; 181009f43d5SZerun Fu } 182009f43d5SZerun Fu } 183009f43d5SZerun Fu 184009f43d5SZerun Fu return nfp_eth_config_commit_end(nsp); 185009f43d5SZerun Fu 186009f43d5SZerun Fu config_cleanup: 187009f43d5SZerun Fu nfp_eth_config_cleanup_end(nsp); 188009f43d5SZerun Fu 189009f43d5SZerun Fu return ret; 190009f43d5SZerun Fu } 191009f43d5SZerun Fu 192646ea79cSHeinrich Kuhn static int 193646ea79cSHeinrich Kuhn nfp_net_start(struct rte_eth_dev *dev) 194646ea79cSHeinrich Kuhn { 19549952141SChaoyong He int ret; 19649952141SChaoyong He uint16_t i; 19772d1dea6SChaoyong He struct nfp_hw *hw; 19849952141SChaoyong He uint32_t new_ctrl; 199acb6bebfSChaoyong He struct nfp_cpp *cpp; 20049952141SChaoyong He uint32_t update = 0; 2012e7c3612SQin Ke uint32_t cap_extend; 20249952141SChaoyong He uint32_t intr_vector; 20349952141SChaoyong He uint32_t ctrl_extend = 0; 20472d1dea6SChaoyong He struct nfp_net_hw *net_hw; 205646ea79cSHeinrich Kuhn struct nfp_pf_dev *pf_dev; 206646ea79cSHeinrich Kuhn struct rte_eth_rxmode *rxmode; 20749952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 20849952141SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 20949952141SChaoyong He struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 210646ea79cSHeinrich Kuhn 2119d723baaSChaoyong He net_hw = dev->data->dev_private; 21265f6915dSChaoyong He pf_dev = net_hw->pf_dev; 213968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 21472d1dea6SChaoyong He hw = &net_hw->super; 215646ea79cSHeinrich Kuhn 216646ea79cSHeinrich Kuhn /* Disabling queues just in case... */ 217646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 218646ea79cSHeinrich Kuhn 219646ea79cSHeinrich Kuhn /* Enabling the required queues in the device */ 220646ea79cSHeinrich Kuhn nfp_net_enable_queues(dev); 221646ea79cSHeinrich Kuhn 222009f43d5SZerun Fu /* Configure the port speed and the auto-negotiation mode. */ 223009f43d5SZerun Fu ret = nfp_net_speed_configure(dev, net_hw); 224009f43d5SZerun Fu if (ret < 0) { 225009f43d5SZerun Fu PMD_DRV_LOG(ERR, "Failed to set the speed and auto-negotiation mode."); 226009f43d5SZerun Fu return ret; 227009f43d5SZerun Fu } 228009f43d5SZerun Fu 22940688372SChaoyong He /* Check and configure queue intr-vector mapping */ 230646ea79cSHeinrich Kuhn if (dev->data->dev_conf.intr_conf.rxq != 0) { 231968ec1c3SChaoyong He if (app_fw_nic->multiport) { 232646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt is not supported " 233646ea79cSHeinrich Kuhn "with NFP multiport PF"); 234646ea79cSHeinrich Kuhn return -EINVAL; 235646ea79cSHeinrich Kuhn } 236b0c496abSChaoyong He 237f4d24fe9SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 238646ea79cSHeinrich Kuhn /* 239646ea79cSHeinrich Kuhn * Better not to share LSC with RX interrupts. 24040688372SChaoyong He * Unregistering LSC interrupt handler. 241646ea79cSHeinrich Kuhn */ 242e7978635SChaoyong He rte_intr_callback_unregister(intr_handle, 243646ea79cSHeinrich Kuhn nfp_net_dev_interrupt_handler, (void *)dev); 244646ea79cSHeinrich Kuhn 245646ea79cSHeinrich Kuhn if (dev->data->nb_rx_queues > 1) { 246646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt only " 247646ea79cSHeinrich Kuhn "supports 1 queue with UIO"); 248646ea79cSHeinrich Kuhn return -EIO; 249646ea79cSHeinrich Kuhn } 250646ea79cSHeinrich Kuhn } 251b0c496abSChaoyong He 252646ea79cSHeinrich Kuhn intr_vector = dev->data->nb_rx_queues; 253c01e5c0cSChaoyong He if (rte_intr_efd_enable(intr_handle, intr_vector) != 0) 254646ea79cSHeinrich Kuhn return -1; 255646ea79cSHeinrich Kuhn 256646ea79cSHeinrich Kuhn nfp_configure_rx_interrupt(dev, intr_handle); 257646ea79cSHeinrich Kuhn update = NFP_NET_CFG_UPDATE_MSIX; 258646ea79cSHeinrich Kuhn } 259646ea79cSHeinrich Kuhn 260dbad6f64SPeng Zhang /* Checking MTU set */ 26172d1dea6SChaoyong He if (dev->data->mtu > net_hw->flbufsz) { 262dbad6f64SPeng Zhang PMD_INIT_LOG(ERR, "MTU (%u) can't be larger than the current NFP_FRAME_SIZE (%u)", 26372d1dea6SChaoyong He dev->data->mtu, net_hw->flbufsz); 264dbad6f64SPeng Zhang return -ERANGE; 265dbad6f64SPeng Zhang } 266dbad6f64SPeng Zhang 267646ea79cSHeinrich Kuhn rte_intr_enable(intr_handle); 268646ea79cSHeinrich Kuhn 269646ea79cSHeinrich Kuhn new_ctrl = nfp_check_offloads(dev); 270646ea79cSHeinrich Kuhn 271646ea79cSHeinrich Kuhn /* Writing configuration parameters in the device */ 27272d1dea6SChaoyong He nfp_net_params_setup(net_hw); 273646ea79cSHeinrich Kuhn 274c4de52ecSChaoyong He rxmode = &dev->data->dev_conf.rxmode; 275c01e5c0cSChaoyong He if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS) != 0) { 276646ea79cSHeinrich Kuhn nfp_net_rss_config_default(dev); 277646ea79cSHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_RSS; 27872d1dea6SChaoyong He new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap); 279646ea79cSHeinrich Kuhn } 280646ea79cSHeinrich Kuhn 281646ea79cSHeinrich Kuhn /* Enable device */ 282646ea79cSHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; 283646ea79cSHeinrich Kuhn 284646ea79cSHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING; 285646ea79cSHeinrich Kuhn 286c55abf61SChaoyong He /* Enable vxlan */ 28772d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_VXLAN) != 0) { 288c55abf61SChaoyong He new_ctrl |= NFP_NET_CFG_CTRL_VXLAN; 289c55abf61SChaoyong He update |= NFP_NET_CFG_UPDATE_VXLAN; 290c925a157SFei Qin } 291c55abf61SChaoyong He 29272d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0) 293646ea79cSHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; 294646ea79cSHeinrich Kuhn 29572d1dea6SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) 296646ea79cSHeinrich Kuhn return -EIO; 297646ea79cSHeinrich Kuhn 2981e80c074SChaoyong He hw->ctrl = new_ctrl; 2991e80c074SChaoyong He 3002e7c3612SQin Ke /* Enable packet type offload by extend ctrl word1. */ 30172d1dea6SChaoyong He cap_extend = hw->cap_ext; 3022e7c3612SQin Ke if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0) 3032e7c3612SQin Ke ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE; 3042e7c3612SQin Ke 30554713740SChang Miao if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) 3069177c800SChaoyong He ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC | 3079177c800SChaoyong He NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP | 3089177c800SChaoyong He NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP; 30954713740SChang Miao 3108153bc6fSChaoyong He /* Enable flow steer by extend ctrl word1. */ 3118153bc6fSChaoyong He if ((cap_extend & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) 3128153bc6fSChaoyong He ctrl_extend |= NFP_NET_CFG_CTRL_FLOW_STEER; 3138153bc6fSChaoyong He 3142e7c3612SQin Ke update = NFP_NET_CFG_UPDATE_GEN; 31572d1dea6SChaoyong He if (nfp_ext_reconfig(hw, ctrl_extend, update) != 0) 3162e7c3612SQin Ke return -EIO; 3172e7c3612SQin Ke 31872d1dea6SChaoyong He hw->ctrl_ext = ctrl_extend; 319b4b6988aSChaoyong He 320646ea79cSHeinrich Kuhn /* 321646ea79cSHeinrich Kuhn * Allocating rte mbufs for configured rx queues. 32240688372SChaoyong He * This requires queues being enabled before. 323646ea79cSHeinrich Kuhn */ 324c01e5c0cSChaoyong He if (nfp_net_rx_freelist_setup(dev) != 0) { 325646ea79cSHeinrich Kuhn ret = -ENOMEM; 326646ea79cSHeinrich Kuhn goto error; 327646ea79cSHeinrich Kuhn } 328646ea79cSHeinrich Kuhn 329646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 330acb6bebfSChaoyong He cpp = net_hw->cpp; 331646ea79cSHeinrich Kuhn else 332acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 333acb6bebfSChaoyong He 334acb6bebfSChaoyong He /* Configure the physical port up */ 335acb6bebfSChaoyong He nfp_eth_set_configured(cpp, net_hw->nfp_idx, 1); 336646ea79cSHeinrich Kuhn 337c46216e7SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 338c46216e7SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 339c46216e7SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 340c46216e7SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 341c46216e7SJie Hai 342646ea79cSHeinrich Kuhn return 0; 343646ea79cSHeinrich Kuhn 344646ea79cSHeinrich Kuhn error: 345646ea79cSHeinrich Kuhn /* 346646ea79cSHeinrich Kuhn * An error returned by this function should mean the app 347646ea79cSHeinrich Kuhn * exiting and then the system releasing all the memory 348646ea79cSHeinrich Kuhn * allocated even memory coming from hugepages. 349646ea79cSHeinrich Kuhn * 350646ea79cSHeinrich Kuhn * The device could be enabled at this point with some queues 351646ea79cSHeinrich Kuhn * ready for getting packets. This is true if the call to 352646ea79cSHeinrich Kuhn * nfp_net_rx_freelist_setup() succeeds for some queues but 353646ea79cSHeinrich Kuhn * fails for subsequent queues. 354646ea79cSHeinrich Kuhn * 355646ea79cSHeinrich Kuhn * This should make the app exiting but better if we tell the 356646ea79cSHeinrich Kuhn * device first. 357646ea79cSHeinrich Kuhn */ 358646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 359646ea79cSHeinrich Kuhn 360646ea79cSHeinrich Kuhn return ret; 361646ea79cSHeinrich Kuhn } 362646ea79cSHeinrich Kuhn 363646ea79cSHeinrich Kuhn /* Set the link up. */ 364646ea79cSHeinrich Kuhn static int 365646ea79cSHeinrich Kuhn nfp_net_set_link_up(struct rte_eth_dev *dev) 366646ea79cSHeinrich Kuhn { 367acb6bebfSChaoyong He struct nfp_cpp *cpp; 368646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 369646ea79cSHeinrich Kuhn 3709d723baaSChaoyong He hw = dev->data->dev_private; 371646ea79cSHeinrich Kuhn 372646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 373acb6bebfSChaoyong He cpp = hw->cpp; 374646ea79cSHeinrich Kuhn else 375acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 376acb6bebfSChaoyong He 377acb6bebfSChaoyong He return nfp_eth_set_configured(cpp, hw->nfp_idx, 1); 378646ea79cSHeinrich Kuhn } 379646ea79cSHeinrich Kuhn 380646ea79cSHeinrich Kuhn /* Set the link down. */ 381646ea79cSHeinrich Kuhn static int 382646ea79cSHeinrich Kuhn nfp_net_set_link_down(struct rte_eth_dev *dev) 383646ea79cSHeinrich Kuhn { 384acb6bebfSChaoyong He struct nfp_cpp *cpp; 385646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 386646ea79cSHeinrich Kuhn 3879d723baaSChaoyong He hw = dev->data->dev_private; 388646ea79cSHeinrich Kuhn 389646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 390acb6bebfSChaoyong He cpp = hw->cpp; 391646ea79cSHeinrich Kuhn else 392acb6bebfSChaoyong He cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp; 393acb6bebfSChaoyong He 394acb6bebfSChaoyong He return nfp_eth_set_configured(cpp, hw->nfp_idx, 0); 395646ea79cSHeinrich Kuhn } 396646ea79cSHeinrich Kuhn 3973b00109dSPeng Zhang static uint8_t 3983b00109dSPeng Zhang nfp_function_id_get(const struct nfp_pf_dev *pf_dev, 3993b00109dSPeng Zhang uint8_t phy_port) 4003b00109dSPeng Zhang { 4013b00109dSPeng Zhang if (pf_dev->multi_pf.enabled) 4023b00109dSPeng Zhang return pf_dev->multi_pf.function_id; 4033b00109dSPeng Zhang 4043b00109dSPeng Zhang return phy_port; 4053b00109dSPeng Zhang } 4063b00109dSPeng Zhang 4078ba461d1SPeng Zhang static void 4088ba461d1SPeng Zhang nfp_net_beat_timer(void *arg) 4098ba461d1SPeng Zhang { 4108ba461d1SPeng Zhang uint64_t cur_sec; 4118ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf = arg; 4128ba461d1SPeng Zhang 4138ba461d1SPeng Zhang cur_sec = rte_rdtsc(); 4148ba461d1SPeng Zhang nn_writeq(cur_sec, multi_pf->beat_addr + NFP_BEAT_OFFSET(multi_pf->function_id)); 4158ba461d1SPeng Zhang 4168ba461d1SPeng Zhang /* Beat once per second. */ 4178ba461d1SPeng Zhang if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer, 4188ba461d1SPeng Zhang (void *)multi_pf) < 0) { 4198ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Error setting alarm"); 4208ba461d1SPeng Zhang } 4218ba461d1SPeng Zhang } 4228ba461d1SPeng Zhang 4238ba461d1SPeng Zhang static int 4248ba461d1SPeng Zhang nfp_net_keepalive_init(struct nfp_cpp *cpp, 4258ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 4268ba461d1SPeng Zhang { 4278ba461d1SPeng Zhang uint8_t *base; 4288ba461d1SPeng Zhang uint64_t addr; 4298ba461d1SPeng Zhang uint32_t size; 4308ba461d1SPeng Zhang uint32_t cpp_id; 4318ba461d1SPeng Zhang struct nfp_resource *res; 4328ba461d1SPeng Zhang 4338ba461d1SPeng Zhang res = nfp_resource_acquire(cpp, NFP_RESOURCE_KEEPALIVE); 4348ba461d1SPeng Zhang if (res == NULL) 4358ba461d1SPeng Zhang return -EIO; 4368ba461d1SPeng Zhang 4378ba461d1SPeng Zhang cpp_id = nfp_resource_cpp_id(res); 4388ba461d1SPeng Zhang addr = nfp_resource_address(res); 4398ba461d1SPeng Zhang size = nfp_resource_size(res); 4408ba461d1SPeng Zhang 4418ba461d1SPeng Zhang nfp_resource_release(res); 4428ba461d1SPeng Zhang 4438ba461d1SPeng Zhang /* Allocate a fixed area for keepalive. */ 4448ba461d1SPeng Zhang base = nfp_cpp_map_area(cpp, cpp_id, addr, size, &multi_pf->beat_area); 4458ba461d1SPeng Zhang if (base == NULL) { 4468ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Failed to map area for keepalive."); 4478ba461d1SPeng Zhang return -EIO; 4488ba461d1SPeng Zhang } 4498ba461d1SPeng Zhang 4508ba461d1SPeng Zhang multi_pf->beat_addr = base; 4518ba461d1SPeng Zhang 4528ba461d1SPeng Zhang return 0; 4538ba461d1SPeng Zhang } 4548ba461d1SPeng Zhang 4558ba461d1SPeng Zhang static void 4568ba461d1SPeng Zhang nfp_net_keepalive_uninit(struct nfp_multi_pf *multi_pf) 4578ba461d1SPeng Zhang { 4588ba461d1SPeng Zhang nfp_cpp_area_release_free(multi_pf->beat_area); 4598ba461d1SPeng Zhang } 4608ba461d1SPeng Zhang 4618ba461d1SPeng Zhang static int 4628ba461d1SPeng Zhang nfp_net_keepalive_start(struct nfp_multi_pf *multi_pf) 4638ba461d1SPeng Zhang { 4648ba461d1SPeng Zhang if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer, 4658ba461d1SPeng Zhang (void *)multi_pf) < 0) { 4668ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "Error setting alarm"); 4678ba461d1SPeng Zhang return -EIO; 4688ba461d1SPeng Zhang } 4698ba461d1SPeng Zhang 4708ba461d1SPeng Zhang return 0; 4718ba461d1SPeng Zhang } 4728ba461d1SPeng Zhang 4738ba461d1SPeng Zhang static void 474*b67a7b40SPeng Zhang nfp_net_keepalive_clear(uint8_t *beat_addr, 475*b67a7b40SPeng Zhang uint8_t function_id) 476*b67a7b40SPeng Zhang { 477*b67a7b40SPeng Zhang nn_writeq(0, beat_addr + NFP_BEAT_OFFSET(function_id)); 478*b67a7b40SPeng Zhang } 479*b67a7b40SPeng Zhang 480*b67a7b40SPeng Zhang static void 481*b67a7b40SPeng Zhang nfp_net_keepalive_clear_others(const struct nfp_dev_info *dev_info, 482*b67a7b40SPeng Zhang struct nfp_multi_pf *multi_pf) 483*b67a7b40SPeng Zhang { 484*b67a7b40SPeng Zhang uint8_t port_num; 485*b67a7b40SPeng Zhang 486*b67a7b40SPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 487*b67a7b40SPeng Zhang if (port_num == multi_pf->function_id) 488*b67a7b40SPeng Zhang continue; 489*b67a7b40SPeng Zhang 490*b67a7b40SPeng Zhang nfp_net_keepalive_clear(multi_pf->beat_addr, port_num); 491*b67a7b40SPeng Zhang } 492*b67a7b40SPeng Zhang } 493*b67a7b40SPeng Zhang 494*b67a7b40SPeng Zhang static void 4958ba461d1SPeng Zhang nfp_net_keepalive_stop(struct nfp_multi_pf *multi_pf) 4968ba461d1SPeng Zhang { 4978ba461d1SPeng Zhang /* Cancel keepalive for multiple PF setup */ 4988ba461d1SPeng Zhang rte_eal_alarm_cancel(nfp_net_beat_timer, (void *)multi_pf); 4998ba461d1SPeng Zhang } 5008ba461d1SPeng Zhang 5018b8f116bSChaoyong He static void 5028b8f116bSChaoyong He nfp_net_uninit(struct rte_eth_dev *eth_dev) 5038b8f116bSChaoyong He { 5048b8f116bSChaoyong He struct nfp_net_hw *net_hw; 5058b8f116bSChaoyong He 5068b8f116bSChaoyong He net_hw = eth_dev->data->dev_private; 5078153bc6fSChaoyong He 5088153bc6fSChaoyong He if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) 5098153bc6fSChaoyong He nfp_net_flow_priv_uninit(net_hw->pf_dev, net_hw->idx); 5108153bc6fSChaoyong He 5118b8f116bSChaoyong He rte_free(net_hw->eth_xstats_base); 5128b8f116bSChaoyong He nfp_ipsec_uninit(eth_dev); 5138b8f116bSChaoyong He if (net_hw->mac_stats_area != NULL) 5148b8f116bSChaoyong He nfp_cpp_area_release_free(net_hw->mac_stats_area); 5158b8f116bSChaoyong He } 5168b8f116bSChaoyong He 51766d5f53dSChaoyong He static void 51866d5f53dSChaoyong He nfp_cleanup_port_app_fw_nic(struct nfp_pf_dev *pf_dev, 51966d5f53dSChaoyong He uint8_t id) 52066d5f53dSChaoyong He { 52166d5f53dSChaoyong He struct rte_eth_dev *eth_dev; 52266d5f53dSChaoyong He struct nfp_app_fw_nic *app_fw_nic; 52366d5f53dSChaoyong He 52466d5f53dSChaoyong He app_fw_nic = pf_dev->app_fw_priv; 52566d5f53dSChaoyong He if (app_fw_nic->ports[id] != NULL) { 52666d5f53dSChaoyong He eth_dev = app_fw_nic->ports[id]->eth_dev; 52766d5f53dSChaoyong He if (eth_dev != NULL) 52866d5f53dSChaoyong He nfp_net_uninit(eth_dev); 52966d5f53dSChaoyong He 53066d5f53dSChaoyong He app_fw_nic->ports[id] = NULL; 53166d5f53dSChaoyong He } 53266d5f53dSChaoyong He } 53366d5f53dSChaoyong He 53466d5f53dSChaoyong He static void 53566d5f53dSChaoyong He nfp_uninit_app_fw_nic(struct nfp_pf_dev *pf_dev) 53666d5f53dSChaoyong He { 53766d5f53dSChaoyong He nfp_cpp_area_release_free(pf_dev->ctrl_area); 53866d5f53dSChaoyong He rte_free(pf_dev->app_fw_priv); 53966d5f53dSChaoyong He } 54066d5f53dSChaoyong He 54166d5f53dSChaoyong He void 54266d5f53dSChaoyong He nfp_pf_uninit(struct nfp_pf_dev *pf_dev) 54366d5f53dSChaoyong He { 54466d5f53dSChaoyong He nfp_cpp_area_release_free(pf_dev->qc_area); 54566d5f53dSChaoyong He free(pf_dev->sym_tbl); 54666d5f53dSChaoyong He if (pf_dev->multi_pf.enabled) { 54766d5f53dSChaoyong He nfp_net_keepalive_stop(&pf_dev->multi_pf); 548*b67a7b40SPeng Zhang nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id); 54966d5f53dSChaoyong He nfp_net_keepalive_uninit(&pf_dev->multi_pf); 55066d5f53dSChaoyong He } 55166d5f53dSChaoyong He free(pf_dev->nfp_eth_table); 55266d5f53dSChaoyong He free(pf_dev->hwinfo); 55366d5f53dSChaoyong He nfp_cpp_free(pf_dev->cpp); 55466d5f53dSChaoyong He rte_free(pf_dev); 55566d5f53dSChaoyong He } 55666d5f53dSChaoyong He 55766d5f53dSChaoyong He static int 55866d5f53dSChaoyong He nfp_pf_secondary_uninit(struct nfp_pf_dev *pf_dev) 55966d5f53dSChaoyong He { 56066d5f53dSChaoyong He free(pf_dev->sym_tbl); 56166d5f53dSChaoyong He nfp_cpp_free(pf_dev->cpp); 56266d5f53dSChaoyong He rte_free(pf_dev); 56366d5f53dSChaoyong He 56466d5f53dSChaoyong He return 0; 56566d5f53dSChaoyong He } 56666d5f53dSChaoyong He 567646ea79cSHeinrich Kuhn /* Reset and stop device. The device can not be restarted. */ 568646ea79cSHeinrich Kuhn static int 569646ea79cSHeinrich Kuhn nfp_net_close(struct rte_eth_dev *dev) 570646ea79cSHeinrich Kuhn { 5718ceb85c3SChaoyong He uint8_t i; 5723b00109dSPeng Zhang uint8_t id; 57349952141SChaoyong He struct nfp_net_hw *hw; 57449952141SChaoyong He struct nfp_pf_dev *pf_dev; 57549952141SChaoyong He struct rte_pci_device *pci_dev; 57649952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 577646ea79cSHeinrich Kuhn 57866d5f53dSChaoyong He /* 57966d5f53dSChaoyong He * In secondary process, a released eth device can be found by its name 58066d5f53dSChaoyong He * in shared memory. 58166d5f53dSChaoyong He * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the 58266d5f53dSChaoyong He * eth device has been released. 58366d5f53dSChaoyong He */ 58466d5f53dSChaoyong He if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 58566d5f53dSChaoyong He if (dev->state == RTE_ETH_DEV_UNUSED) 586646ea79cSHeinrich Kuhn return 0; 587646ea79cSHeinrich Kuhn 58866d5f53dSChaoyong He nfp_pf_secondary_uninit(dev->process_private); 58966d5f53dSChaoyong He return 0; 59066d5f53dSChaoyong He } 59166d5f53dSChaoyong He 5929d723baaSChaoyong He hw = dev->data->dev_private; 59365f6915dSChaoyong He pf_dev = hw->pf_dev; 594646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(dev); 595968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 596646ea79cSHeinrich Kuhn 597646ea79cSHeinrich Kuhn /* 598646ea79cSHeinrich Kuhn * We assume that the DPDK application is stopping all the 599646ea79cSHeinrich Kuhn * threads/queues before calling the device close function. 600646ea79cSHeinrich Kuhn */ 601646ea79cSHeinrich Kuhn nfp_net_disable_queues(dev); 602646ea79cSHeinrich Kuhn 603646ea79cSHeinrich Kuhn /* Clear queues */ 6041c8d02bbSJin Liu nfp_net_close_tx_queue(dev); 6051c8d02bbSJin Liu nfp_net_close_rx_queue(dev); 606646ea79cSHeinrich Kuhn 607851f03e1SHeinrich Kuhn /* Cancel possible impending LSC work here before releasing the port */ 608f4d24fe9SChaoyong He rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev); 609851f03e1SHeinrich Kuhn 610646ea79cSHeinrich Kuhn /* Only free PF resources after all physical ports have been closed */ 611646ea79cSHeinrich Kuhn /* Mark this port as unused and free device priv resources */ 612f58bde00SChaoyong He nn_cfg_writeb(&hw->super, NFP_NET_CFG_LSC, 0xff); 61366d5f53dSChaoyong He 61466d5f53dSChaoyong He if (pf_dev->app_fw_id != NFP_APP_FW_CORE_NIC) 61566d5f53dSChaoyong He return -EINVAL; 61666d5f53dSChaoyong He 61766d5f53dSChaoyong He nfp_cleanup_port_app_fw_nic(pf_dev, hw->idx); 618646ea79cSHeinrich Kuhn 619968ec1c3SChaoyong He for (i = 0; i < app_fw_nic->total_phyports; i++) { 6203b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 6213b00109dSPeng Zhang 622646ea79cSHeinrich Kuhn /* Check to see if ports are still in use */ 6233b00109dSPeng Zhang if (app_fw_nic->ports[id] != NULL) 624646ea79cSHeinrich Kuhn return 0; 625646ea79cSHeinrich Kuhn } 626646ea79cSHeinrich Kuhn 62766d5f53dSChaoyong He /* Enable in nfp_net_start() */ 628d61138d4SHarman Kalra rte_intr_disable(pci_dev->intr_handle); 629646ea79cSHeinrich Kuhn 63066d5f53dSChaoyong He /* Register in nfp_net_init() */ 631d61138d4SHarman Kalra rte_intr_callback_unregister(pci_dev->intr_handle, 632a6189a67SJin Liu nfp_net_dev_interrupt_handler, (void *)dev); 633646ea79cSHeinrich Kuhn 63466d5f53dSChaoyong He nfp_uninit_app_fw_nic(pf_dev); 63566d5f53dSChaoyong He nfp_pf_uninit(pf_dev); 63666d5f53dSChaoyong He 637646ea79cSHeinrich Kuhn return 0; 638646ea79cSHeinrich Kuhn } 639646ea79cSHeinrich Kuhn 640c55abf61SChaoyong He static int 641c55abf61SChaoyong He nfp_net_find_vxlan_idx(struct nfp_net_hw *hw, 642c55abf61SChaoyong He uint16_t port, 643c55abf61SChaoyong He uint32_t *idx) 644c55abf61SChaoyong He { 645c55abf61SChaoyong He uint32_t i; 646c55abf61SChaoyong He int free_idx = -1; 647c55abf61SChaoyong He 648c55abf61SChaoyong He for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i++) { 649c55abf61SChaoyong He if (hw->vxlan_ports[i] == port) { 650c55abf61SChaoyong He free_idx = i; 651c55abf61SChaoyong He break; 652c55abf61SChaoyong He } 653c55abf61SChaoyong He 654c55abf61SChaoyong He if (hw->vxlan_usecnt[i] == 0) { 655c55abf61SChaoyong He free_idx = i; 656c55abf61SChaoyong He break; 657c55abf61SChaoyong He } 658c55abf61SChaoyong He } 659c55abf61SChaoyong He 660c55abf61SChaoyong He if (free_idx == -1) 661c55abf61SChaoyong He return -EINVAL; 662c55abf61SChaoyong He 663c55abf61SChaoyong He *idx = free_idx; 664c55abf61SChaoyong He 665c55abf61SChaoyong He return 0; 666c55abf61SChaoyong He } 667c55abf61SChaoyong He 668c55abf61SChaoyong He static int 669c55abf61SChaoyong He nfp_udp_tunnel_port_add(struct rte_eth_dev *dev, 670c55abf61SChaoyong He struct rte_eth_udp_tunnel *tunnel_udp) 671c55abf61SChaoyong He { 672c55abf61SChaoyong He int ret; 673c55abf61SChaoyong He uint32_t idx; 674c55abf61SChaoyong He uint16_t vxlan_port; 675c55abf61SChaoyong He struct nfp_net_hw *hw; 676c55abf61SChaoyong He enum rte_eth_tunnel_type tnl_type; 677c55abf61SChaoyong He 6789d723baaSChaoyong He hw = dev->data->dev_private; 679c55abf61SChaoyong He vxlan_port = tunnel_udp->udp_port; 680c55abf61SChaoyong He tnl_type = tunnel_udp->prot_type; 681c55abf61SChaoyong He 682c55abf61SChaoyong He if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) { 683c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Not VXLAN tunnel"); 684c55abf61SChaoyong He return -ENOTSUP; 685c55abf61SChaoyong He } 686c55abf61SChaoyong He 687c55abf61SChaoyong He ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx); 688c55abf61SChaoyong He if (ret != 0) { 689c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed find valid vxlan idx"); 690c55abf61SChaoyong He return -EINVAL; 691c55abf61SChaoyong He } 692c55abf61SChaoyong He 693c55abf61SChaoyong He if (hw->vxlan_usecnt[idx] == 0) { 694c55abf61SChaoyong He ret = nfp_net_set_vxlan_port(hw, idx, vxlan_port); 695c55abf61SChaoyong He if (ret != 0) { 696c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed set vxlan port"); 697c55abf61SChaoyong He return -EINVAL; 698c55abf61SChaoyong He } 699c55abf61SChaoyong He } 700c55abf61SChaoyong He 701c55abf61SChaoyong He hw->vxlan_usecnt[idx]++; 702c55abf61SChaoyong He 703c55abf61SChaoyong He return 0; 704c55abf61SChaoyong He } 705c55abf61SChaoyong He 706c55abf61SChaoyong He static int 707c55abf61SChaoyong He nfp_udp_tunnel_port_del(struct rte_eth_dev *dev, 708c55abf61SChaoyong He struct rte_eth_udp_tunnel *tunnel_udp) 709c55abf61SChaoyong He { 710c55abf61SChaoyong He int ret; 711c55abf61SChaoyong He uint32_t idx; 712c55abf61SChaoyong He uint16_t vxlan_port; 713c55abf61SChaoyong He struct nfp_net_hw *hw; 714c55abf61SChaoyong He enum rte_eth_tunnel_type tnl_type; 715c55abf61SChaoyong He 7169d723baaSChaoyong He hw = dev->data->dev_private; 717c55abf61SChaoyong He vxlan_port = tunnel_udp->udp_port; 718c55abf61SChaoyong He tnl_type = tunnel_udp->prot_type; 719c55abf61SChaoyong He 720c55abf61SChaoyong He if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) { 721c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Not VXLAN tunnel"); 722c55abf61SChaoyong He return -ENOTSUP; 723c55abf61SChaoyong He } 724c55abf61SChaoyong He 725c55abf61SChaoyong He ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx); 726c55abf61SChaoyong He if (ret != 0 || hw->vxlan_usecnt[idx] == 0) { 727c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed find valid vxlan idx"); 728c55abf61SChaoyong He return -EINVAL; 729c55abf61SChaoyong He } 730c55abf61SChaoyong He 731c55abf61SChaoyong He hw->vxlan_usecnt[idx]--; 732c55abf61SChaoyong He 733c55abf61SChaoyong He if (hw->vxlan_usecnt[idx] == 0) { 734c55abf61SChaoyong He ret = nfp_net_set_vxlan_port(hw, idx, 0); 735c55abf61SChaoyong He if (ret != 0) { 736c55abf61SChaoyong He PMD_DRV_LOG(ERR, "Failed set vxlan port"); 737c55abf61SChaoyong He return -EINVAL; 738c55abf61SChaoyong He } 739c55abf61SChaoyong He } 740c55abf61SChaoyong He 741c55abf61SChaoyong He return 0; 742c55abf61SChaoyong He } 743c55abf61SChaoyong He 744646ea79cSHeinrich Kuhn /* Initialise and register driver with DPDK Application */ 7458d961320SJin Liu static const struct eth_dev_ops nfp_net_eth_dev_ops = { 746646ea79cSHeinrich Kuhn .dev_configure = nfp_net_configure, 747646ea79cSHeinrich Kuhn .dev_start = nfp_net_start, 748646ea79cSHeinrich Kuhn .dev_stop = nfp_net_stop, 749646ea79cSHeinrich Kuhn .dev_set_link_up = nfp_net_set_link_up, 750646ea79cSHeinrich Kuhn .dev_set_link_down = nfp_net_set_link_down, 751646ea79cSHeinrich Kuhn .dev_close = nfp_net_close, 752646ea79cSHeinrich Kuhn .promiscuous_enable = nfp_net_promisc_enable, 753646ea79cSHeinrich Kuhn .promiscuous_disable = nfp_net_promisc_disable, 7544a86c36bSQin Ke .allmulticast_enable = nfp_net_allmulticast_enable, 7554a86c36bSQin Ke .allmulticast_disable = nfp_net_allmulticast_disable, 756646ea79cSHeinrich Kuhn .link_update = nfp_net_link_update, 757646ea79cSHeinrich Kuhn .stats_get = nfp_net_stats_get, 758646ea79cSHeinrich Kuhn .stats_reset = nfp_net_stats_reset, 759f26e8239SJames Hershaw .xstats_get = nfp_net_xstats_get, 760f26e8239SJames Hershaw .xstats_reset = nfp_net_xstats_reset, 761f26e8239SJames Hershaw .xstats_get_names = nfp_net_xstats_get_names, 762f26e8239SJames Hershaw .xstats_get_by_id = nfp_net_xstats_get_by_id, 763f26e8239SJames Hershaw .xstats_get_names_by_id = nfp_net_xstats_get_names_by_id, 764646ea79cSHeinrich Kuhn .dev_infos_get = nfp_net_infos_get, 765646ea79cSHeinrich Kuhn .dev_supported_ptypes_get = nfp_net_supported_ptypes_get, 766646ea79cSHeinrich Kuhn .mtu_set = nfp_net_dev_mtu_set, 7670a94d6bcSJin Liu .mac_addr_set = nfp_net_set_mac_addr, 768646ea79cSHeinrich Kuhn .vlan_offload_set = nfp_net_vlan_offload_set, 769646ea79cSHeinrich Kuhn .reta_update = nfp_net_reta_update, 770646ea79cSHeinrich Kuhn .reta_query = nfp_net_reta_query, 771646ea79cSHeinrich Kuhn .rss_hash_update = nfp_net_rss_hash_update, 772646ea79cSHeinrich Kuhn .rss_hash_conf_get = nfp_net_rss_hash_conf_get, 773646ea79cSHeinrich Kuhn .rx_queue_setup = nfp_net_rx_queue_setup, 774646ea79cSHeinrich Kuhn .rx_queue_release = nfp_net_rx_queue_release, 7758d961320SJin Liu .tx_queue_setup = nfp_net_tx_queue_setup, 77652ddc4c2SJin Liu .tx_queue_release = nfp_net_tx_queue_release, 77752ddc4c2SJin Liu .rx_queue_intr_enable = nfp_rx_queue_intr_enable, 77852ddc4c2SJin Liu .rx_queue_intr_disable = nfp_rx_queue_intr_disable, 779c55abf61SChaoyong He .udp_tunnel_port_add = nfp_udp_tunnel_port_add, 780c55abf61SChaoyong He .udp_tunnel_port_del = nfp_udp_tunnel_port_del, 781128c8ad9SChaoyong He .fw_version_get = nfp_net_firmware_version_get, 78251d15e82SZerun Fu .flow_ctrl_get = nfp_net_flow_ctrl_get, 78368aa3537SZerun Fu .flow_ctrl_set = nfp_net_flow_ctrl_set, 7840b9079d2SChaoyong He .flow_ops_get = nfp_net_flow_ops_get, 7850786add9SZerun Fu .fec_get_capability = nfp_net_fec_get_capability, 786c6835a32SZerun Fu .fec_get = nfp_net_fec_get, 78737bd1b84SZerun Fu .fec_set = nfp_net_fec_set, 78852ddc4c2SJin Liu }; 78952ddc4c2SJin Liu 790ee8ca64eSChaoyong He static inline void 791ee8ca64eSChaoyong He nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw, 792ee8ca64eSChaoyong He struct rte_eth_dev *eth_dev) 793266470b2SJin Liu { 794ee8ca64eSChaoyong He if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 795ee8ca64eSChaoyong He eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts; 796ee8ca64eSChaoyong He else 797ee8ca64eSChaoyong He eth_dev->tx_pkt_burst = nfp_net_nfdk_xmit_pkts; 798266470b2SJin Liu 7998d961320SJin Liu eth_dev->dev_ops = &nfp_net_eth_dev_ops; 800266470b2SJin Liu eth_dev->rx_queue_count = nfp_net_rx_queue_count; 801266470b2SJin Liu eth_dev->rx_pkt_burst = &nfp_net_recv_pkts; 802266470b2SJin Liu } 803266470b2SJin Liu 804646ea79cSHeinrich Kuhn static int 805646ea79cSHeinrich Kuhn nfp_net_init(struct rte_eth_dev *eth_dev) 806646ea79cSHeinrich Kuhn { 80749952141SChaoyong He int err; 80849952141SChaoyong He uint16_t port; 8090314a8ffSChaoyong He uint64_t rx_base; 8100314a8ffSChaoyong He uint64_t tx_base; 8114a9bb682SChaoyong He struct nfp_hw *hw; 8124a9bb682SChaoyong He struct nfp_net_hw *net_hw; 81349952141SChaoyong He struct nfp_pf_dev *pf_dev; 81449952141SChaoyong He struct rte_pci_device *pci_dev; 81549952141SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 816646ea79cSHeinrich Kuhn 817646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 81865f6915dSChaoyong He net_hw = eth_dev->data->dev_private; 819646ea79cSHeinrich Kuhn 820646ea79cSHeinrich Kuhn /* Use backpointer here to the PF of this eth_dev */ 82165f6915dSChaoyong He pf_dev = net_hw->pf_dev; 822646ea79cSHeinrich Kuhn 823968ec1c3SChaoyong He /* Use backpointer to the CoreNIC app struct */ 824968ec1c3SChaoyong He app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv); 825968ec1c3SChaoyong He 826646ea79cSHeinrich Kuhn port = ((struct nfp_net_hw *)eth_dev->data->dev_private)->idx; 8278ceb85c3SChaoyong He if (port > 7) { 828646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "Port value is wrong"); 829646ea79cSHeinrich Kuhn return -ENODEV; 830646ea79cSHeinrich Kuhn } 831646ea79cSHeinrich Kuhn 8324a9bb682SChaoyong He hw = &net_hw->super; 833646ea79cSHeinrich Kuhn 834030b2b19SChaoyong He PMD_INIT_LOG(DEBUG, "Working with physical port number: %hu, " 8354a9bb682SChaoyong He "NFP internal port number: %d", port, net_hw->nfp_idx); 836646ea79cSHeinrich Kuhn 837646ea79cSHeinrich Kuhn rte_eth_copy_pci_info(eth_dev, pci_dev); 838646ea79cSHeinrich Kuhn 8398ad2cc8fSPeng Zhang if (port == 0 || pf_dev->multi_pf.enabled) { 840f26e8239SJames Hershaw uint32_t min_size; 841f26e8239SJames Hershaw 8424a9bb682SChaoyong He hw->ctrl_bar = pf_dev->ctrl_bar; 8434a9bb682SChaoyong He min_size = NFP_MAC_STATS_SIZE * net_hw->pf_dev->nfp_eth_table->max_index; 8444a9bb682SChaoyong He net_hw->mac_stats_bar = nfp_rtsym_map(net_hw->pf_dev->sym_tbl, "_mac_stats", 8454a9bb682SChaoyong He min_size, &net_hw->mac_stats_area); 8464a9bb682SChaoyong He if (net_hw->mac_stats_bar == NULL) { 847f26e8239SJames Hershaw PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for _mac_stats_bar"); 848f26e8239SJames Hershaw return -EIO; 849f26e8239SJames Hershaw } 850b0c496abSChaoyong He 8514a9bb682SChaoyong He net_hw->mac_stats = net_hw->mac_stats_bar; 852646ea79cSHeinrich Kuhn } else { 853a6189a67SJin Liu /* Use port offset in pf ctrl_bar for this ports control bar */ 8544a9bb682SChaoyong He hw->ctrl_bar = pf_dev->ctrl_bar + (port * NFP_NET_CFG_BAR_SZ); 8554a9bb682SChaoyong He net_hw->mac_stats = app_fw_nic->ports[0]->mac_stats_bar + 8564a9bb682SChaoyong He (net_hw->nfp_idx * NFP_MAC_STATS_SIZE); 857646ea79cSHeinrich Kuhn } 858646ea79cSHeinrich Kuhn 8594a9bb682SChaoyong He PMD_INIT_LOG(DEBUG, "ctrl bar: %p", hw->ctrl_bar); 8604a9bb682SChaoyong He PMD_INIT_LOG(DEBUG, "MAC stats: %p", net_hw->mac_stats); 861646ea79cSHeinrich Kuhn 8624a9bb682SChaoyong He err = nfp_net_common_init(pci_dev, net_hw); 863cd4397ebSPeng Zhang if (err != 0) 86436994566SChaoyong He goto free_area; 865fd392f84SPeng Zhang 866eecdfcc1SShihong Wang err = nfp_net_tlv_caps_parse(eth_dev); 867eecdfcc1SShihong Wang if (err != 0) { 868eecdfcc1SShihong Wang PMD_INIT_LOG(ERR, "Failed to parser TLV caps"); 869eecdfcc1SShihong Wang return err; 87036994566SChaoyong He goto free_area; 871eecdfcc1SShihong Wang } 872eecdfcc1SShihong Wang 87354713740SChang Miao err = nfp_ipsec_init(eth_dev); 87454713740SChang Miao if (err != 0) { 87554713740SChang Miao PMD_INIT_LOG(ERR, "Failed to init IPsec module"); 87636994566SChaoyong He goto free_area; 87754713740SChang Miao } 87854713740SChang Miao 8794a9bb682SChaoyong He nfp_net_ethdev_ops_mount(net_hw, eth_dev); 880266470b2SJin Liu 8814a9bb682SChaoyong He net_hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) * 882f26e8239SJames Hershaw nfp_net_xstats_size(eth_dev), 0); 8834a9bb682SChaoyong He if (net_hw->eth_xstats_base == NULL) { 884f26e8239SJames Hershaw PMD_INIT_LOG(ERR, "no memory for xstats base values on device %s!", 885f26e8239SJames Hershaw pci_dev->device.name); 88636994566SChaoyong He err = -ENOMEM; 88736994566SChaoyong He goto ipsec_exit; 888f26e8239SJames Hershaw } 889f26e8239SJames Hershaw 890646ea79cSHeinrich Kuhn /* Work out where in the BAR the queues start. */ 8914a9bb682SChaoyong He tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 8924a9bb682SChaoyong He rx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ); 893646ea79cSHeinrich Kuhn 8944a9bb682SChaoyong He net_hw->tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ; 8954a9bb682SChaoyong He net_hw->rx_bar = pf_dev->qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ; 8964a9bb682SChaoyong He eth_dev->data->dev_private = net_hw; 897646ea79cSHeinrich Kuhn 898646ea79cSHeinrich Kuhn PMD_INIT_LOG(DEBUG, "ctrl_bar: %p, tx_bar: %p, rx_bar: %p", 8994a9bb682SChaoyong He hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar); 900646ea79cSHeinrich Kuhn 9014a9bb682SChaoyong He nfp_net_cfg_queue_setup(net_hw); 9024a9bb682SChaoyong He net_hw->mtu = RTE_ETHER_MTU; 903646ea79cSHeinrich Kuhn 904646ea79cSHeinrich Kuhn /* VLAN insertion is incompatible with LSOv2 */ 9054a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0) 9064a9bb682SChaoyong He hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN; 907646ea79cSHeinrich Kuhn 9084a9bb682SChaoyong He nfp_net_log_device_information(net_hw); 909646ea79cSHeinrich Kuhn 910646ea79cSHeinrich Kuhn /* Initializing spinlock for reconfigs */ 9114a9bb682SChaoyong He rte_spinlock_init(&hw->reconfig_lock); 912646ea79cSHeinrich Kuhn 913646ea79cSHeinrich Kuhn /* Allocating memory for mac addr */ 914f4d24fe9SChaoyong He eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0); 915646ea79cSHeinrich Kuhn if (eth_dev->data->mac_addrs == NULL) { 916646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Failed to space for MAC address"); 91736994566SChaoyong He err = -ENOMEM; 91836994566SChaoyong He goto xstats_free; 919646ea79cSHeinrich Kuhn } 920646ea79cSHeinrich Kuhn 921968ec1c3SChaoyong He nfp_net_pf_read_mac(app_fw_nic, port); 922503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 923646ea79cSHeinrich Kuhn 9244a9bb682SChaoyong He if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) { 925a6189a67SJin Liu PMD_INIT_LOG(INFO, "Using random mac address for port %d", port); 926646ea79cSHeinrich Kuhn /* Using random mac addresses for VFs */ 9274a9bb682SChaoyong He rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]); 928503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 929646ea79cSHeinrich Kuhn } 930646ea79cSHeinrich Kuhn 931646ea79cSHeinrich Kuhn /* Copying mac address to DPDK eth_dev struct */ 9324a9bb682SChaoyong He rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs); 933646ea79cSHeinrich Kuhn 9344a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) 935646ea79cSHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR; 936646ea79cSHeinrich Kuhn 937646ea79cSHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 938646ea79cSHeinrich Kuhn 939030b2b19SChaoyong He PMD_INIT_LOG(INFO, "port %d VendorID=%#x DeviceID=%#x " 940c2c4f87bSAman Deep Singh "mac=" RTE_ETHER_ADDR_PRT_FMT, 941646ea79cSHeinrich Kuhn eth_dev->data->port_id, pci_dev->id.vendor_id, 942646ea79cSHeinrich Kuhn pci_dev->id.device_id, 9434a9bb682SChaoyong He RTE_ETHER_ADDR_BYTES(&hw->mac_addr)); 944646ea79cSHeinrich Kuhn 945646ea79cSHeinrich Kuhn /* Registering LSC interrupt handler */ 946d61138d4SHarman Kalra rte_intr_callback_register(pci_dev->intr_handle, 947a6189a67SJin Liu nfp_net_dev_interrupt_handler, (void *)eth_dev); 948646ea79cSHeinrich Kuhn /* Telling the firmware about the LSC interrupt entry */ 9494a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); 95094d0631aSPeng Zhang /* Unmask the LSC interrupt */ 95194d0631aSPeng Zhang nfp_net_irq_unmask(eth_dev); 952646ea79cSHeinrich Kuhn /* Recording current stats counters values */ 953646ea79cSHeinrich Kuhn nfp_net_stats_reset(eth_dev); 954646ea79cSHeinrich Kuhn 9558153bc6fSChaoyong He if ((hw->cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) { 9568153bc6fSChaoyong He err = nfp_net_flow_priv_init(pf_dev, port); 9578153bc6fSChaoyong He if (err != 0) { 9588153bc6fSChaoyong He PMD_INIT_LOG(ERR, "Init net flow priv failed"); 9598153bc6fSChaoyong He goto xstats_free; 9608153bc6fSChaoyong He } 9618153bc6fSChaoyong He } 9628153bc6fSChaoyong He 963646ea79cSHeinrich Kuhn return 0; 96436994566SChaoyong He 96536994566SChaoyong He xstats_free: 96636994566SChaoyong He rte_free(net_hw->eth_xstats_base); 96736994566SChaoyong He ipsec_exit: 96836994566SChaoyong He nfp_ipsec_uninit(eth_dev); 96936994566SChaoyong He free_area: 97036994566SChaoyong He if (net_hw->mac_stats_area != NULL) 97136994566SChaoyong He nfp_cpp_area_release_free(net_hw->mac_stats_area); 97236994566SChaoyong He 97336994566SChaoyong He return err; 974646ea79cSHeinrich Kuhn } 975646ea79cSHeinrich Kuhn 976646ea79cSHeinrich Kuhn #define DEFAULT_FW_PATH "/lib/firmware/netronome" 977646ea79cSHeinrich Kuhn 978646ea79cSHeinrich Kuhn static int 979ebfb540eSPeng Zhang nfp_fw_get_name(struct rte_pci_device *dev, 980f4d24fe9SChaoyong He struct nfp_nsp *nsp, 981ebfb540eSPeng Zhang char *card, 982ebfb540eSPeng Zhang char *fw_name, 983ebfb540eSPeng Zhang size_t fw_size) 984646ea79cSHeinrich Kuhn { 98549952141SChaoyong He char serial[40]; 986ff627b74SChaoyong He uint16_t interface; 987ff627b74SChaoyong He uint32_t cpp_serial_len; 988ff627b74SChaoyong He const uint8_t *cpp_serial; 98949952141SChaoyong He struct nfp_cpp *cpp = nfp_nsp_cpp(nsp); 990ff627b74SChaoyong He 991ff627b74SChaoyong He cpp_serial_len = nfp_cpp_serial(cpp, &cpp_serial); 992ff627b74SChaoyong He if (cpp_serial_len != NFP_SERIAL_LEN) 993ff627b74SChaoyong He return -ERANGE; 994ff627b74SChaoyong He 995ff627b74SChaoyong He interface = nfp_cpp_interface(cpp); 996646ea79cSHeinrich Kuhn 997646ea79cSHeinrich Kuhn /* Looking for firmware file in order of priority */ 998646ea79cSHeinrich Kuhn 999646ea79cSHeinrich Kuhn /* First try to find a firmware image specific for this device */ 1000646ea79cSHeinrich Kuhn snprintf(serial, sizeof(serial), 1001646ea79cSHeinrich Kuhn "serial-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 1002ff627b74SChaoyong He cpp_serial[0], cpp_serial[1], cpp_serial[2], cpp_serial[3], 1003ff627b74SChaoyong He cpp_serial[4], cpp_serial[5], interface >> 8, interface & 0xff); 1004ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/%s.nffw", DEFAULT_FW_PATH, serial); 1005646ea79cSHeinrich Kuhn 1006646ea79cSHeinrich Kuhn PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); 1007ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1008ebfb540eSPeng Zhang return 0; 1009b0c496abSChaoyong He 1010646ea79cSHeinrich Kuhn /* Then try the PCI name */ 1011ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/pci-%s.nffw", DEFAULT_FW_PATH, 10123ddb4cc0SPeng Zhang dev->name); 1013646ea79cSHeinrich Kuhn 1014646ea79cSHeinrich Kuhn PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); 1015ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1016ebfb540eSPeng Zhang return 0; 1017646ea79cSHeinrich Kuhn 1018646ea79cSHeinrich Kuhn /* Finally try the card type and media */ 1019ebfb540eSPeng Zhang snprintf(fw_name, fw_size, "%s/%s", DEFAULT_FW_PATH, card); 1020646ea79cSHeinrich Kuhn PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); 1021ebfb540eSPeng Zhang if (access(fw_name, F_OK) == 0) 1022ebfb540eSPeng Zhang return 0; 1023c01e5c0cSChaoyong He 1024646ea79cSHeinrich Kuhn return -ENOENT; 1025ebfb540eSPeng Zhang } 1026646ea79cSHeinrich Kuhn 1027ebfb540eSPeng Zhang static int 1028ebfb540eSPeng Zhang nfp_fw_upload(struct nfp_nsp *nsp, 1029ebfb540eSPeng Zhang char *fw_name) 1030ebfb540eSPeng Zhang { 1031ebfb540eSPeng Zhang int err; 1032ebfb540eSPeng Zhang void *fw_buf; 1033ebfb540eSPeng Zhang size_t fsize; 1034ebfb540eSPeng Zhang 1035ebfb540eSPeng Zhang err = rte_firmware_read(fw_name, &fw_buf, &fsize); 1036ebfb540eSPeng Zhang if (err != 0) { 1037ebfb540eSPeng Zhang PMD_DRV_LOG(ERR, "firmware %s not found!", fw_name); 1038ebfb540eSPeng Zhang return -ENOENT; 1039ebfb540eSPeng Zhang } 1040ebfb540eSPeng Zhang 1041646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu", 1042646ea79cSHeinrich Kuhn fw_name, fsize); 1043646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Uploading the firmware ..."); 10442e634b03SPeng Zhang if (nfp_nsp_load_fw(nsp, fw_buf, fsize) < 0) { 10452e634b03SPeng Zhang free(fw_buf); 10462e634b03SPeng Zhang PMD_DRV_LOG(ERR, "Firmware load failed."); 10472e634b03SPeng Zhang return -EIO; 10482e634b03SPeng Zhang } 10492e634b03SPeng Zhang 1050646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Done"); 1051646ea79cSHeinrich Kuhn 1052646ea79cSHeinrich Kuhn free(fw_buf); 1053646ea79cSHeinrich Kuhn 1054646ea79cSHeinrich Kuhn return 0; 1055646ea79cSHeinrich Kuhn } 1056646ea79cSHeinrich Kuhn 10573b00109dSPeng Zhang static void 10583b00109dSPeng Zhang nfp_fw_unload(struct nfp_cpp *cpp) 10593b00109dSPeng Zhang { 10603b00109dSPeng Zhang struct nfp_nsp *nsp; 10613b00109dSPeng Zhang 10623b00109dSPeng Zhang nsp = nfp_nsp_open(cpp); 10633b00109dSPeng Zhang if (nsp == NULL) 10643b00109dSPeng Zhang return; 10653b00109dSPeng Zhang 10663b00109dSPeng Zhang nfp_nsp_device_soft_reset(nsp); 10673b00109dSPeng Zhang nfp_nsp_close(nsp); 10683b00109dSPeng Zhang } 10693b00109dSPeng Zhang 1070646ea79cSHeinrich Kuhn static int 1071ebfb540eSPeng Zhang nfp_fw_reload(struct nfp_nsp *nsp, 1072ebfb540eSPeng Zhang char *fw_name) 10738ba461d1SPeng Zhang { 10748ba461d1SPeng Zhang int err; 10758ba461d1SPeng Zhang 10768ba461d1SPeng Zhang nfp_nsp_device_soft_reset(nsp); 1077ebfb540eSPeng Zhang err = nfp_fw_upload(nsp, fw_name); 10788ba461d1SPeng Zhang if (err != 0) 10798ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "NFP firmware load failed"); 10808ba461d1SPeng Zhang 10818ba461d1SPeng Zhang return err; 10828ba461d1SPeng Zhang } 10838ba461d1SPeng Zhang 1084a99ca614SPeng Zhang static bool 1085a99ca614SPeng Zhang nfp_fw_skip_load(const struct nfp_dev_info *dev_info, 10868ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 10878ba461d1SPeng Zhang { 108874397a7aSPeng Zhang uint8_t i; 108974397a7aSPeng Zhang uint64_t tmp_beat; 10908ba461d1SPeng Zhang uint32_t port_num; 10918b9a83eaSPeng Zhang uint8_t in_use = 0; 109274397a7aSPeng Zhang uint64_t beat[dev_info->pf_num_per_unit]; 109374397a7aSPeng Zhang uint32_t offset[dev_info->pf_num_per_unit]; 10948b9a83eaSPeng Zhang uint8_t abnormal = dev_info->pf_num_per_unit; 109574397a7aSPeng Zhang 109674397a7aSPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 109774397a7aSPeng Zhang offset[port_num] = NFP_BEAT_OFFSET(port_num); 109874397a7aSPeng Zhang beat[port_num] = nn_readq(multi_pf->beat_addr + offset[port_num]); 10998b9a83eaSPeng Zhang if (beat[port_num] == 0) 11008b9a83eaSPeng Zhang abnormal--; 110174397a7aSPeng Zhang } 11028ba461d1SPeng Zhang 11038b9a83eaSPeng Zhang if (abnormal == 0) 11048b9a83eaSPeng Zhang return true; 11058b9a83eaSPeng Zhang 110674397a7aSPeng Zhang for (i = 0; i < 3; i++) { 110774397a7aSPeng Zhang sleep(1); 11088ba461d1SPeng Zhang for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) { 11098ba461d1SPeng Zhang if (port_num == multi_pf->function_id) 11108ba461d1SPeng Zhang continue; 11118ba461d1SPeng Zhang 11128b9a83eaSPeng Zhang if (beat[port_num] == 0) 11138b9a83eaSPeng Zhang continue; 11148b9a83eaSPeng Zhang 111574397a7aSPeng Zhang tmp_beat = nn_readq(multi_pf->beat_addr + offset[port_num]); 11168b9a83eaSPeng Zhang if (tmp_beat != beat[port_num]) { 11178b9a83eaSPeng Zhang in_use++; 11188b9a83eaSPeng Zhang abnormal--; 11198b9a83eaSPeng Zhang beat[port_num] = 0; 11208b9a83eaSPeng Zhang } 11218b9a83eaSPeng Zhang } 11228b9a83eaSPeng Zhang 11238b9a83eaSPeng Zhang if (abnormal == 0) 1124a99ca614SPeng Zhang return true; 11258ba461d1SPeng Zhang } 11268b9a83eaSPeng Zhang 11278b9a83eaSPeng Zhang if (in_use != 0) { 11288b9a83eaSPeng Zhang PMD_DRV_LOG(WARNING, "Abnormal %u != 0, the nic has port which is exit abnormally.", 11298b9a83eaSPeng Zhang abnormal); 11308b9a83eaSPeng Zhang return true; 11318ba461d1SPeng Zhang } 11328ba461d1SPeng Zhang 1133a99ca614SPeng Zhang return false; 11348ba461d1SPeng Zhang } 11358ba461d1SPeng Zhang 11368ba461d1SPeng Zhang static int 1137ebfb540eSPeng Zhang nfp_fw_reload_for_multipf(struct nfp_nsp *nsp, 1138ebfb540eSPeng Zhang char *fw_name, 11398ba461d1SPeng Zhang struct nfp_cpp *cpp, 11408ba461d1SPeng Zhang const struct nfp_dev_info *dev_info, 11418ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 11428ba461d1SPeng Zhang { 11438ba461d1SPeng Zhang int err; 1144a99ca614SPeng Zhang bool skip_load_fw = false; 11458ba461d1SPeng Zhang 11468ba461d1SPeng Zhang err = nfp_net_keepalive_init(cpp, multi_pf); 11478ba461d1SPeng Zhang if (err != 0) { 1148a99ca614SPeng Zhang PMD_DRV_LOG(ERR, "NFP init beat failed"); 11498ba461d1SPeng Zhang return err; 11508ba461d1SPeng Zhang } 11518ba461d1SPeng Zhang 11528ba461d1SPeng Zhang err = nfp_net_keepalive_start(multi_pf); 11538ba461d1SPeng Zhang if (err != 0) { 11548ba461d1SPeng Zhang nfp_net_keepalive_uninit(multi_pf); 11558ba461d1SPeng Zhang PMD_DRV_LOG(ERR, "NFP write beat failed"); 1156a99ca614SPeng Zhang return err; 11578ba461d1SPeng Zhang } 11588ba461d1SPeng Zhang 1159a99ca614SPeng Zhang if (nfp_nsp_fw_loaded(nsp)) 1160a99ca614SPeng Zhang skip_load_fw = nfp_fw_skip_load(dev_info, multi_pf); 1161a99ca614SPeng Zhang 1162a99ca614SPeng Zhang if (skip_load_fw) 1163a99ca614SPeng Zhang return 0; 1164a99ca614SPeng Zhang 1165a99ca614SPeng Zhang err = nfp_fw_reload(nsp, fw_name); 1166a99ca614SPeng Zhang if (err != 0) { 1167a99ca614SPeng Zhang nfp_net_keepalive_stop(multi_pf); 1168a99ca614SPeng Zhang nfp_net_keepalive_uninit(multi_pf); 11698ba461d1SPeng Zhang return err; 11708ba461d1SPeng Zhang } 11718ba461d1SPeng Zhang 1172*b67a7b40SPeng Zhang nfp_net_keepalive_clear_others(dev_info, multi_pf); 1173*b67a7b40SPeng Zhang 1174a99ca614SPeng Zhang return 0; 1175a99ca614SPeng Zhang } 1176a99ca614SPeng Zhang 11778ba461d1SPeng Zhang static int 1178a6189a67SJin Liu nfp_fw_setup(struct rte_pci_device *dev, 1179a6189a67SJin Liu struct nfp_cpp *cpp, 1180a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table, 11818ba461d1SPeng Zhang struct nfp_hwinfo *hwinfo, 11828ba461d1SPeng Zhang const struct nfp_dev_info *dev_info, 11838ba461d1SPeng Zhang struct nfp_multi_pf *multi_pf) 1184646ea79cSHeinrich Kuhn { 118549952141SChaoyong He int err; 1186ebfb540eSPeng Zhang char fw_name[125]; 118749952141SChaoyong He char card_desc[100]; 1188646ea79cSHeinrich Kuhn struct nfp_nsp *nsp; 1189646ea79cSHeinrich Kuhn const char *nfp_fw_model; 1190646ea79cSHeinrich Kuhn 119106be30d4SPeng Zhang nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "nffw.partno"); 119206be30d4SPeng Zhang if (nfp_fw_model == NULL) 1193646ea79cSHeinrich Kuhn nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "assembly.partno"); 1194646ea79cSHeinrich Kuhn 1195c01e5c0cSChaoyong He if (nfp_fw_model != NULL) { 1196646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "firmware model found: %s", nfp_fw_model); 1197646ea79cSHeinrich Kuhn } else { 1198646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "firmware model NOT found"); 1199646ea79cSHeinrich Kuhn return -EIO; 1200646ea79cSHeinrich Kuhn } 1201646ea79cSHeinrich Kuhn 1202646ea79cSHeinrich Kuhn if (nfp_eth_table->count == 0 || nfp_eth_table->count > 8) { 1203646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "NFP ethernet table reports wrong ports: %u", 1204646ea79cSHeinrich Kuhn nfp_eth_table->count); 1205646ea79cSHeinrich Kuhn return -EIO; 1206646ea79cSHeinrich Kuhn } 1207646ea79cSHeinrich Kuhn 1208646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "NFP ethernet port table reports %u ports", 1209646ea79cSHeinrich Kuhn nfp_eth_table->count); 1210646ea79cSHeinrich Kuhn 1211646ea79cSHeinrich Kuhn PMD_DRV_LOG(INFO, "Port speed: %u", nfp_eth_table->ports[0].speed); 1212646ea79cSHeinrich Kuhn 1213646ea79cSHeinrich Kuhn snprintf(card_desc, sizeof(card_desc), "nic_%s_%dx%d.nffw", 1214646ea79cSHeinrich Kuhn nfp_fw_model, nfp_eth_table->count, 1215646ea79cSHeinrich Kuhn nfp_eth_table->ports[0].speed / 1000); 1216646ea79cSHeinrich Kuhn 1217646ea79cSHeinrich Kuhn nsp = nfp_nsp_open(cpp); 1218a6189a67SJin Liu if (nsp == NULL) { 1219646ea79cSHeinrich Kuhn PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle"); 1220646ea79cSHeinrich Kuhn return -EIO; 1221646ea79cSHeinrich Kuhn } 1222646ea79cSHeinrich Kuhn 1223ebfb540eSPeng Zhang err = nfp_fw_get_name(dev, nsp, card_desc, fw_name, sizeof(fw_name)); 1224ebfb540eSPeng Zhang if (err != 0) { 1225ebfb540eSPeng Zhang PMD_DRV_LOG(ERR, "Can't find suitable firmware."); 1226ebfb540eSPeng Zhang nfp_nsp_close(nsp); 1227ebfb540eSPeng Zhang return err; 1228ebfb540eSPeng Zhang } 1229ebfb540eSPeng Zhang 12308ba461d1SPeng Zhang if (multi_pf->enabled) 1231ebfb540eSPeng Zhang err = nfp_fw_reload_for_multipf(nsp, fw_name, cpp, dev_info, multi_pf); 12328ba461d1SPeng Zhang else 1233ebfb540eSPeng Zhang err = nfp_fw_reload(nsp, fw_name); 1234646ea79cSHeinrich Kuhn 1235646ea79cSHeinrich Kuhn nfp_nsp_close(nsp); 1236646ea79cSHeinrich Kuhn return err; 1237646ea79cSHeinrich Kuhn } 1238646ea79cSHeinrich Kuhn 12398ad2cc8fSPeng Zhang static inline bool 1240a508fa23SPeng Zhang nfp_check_multi_pf_from_fw(uint32_t total_vnics) 1241a508fa23SPeng Zhang { 1242a508fa23SPeng Zhang if (total_vnics == 1) 1243a508fa23SPeng Zhang return true; 1244a508fa23SPeng Zhang 1245a508fa23SPeng Zhang return false; 1246a508fa23SPeng Zhang } 1247a508fa23SPeng Zhang 1248a508fa23SPeng Zhang static inline bool 12498ad2cc8fSPeng Zhang nfp_check_multi_pf_from_nsp(struct rte_pci_device *pci_dev, 12508ad2cc8fSPeng Zhang struct nfp_cpp *cpp) 12518ad2cc8fSPeng Zhang { 12528ad2cc8fSPeng Zhang bool flag; 12538ad2cc8fSPeng Zhang struct nfp_nsp *nsp; 12548ad2cc8fSPeng Zhang 12558ad2cc8fSPeng Zhang nsp = nfp_nsp_open(cpp); 12568ad2cc8fSPeng Zhang if (nsp == NULL) { 12578ad2cc8fSPeng Zhang PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle"); 12588ad2cc8fSPeng Zhang return false; 12598ad2cc8fSPeng Zhang } 12608ad2cc8fSPeng Zhang 12618ad2cc8fSPeng Zhang flag = (nfp_nsp_get_abi_ver_major(nsp) > 0) && 12628ad2cc8fSPeng Zhang (pci_dev->id.device_id == PCI_DEVICE_ID_NFP3800_PF_NIC); 12638ad2cc8fSPeng Zhang 12648ad2cc8fSPeng Zhang nfp_nsp_close(nsp); 12658ad2cc8fSPeng Zhang return flag; 12668ad2cc8fSPeng Zhang } 12678ad2cc8fSPeng Zhang 1268a6189a67SJin Liu static int 126995f978efSPeng Zhang nfp_enable_multi_pf(struct nfp_pf_dev *pf_dev) 127095f978efSPeng Zhang { 127195f978efSPeng Zhang int err = 0; 127295f978efSPeng Zhang uint64_t tx_base; 127395f978efSPeng Zhang uint8_t *ctrl_bar; 127495f978efSPeng Zhang struct nfp_hw *hw; 127595f978efSPeng Zhang uint32_t cap_extend; 127695f978efSPeng Zhang struct nfp_net_hw net_hw; 127795f978efSPeng Zhang struct nfp_cpp_area *area; 127895f978efSPeng Zhang char name[RTE_ETH_NAME_MAX_LEN]; 127995f978efSPeng Zhang 128095f978efSPeng Zhang memset(&net_hw, 0, sizeof(struct nfp_net_hw)); 128195f978efSPeng Zhang 128295f978efSPeng Zhang /* Map the symbol table */ 128395f978efSPeng Zhang snprintf(name, sizeof(name), "_pf%u_net_bar0", 128495f978efSPeng Zhang pf_dev->multi_pf.function_id); 128595f978efSPeng Zhang ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, name, NFP_NET_CFG_BAR_SZ, 128695f978efSPeng Zhang &area); 128795f978efSPeng Zhang if (ctrl_bar == NULL) { 128895f978efSPeng Zhang PMD_INIT_LOG(ERR, "Failed to find data vNIC memory symbol"); 128995f978efSPeng Zhang return -ENODEV; 129095f978efSPeng Zhang } 129195f978efSPeng Zhang 129295f978efSPeng Zhang hw = &net_hw.super; 129395f978efSPeng Zhang hw->ctrl_bar = ctrl_bar; 129495f978efSPeng Zhang 129595f978efSPeng Zhang cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1); 129695f978efSPeng Zhang if ((cap_extend & NFP_NET_CFG_CTRL_MULTI_PF) == 0) { 129795f978efSPeng Zhang PMD_INIT_LOG(ERR, "Loaded firmware doesn't support multiple PF"); 129895f978efSPeng Zhang err = -EINVAL; 129995f978efSPeng Zhang goto end; 130095f978efSPeng Zhang } 130195f978efSPeng Zhang 130295f978efSPeng Zhang tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 130395f978efSPeng Zhang net_hw.tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ; 130495f978efSPeng Zhang nfp_net_cfg_queue_setup(&net_hw); 130595f978efSPeng Zhang rte_spinlock_init(&hw->reconfig_lock); 130695f978efSPeng Zhang nfp_ext_reconfig(&net_hw.super, NFP_NET_CFG_CTRL_MULTI_PF, NFP_NET_CFG_UPDATE_GEN); 130795f978efSPeng Zhang end: 130895f978efSPeng Zhang nfp_cpp_area_release_free(area); 130995f978efSPeng Zhang return err; 131095f978efSPeng Zhang } 131195f978efSPeng Zhang 131295f978efSPeng Zhang static int 13130314a8ffSChaoyong He nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev, 13140314a8ffSChaoyong He const struct nfp_dev_info *dev_info) 1315646ea79cSHeinrich Kuhn { 13168ceb85c3SChaoyong He uint8_t i; 13173b00109dSPeng Zhang uint8_t id; 1318e7978635SChaoyong He int ret = 0; 13198ceb85c3SChaoyong He uint32_t total_vnics; 1320646ea79cSHeinrich Kuhn struct nfp_net_hw *hw; 1321968ec1c3SChaoyong He unsigned int numa_node; 1322646ea79cSHeinrich Kuhn struct rte_eth_dev *eth_dev; 1323968ec1c3SChaoyong He struct nfp_app_fw_nic *app_fw_nic; 1324a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table; 13253b00109dSPeng Zhang char bar_name[RTE_ETH_NAME_MAX_LEN]; 1326646ea79cSHeinrich Kuhn char port_name[RTE_ETH_NAME_MAX_LEN]; 13273b00109dSPeng Zhang char vnic_name[RTE_ETH_NAME_MAX_LEN]; 1328646ea79cSHeinrich Kuhn 1329968ec1c3SChaoyong He nfp_eth_table = pf_dev->nfp_eth_table; 1330968ec1c3SChaoyong He PMD_INIT_LOG(INFO, "Total physical ports: %d", nfp_eth_table->count); 13313b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, 0); 1332968ec1c3SChaoyong He 1333968ec1c3SChaoyong He /* Allocate memory for the CoreNIC app */ 1334968ec1c3SChaoyong He app_fw_nic = rte_zmalloc("nfp_app_fw_nic", sizeof(*app_fw_nic), 0); 1335968ec1c3SChaoyong He if (app_fw_nic == NULL) 1336968ec1c3SChaoyong He return -ENOMEM; 1337968ec1c3SChaoyong He 1338968ec1c3SChaoyong He /* Point the app_fw_priv pointer in the PF to the coreNIC app */ 1339968ec1c3SChaoyong He pf_dev->app_fw_priv = app_fw_nic; 1340968ec1c3SChaoyong He 1341968ec1c3SChaoyong He /* Read the number of vNIC's created for the PF */ 13423b00109dSPeng Zhang snprintf(vnic_name, sizeof(vnic_name), "nfd_cfg_pf%u_num_ports", id); 13433b00109dSPeng Zhang total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, vnic_name, &ret); 1344e7978635SChaoyong He if (ret != 0 || total_vnics == 0 || total_vnics > 8) { 13453b00109dSPeng Zhang PMD_INIT_LOG(ERR, "%s symbol with wrong value", vnic_name); 1346968ec1c3SChaoyong He ret = -ENODEV; 1347968ec1c3SChaoyong He goto app_cleanup; 1348968ec1c3SChaoyong He } 1349968ec1c3SChaoyong He 1350a508fa23SPeng Zhang if (pf_dev->multi_pf.enabled) { 1351a508fa23SPeng Zhang if (!nfp_check_multi_pf_from_fw(total_vnics)) { 1352a508fa23SPeng Zhang PMD_INIT_LOG(ERR, "NSP report multipf, but FW report not multipf"); 1353a508fa23SPeng Zhang ret = -ENODEV; 1354a508fa23SPeng Zhang goto app_cleanup; 1355a508fa23SPeng Zhang } 1356a508fa23SPeng Zhang } else { 1357968ec1c3SChaoyong He /* 1358968ec1c3SChaoyong He * For coreNIC the number of vNICs exposed should be the same as the 135940688372SChaoyong He * number of physical ports. 1360968ec1c3SChaoyong He */ 13618ceb85c3SChaoyong He if (total_vnics != nfp_eth_table->count) { 1362968ec1c3SChaoyong He PMD_INIT_LOG(ERR, "Total physical ports do not match number of vNICs"); 1363968ec1c3SChaoyong He ret = -ENODEV; 1364968ec1c3SChaoyong He goto app_cleanup; 1365968ec1c3SChaoyong He } 1366a508fa23SPeng Zhang } 1367968ec1c3SChaoyong He 1368968ec1c3SChaoyong He /* Populate coreNIC app properties */ 1369968ec1c3SChaoyong He app_fw_nic->total_phyports = total_vnics; 1370968ec1c3SChaoyong He app_fw_nic->pf_dev = pf_dev; 1371968ec1c3SChaoyong He if (total_vnics > 1) 1372968ec1c3SChaoyong He app_fw_nic->multiport = true; 1373968ec1c3SChaoyong He 1374968ec1c3SChaoyong He /* Map the symbol table */ 13753b00109dSPeng Zhang snprintf(bar_name, sizeof(bar_name), "_pf%u_net_bar0", id); 13763b00109dSPeng Zhang pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, bar_name, 1377d5e9fc86SChaoyong He app_fw_nic->total_phyports * NFP_NET_CFG_BAR_SZ, 1378d5e9fc86SChaoyong He &pf_dev->ctrl_area); 1379968ec1c3SChaoyong He if (pf_dev->ctrl_bar == NULL) { 13803b00109dSPeng Zhang PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for %s", bar_name); 1381968ec1c3SChaoyong He ret = -EIO; 1382968ec1c3SChaoyong He goto app_cleanup; 1383968ec1c3SChaoyong He } 1384968ec1c3SChaoyong He 1385968ec1c3SChaoyong He PMD_INIT_LOG(DEBUG, "ctrl bar: %p", pf_dev->ctrl_bar); 1386968ec1c3SChaoyong He 1387968ec1c3SChaoyong He /* Loop through all physical ports on PF */ 1388968ec1c3SChaoyong He numa_node = rte_socket_id(); 1389968ec1c3SChaoyong He for (i = 0; i < app_fw_nic->total_phyports; i++) { 13903b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 13913b00109dSPeng Zhang snprintf(port_name, sizeof(port_name), "%s_port%u", 13923b00109dSPeng Zhang pf_dev->pci_dev->device.name, id); 1393646ea79cSHeinrich Kuhn 1394646ea79cSHeinrich Kuhn /* Allocate a eth_dev for this phyport */ 1395646ea79cSHeinrich Kuhn eth_dev = rte_eth_dev_allocate(port_name); 1396a6189a67SJin Liu if (eth_dev == NULL) { 1397646ea79cSHeinrich Kuhn ret = -ENODEV; 1398646ea79cSHeinrich Kuhn goto port_cleanup; 1399646ea79cSHeinrich Kuhn } 1400646ea79cSHeinrich Kuhn 1401646ea79cSHeinrich Kuhn /* Allocate memory for this phyport */ 1402f4d24fe9SChaoyong He eth_dev->data->dev_private = rte_zmalloc_socket(port_name, 1403f4d24fe9SChaoyong He sizeof(struct nfp_net_hw), 1404646ea79cSHeinrich Kuhn RTE_CACHE_LINE_SIZE, numa_node); 1405a6189a67SJin Liu if (eth_dev->data->dev_private == NULL) { 1406646ea79cSHeinrich Kuhn ret = -ENOMEM; 1407646ea79cSHeinrich Kuhn rte_eth_dev_release_port(eth_dev); 1408646ea79cSHeinrich Kuhn goto port_cleanup; 1409646ea79cSHeinrich Kuhn } 1410646ea79cSHeinrich Kuhn 14119d723baaSChaoyong He hw = eth_dev->data->dev_private; 1412646ea79cSHeinrich Kuhn 1413646ea79cSHeinrich Kuhn /* Add this device to the PF's array of physical ports */ 14143b00109dSPeng Zhang app_fw_nic->ports[id] = hw; 1415646ea79cSHeinrich Kuhn 14160314a8ffSChaoyong He hw->dev_info = dev_info; 1417646ea79cSHeinrich Kuhn hw->pf_dev = pf_dev; 1418646ea79cSHeinrich Kuhn hw->cpp = pf_dev->cpp; 1419646ea79cSHeinrich Kuhn hw->eth_dev = eth_dev; 14203b00109dSPeng Zhang hw->idx = id; 14213b00109dSPeng Zhang hw->nfp_idx = nfp_eth_table->ports[id].index; 1422646ea79cSHeinrich Kuhn 1423646ea79cSHeinrich Kuhn eth_dev->device = &pf_dev->pci_dev->device; 1424646ea79cSHeinrich Kuhn 142540688372SChaoyong He /* 142640688372SChaoyong He * Ctrl/tx/rx BAR mappings and remaining init happens in 142740688372SChaoyong He * @nfp_net_init() 1428646ea79cSHeinrich Kuhn */ 1429646ea79cSHeinrich Kuhn ret = nfp_net_init(eth_dev); 1430c01e5c0cSChaoyong He if (ret != 0) { 1431646ea79cSHeinrich Kuhn ret = -ENODEV; 1432646ea79cSHeinrich Kuhn goto port_cleanup; 1433646ea79cSHeinrich Kuhn } 1434646ea79cSHeinrich Kuhn 1435646ea79cSHeinrich Kuhn rte_eth_dev_probing_finish(eth_dev); 1436646ea79cSHeinrich Kuhn 1437646ea79cSHeinrich Kuhn } /* End loop, all ports on this PF */ 1438968ec1c3SChaoyong He 1439968ec1c3SChaoyong He return 0; 1440646ea79cSHeinrich Kuhn 1441646ea79cSHeinrich Kuhn port_cleanup: 1442968ec1c3SChaoyong He for (i = 0; i < app_fw_nic->total_phyports; i++) { 14433b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 14448153bc6fSChaoyong He hw = app_fw_nic->ports[id]; 14453b00109dSPeng Zhang 14468153bc6fSChaoyong He if (hw != NULL && hw->eth_dev != NULL) { 14478153bc6fSChaoyong He nfp_net_uninit(hw->eth_dev); 14488153bc6fSChaoyong He rte_eth_dev_release_port(hw->eth_dev); 1449646ea79cSHeinrich Kuhn } 1450646ea79cSHeinrich Kuhn } 14518b8f116bSChaoyong He nfp_cpp_area_release_free(pf_dev->ctrl_area); 1452968ec1c3SChaoyong He app_cleanup: 1453968ec1c3SChaoyong He rte_free(app_fw_nic); 1454a6189a67SJin Liu 1455646ea79cSHeinrich Kuhn return ret; 1456646ea79cSHeinrich Kuhn } 1457646ea79cSHeinrich Kuhn 1458a6189a67SJin Liu static int 1459c7a6970fSZerun Fu nfp_net_hwinfo_set(uint8_t function_id, 1460c7a6970fSZerun Fu struct nfp_rtsym_table *sym_tbl, 1461c7a6970fSZerun Fu struct nfp_cpp *cpp) 1462c7a6970fSZerun Fu { 1463c7a6970fSZerun Fu int ret = 0; 1464c7a6970fSZerun Fu uint64_t app_cap; 1465c7a6970fSZerun Fu uint8_t sp_indiff; 1466c7a6970fSZerun Fu struct nfp_nsp *nsp; 1467c7a6970fSZerun Fu char hw_info[RTE_ETH_NAME_MAX_LEN]; 1468c7a6970fSZerun Fu char app_cap_name[RTE_ETH_NAME_MAX_LEN]; 1469c7a6970fSZerun Fu 1470c7a6970fSZerun Fu /* Read the app capabilities of the firmware loaded */ 1471c7a6970fSZerun Fu snprintf(app_cap_name, sizeof(app_cap_name), "_pf%u_net_app_cap", function_id); 1472c7a6970fSZerun Fu app_cap = nfp_rtsym_read_le(sym_tbl, app_cap_name, &ret); 1473c7a6970fSZerun Fu if (ret != 0) { 1474c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Couldn't read app_fw_cap from firmware."); 1475c7a6970fSZerun Fu return ret; 1476c7a6970fSZerun Fu } 1477c7a6970fSZerun Fu 1478c7a6970fSZerun Fu /* Calculate the value of sp_indiff and write to hw_info */ 1479c7a6970fSZerun Fu sp_indiff = app_cap & NFP_NET_APP_CAP_SP_INDIFF; 1480c7a6970fSZerun Fu snprintf(hw_info, sizeof(hw_info), "sp_indiff=%u", sp_indiff); 1481c7a6970fSZerun Fu 1482c7a6970fSZerun Fu nsp = nfp_nsp_open(cpp); 1483c7a6970fSZerun Fu if (nsp == NULL) { 1484c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Couldn't get NSP."); 1485c7a6970fSZerun Fu return -EIO; 1486c7a6970fSZerun Fu } 1487c7a6970fSZerun Fu 1488c7a6970fSZerun Fu ret = nfp_nsp_hwinfo_set(nsp, hw_info, sizeof(hw_info)); 1489c7a6970fSZerun Fu nfp_nsp_close(nsp); 1490c7a6970fSZerun Fu if (ret != 0) { 1491c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Failed to set parameter to hwinfo."); 1492c7a6970fSZerun Fu return ret; 1493c7a6970fSZerun Fu } 1494c7a6970fSZerun Fu 1495c7a6970fSZerun Fu return 0; 1496c7a6970fSZerun Fu } 1497c7a6970fSZerun Fu 14983110ab73SZerun Fu const uint32_t nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = { 14993110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10M] = RTE_ETH_LINK_SPEED_10M, 15003110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10M_HD] = RTE_ETH_LINK_SPEED_10M_HD, 15013110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_100M] = RTE_ETH_LINK_SPEED_100M, 15023110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_100M_HD] = RTE_ETH_LINK_SPEED_100M_HD, 15033110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_1G] = RTE_ETH_LINK_SPEED_1G, 15043110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_2P5G] = RTE_ETH_LINK_SPEED_2_5G, 15053110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_5G] = RTE_ETH_LINK_SPEED_5G, 15063110ab73SZerun Fu [NFP_MEDIA_W0_RJ45_10G] = RTE_ETH_LINK_SPEED_10G, 15073110ab73SZerun Fu [NFP_MEDIA_1000BASE_CX] = RTE_ETH_LINK_SPEED_1G, 15083110ab73SZerun Fu [NFP_MEDIA_1000BASE_KX] = RTE_ETH_LINK_SPEED_1G, 15093110ab73SZerun Fu [NFP_MEDIA_10GBASE_KX4] = RTE_ETH_LINK_SPEED_10G, 15103110ab73SZerun Fu [NFP_MEDIA_10GBASE_KR] = RTE_ETH_LINK_SPEED_10G, 15113110ab73SZerun Fu [NFP_MEDIA_10GBASE_CX4] = RTE_ETH_LINK_SPEED_10G, 15123110ab73SZerun Fu [NFP_MEDIA_10GBASE_CR] = RTE_ETH_LINK_SPEED_10G, 15133110ab73SZerun Fu [NFP_MEDIA_10GBASE_SR] = RTE_ETH_LINK_SPEED_10G, 15143110ab73SZerun Fu [NFP_MEDIA_10GBASE_ER] = RTE_ETH_LINK_SPEED_10G, 15153110ab73SZerun Fu [NFP_MEDIA_25GBASE_KR] = RTE_ETH_LINK_SPEED_25G, 15163110ab73SZerun Fu [NFP_MEDIA_25GBASE_KR_S] = RTE_ETH_LINK_SPEED_25G, 15173110ab73SZerun Fu [NFP_MEDIA_25GBASE_CR] = RTE_ETH_LINK_SPEED_25G, 15183110ab73SZerun Fu [NFP_MEDIA_25GBASE_CR_S] = RTE_ETH_LINK_SPEED_25G, 15193110ab73SZerun Fu [NFP_MEDIA_25GBASE_SR] = RTE_ETH_LINK_SPEED_25G, 15203110ab73SZerun Fu [NFP_MEDIA_40GBASE_CR4] = RTE_ETH_LINK_SPEED_40G, 15213110ab73SZerun Fu [NFP_MEDIA_40GBASE_KR4] = RTE_ETH_LINK_SPEED_40G, 15223110ab73SZerun Fu [NFP_MEDIA_40GBASE_SR4] = RTE_ETH_LINK_SPEED_40G, 15233110ab73SZerun Fu [NFP_MEDIA_40GBASE_LR4] = RTE_ETH_LINK_SPEED_40G, 15243110ab73SZerun Fu [NFP_MEDIA_50GBASE_KR] = RTE_ETH_LINK_SPEED_50G, 15253110ab73SZerun Fu [NFP_MEDIA_50GBASE_SR] = RTE_ETH_LINK_SPEED_50G, 15263110ab73SZerun Fu [NFP_MEDIA_50GBASE_CR] = RTE_ETH_LINK_SPEED_50G, 15273110ab73SZerun Fu [NFP_MEDIA_50GBASE_LR] = RTE_ETH_LINK_SPEED_50G, 15283110ab73SZerun Fu [NFP_MEDIA_50GBASE_ER] = RTE_ETH_LINK_SPEED_50G, 15293110ab73SZerun Fu [NFP_MEDIA_50GBASE_FR] = RTE_ETH_LINK_SPEED_50G, 15303110ab73SZerun Fu [NFP_MEDIA_100GBASE_KR4] = RTE_ETH_LINK_SPEED_100G, 15313110ab73SZerun Fu [NFP_MEDIA_100GBASE_SR4] = RTE_ETH_LINK_SPEED_100G, 15323110ab73SZerun Fu [NFP_MEDIA_100GBASE_CR4] = RTE_ETH_LINK_SPEED_100G, 15333110ab73SZerun Fu [NFP_MEDIA_100GBASE_KP4] = RTE_ETH_LINK_SPEED_100G, 15343110ab73SZerun Fu [NFP_MEDIA_100GBASE_CR10] = RTE_ETH_LINK_SPEED_100G, 15353110ab73SZerun Fu [NFP_MEDIA_10GBASE_LR] = RTE_ETH_LINK_SPEED_10G, 15363110ab73SZerun Fu [NFP_MEDIA_25GBASE_LR] = RTE_ETH_LINK_SPEED_25G, 15373110ab73SZerun Fu [NFP_MEDIA_25GBASE_ER] = RTE_ETH_LINK_SPEED_25G 15383110ab73SZerun Fu }; 15393110ab73SZerun Fu 15403110ab73SZerun Fu static int 15413110ab73SZerun Fu nfp_net_speed_capa_get_real(struct nfp_eth_media_buf *media_buf, 15423110ab73SZerun Fu struct nfp_pf_dev *pf_dev) 15433110ab73SZerun Fu { 15443110ab73SZerun Fu uint32_t i; 15453110ab73SZerun Fu uint32_t j; 15463110ab73SZerun Fu uint32_t offset; 15473110ab73SZerun Fu uint32_t speed_capa = 0; 15483110ab73SZerun Fu uint64_t supported_modes; 15493110ab73SZerun Fu 15503110ab73SZerun Fu for (i = 0; i < RTE_DIM(media_buf->supported_modes); i++) { 15513110ab73SZerun Fu supported_modes = media_buf->supported_modes[i]; 15523110ab73SZerun Fu offset = i * UINT64_BIT; 15533110ab73SZerun Fu for (j = 0; j < UINT64_BIT; j++) { 15543110ab73SZerun Fu if (supported_modes == 0) 15553110ab73SZerun Fu break; 15563110ab73SZerun Fu 15573110ab73SZerun Fu if ((supported_modes & 1) != 0) { 15583110ab73SZerun Fu if ((j + offset) >= NFP_MEDIA_LINK_MODES_NUMBER) { 15593110ab73SZerun Fu PMD_DRV_LOG(ERR, "Invalid offset of media table."); 15603110ab73SZerun Fu return -EINVAL; 15613110ab73SZerun Fu } 15623110ab73SZerun Fu 15633110ab73SZerun Fu speed_capa |= nfp_eth_media_table[j + offset]; 15643110ab73SZerun Fu } 15653110ab73SZerun Fu 15663110ab73SZerun Fu supported_modes = supported_modes >> 1; 15673110ab73SZerun Fu } 15683110ab73SZerun Fu } 15693110ab73SZerun Fu 15703110ab73SZerun Fu pf_dev->speed_capa = speed_capa; 15713110ab73SZerun Fu 15723110ab73SZerun Fu return pf_dev->speed_capa == 0 ? -EINVAL : 0; 15733110ab73SZerun Fu } 15743110ab73SZerun Fu 15753110ab73SZerun Fu static int 15763110ab73SZerun Fu nfp_net_speed_capa_get(struct nfp_pf_dev *pf_dev, 15773110ab73SZerun Fu uint32_t port_id) 15783110ab73SZerun Fu { 15793110ab73SZerun Fu int ret; 15803110ab73SZerun Fu struct nfp_nsp *nsp; 15813110ab73SZerun Fu struct nfp_eth_media_buf media_buf; 15823110ab73SZerun Fu 15833110ab73SZerun Fu media_buf.eth_index = pf_dev->nfp_eth_table->ports[port_id].eth_index; 15843110ab73SZerun Fu pf_dev->speed_capa = 0; 15853110ab73SZerun Fu 15863110ab73SZerun Fu nsp = nfp_nsp_open(pf_dev->cpp); 15873110ab73SZerun Fu if (nsp == NULL) { 15883110ab73SZerun Fu PMD_DRV_LOG(ERR, "Couldn't get NSP."); 15893110ab73SZerun Fu return -EIO; 15903110ab73SZerun Fu } 15913110ab73SZerun Fu 15923110ab73SZerun Fu ret = nfp_nsp_read_media(nsp, &media_buf, sizeof(media_buf)); 15933110ab73SZerun Fu nfp_nsp_close(nsp); 15943110ab73SZerun Fu if (ret != 0) { 15953110ab73SZerun Fu PMD_DRV_LOG(ERR, "Failed to read media."); 15963110ab73SZerun Fu return ret; 15973110ab73SZerun Fu } 15983110ab73SZerun Fu 15993110ab73SZerun Fu ret = nfp_net_speed_capa_get_real(&media_buf, pf_dev); 16003110ab73SZerun Fu if (ret < 0) { 16013110ab73SZerun Fu PMD_DRV_LOG(ERR, "Speed capability is invalid."); 16023110ab73SZerun Fu return ret; 16033110ab73SZerun Fu } 16043110ab73SZerun Fu 16053110ab73SZerun Fu return 0; 16063110ab73SZerun Fu } 16073110ab73SZerun Fu 1608c7a6970fSZerun Fu static int 1609a6189a67SJin Liu nfp_pf_init(struct rte_pci_device *pci_dev) 1610646ea79cSHeinrich Kuhn { 16119e442599SShihong Wang uint32_t i; 16123b00109dSPeng Zhang uint32_t id; 1613e7978635SChaoyong He int ret = 0; 16145c464d6aSJin Liu uint64_t addr; 16153b00109dSPeng Zhang uint32_t index; 1616925c27ecSChaoyong He uint32_t cpp_id; 16173b00109dSPeng Zhang uint8_t function_id; 1618a6189a67SJin Liu struct nfp_cpp *cpp; 1619a6189a67SJin Liu struct nfp_pf_dev *pf_dev; 1620a6189a67SJin Liu struct nfp_hwinfo *hwinfo; 162149952141SChaoyong He enum nfp_app_fw_id app_fw_id; 1622a6189a67SJin Liu char name[RTE_ETH_NAME_MAX_LEN]; 1623a6189a67SJin Liu struct nfp_rtsym_table *sym_tbl; 16243b00109dSPeng Zhang char app_name[RTE_ETH_NAME_MAX_LEN]; 1625a6189a67SJin Liu struct nfp_eth_table *nfp_eth_table; 16260314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 1627646ea79cSHeinrich Kuhn 1628a6189a67SJin Liu if (pci_dev == NULL) 1629a6189a67SJin Liu return -ENODEV; 1630646ea79cSHeinrich Kuhn 163184aaba5aSChaoyong He if (pci_dev->mem_resource[0].addr == NULL) { 163284aaba5aSChaoyong He PMD_INIT_LOG(ERR, "The address of BAR0 is NULL."); 163384aaba5aSChaoyong He return -ENODEV; 163484aaba5aSChaoyong He } 163584aaba5aSChaoyong He 16360314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 16370314a8ffSChaoyong He if (dev_info == NULL) { 16380314a8ffSChaoyong He PMD_INIT_LOG(ERR, "Not supported device ID"); 16390314a8ffSChaoyong He return -ENODEV; 16400314a8ffSChaoyong He } 16410314a8ffSChaoyong He 16428ad2cc8fSPeng Zhang /* Allocate memory for the PF "device" */ 16433b00109dSPeng Zhang function_id = (pci_dev->addr.function) & 0x07; 16443b00109dSPeng Zhang snprintf(name, sizeof(name), "nfp_pf%u", function_id); 16458ad2cc8fSPeng Zhang pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); 16468ad2cc8fSPeng Zhang if (pf_dev == NULL) { 16478ad2cc8fSPeng Zhang PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device"); 16488ad2cc8fSPeng Zhang return -ENOMEM; 16498ad2cc8fSPeng Zhang } 16508ad2cc8fSPeng Zhang 1651646ea79cSHeinrich Kuhn /* 1652646ea79cSHeinrich Kuhn * When device bound to UIO, the device could be used, by mistake, 1653646ea79cSHeinrich Kuhn * by two DPDK apps, and the UIO driver does not avoid it. This 1654646ea79cSHeinrich Kuhn * could lead to a serious problem when configuring the NFP CPP 1655646ea79cSHeinrich Kuhn * interface. Here we avoid this telling to the CPP init code to 1656646ea79cSHeinrich Kuhn * use a lock file if UIO is being used. 1657646ea79cSHeinrich Kuhn */ 1658646ea79cSHeinrich Kuhn if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) 16591fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false); 1660646ea79cSHeinrich Kuhn else 16611fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true); 1662646ea79cSHeinrich Kuhn 1663a6189a67SJin Liu if (cpp == NULL) { 1664646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "A CPP handle can not be obtained"); 16658ad2cc8fSPeng Zhang ret = -EIO; 16668ad2cc8fSPeng Zhang goto pf_cleanup; 1667646ea79cSHeinrich Kuhn } 1668646ea79cSHeinrich Kuhn 1669646ea79cSHeinrich Kuhn hwinfo = nfp_hwinfo_read(cpp); 1670a6189a67SJin Liu if (hwinfo == NULL) { 1671646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Error reading hwinfo table"); 1672646ea79cSHeinrich Kuhn ret = -EIO; 1673968ec1c3SChaoyong He goto cpp_cleanup; 1674646ea79cSHeinrich Kuhn } 1675646ea79cSHeinrich Kuhn 1676968ec1c3SChaoyong He /* Read the number of physical ports from hardware */ 1677646ea79cSHeinrich Kuhn nfp_eth_table = nfp_eth_read_ports(cpp); 1678a6189a67SJin Liu if (nfp_eth_table == NULL) { 1679646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Error reading NFP ethernet table"); 1680646ea79cSHeinrich Kuhn ret = -EIO; 1681646ea79cSHeinrich Kuhn goto hwinfo_cleanup; 1682646ea79cSHeinrich Kuhn } 1683646ea79cSHeinrich Kuhn 16848ad2cc8fSPeng Zhang pf_dev->multi_pf.enabled = nfp_check_multi_pf_from_nsp(pci_dev, cpp); 16853b00109dSPeng Zhang pf_dev->multi_pf.function_id = function_id; 16868ad2cc8fSPeng Zhang 16879e442599SShihong Wang /* Force the physical port down to clear the possible DMA error */ 16883b00109dSPeng Zhang for (i = 0; i < nfp_eth_table->count; i++) { 16893b00109dSPeng Zhang id = nfp_function_id_get(pf_dev, i); 16903b00109dSPeng Zhang index = nfp_eth_table->ports[id].index; 16913b00109dSPeng Zhang nfp_eth_set_configured(cpp, index, 0); 16923b00109dSPeng Zhang } 16939e442599SShihong Wang 16948ba461d1SPeng Zhang if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo, 16958ba461d1SPeng Zhang dev_info, &pf_dev->multi_pf) != 0) { 1696646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "Error when uploading firmware"); 1697646ea79cSHeinrich Kuhn ret = -EIO; 1698646ea79cSHeinrich Kuhn goto eth_table_cleanup; 1699646ea79cSHeinrich Kuhn } 1700646ea79cSHeinrich Kuhn 1701646ea79cSHeinrich Kuhn /* Now the symbol table should be there */ 1702646ea79cSHeinrich Kuhn sym_tbl = nfp_rtsym_table_read(cpp); 1703a6189a67SJin Liu if (sym_tbl == NULL) { 1704f4d24fe9SChaoyong He PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table"); 1705646ea79cSHeinrich Kuhn ret = -EIO; 17063b00109dSPeng Zhang goto fw_cleanup; 1707646ea79cSHeinrich Kuhn } 1708646ea79cSHeinrich Kuhn 1709968ec1c3SChaoyong He /* Read the app ID of the firmware loaded */ 17103b00109dSPeng Zhang snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id); 17113b00109dSPeng Zhang app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret); 1712e7978635SChaoyong He if (ret != 0) { 17133b00109dSPeng Zhang PMD_INIT_LOG(ERR, "Couldn't read %s from firmware", app_name); 1714646ea79cSHeinrich Kuhn ret = -EIO; 1715646ea79cSHeinrich Kuhn goto sym_tbl_cleanup; 1716646ea79cSHeinrich Kuhn } 1717646ea79cSHeinrich Kuhn 1718c7a6970fSZerun Fu /* Write sp_indiff to hw_info */ 1719c7a6970fSZerun Fu ret = nfp_net_hwinfo_set(function_id, sym_tbl, cpp); 1720c7a6970fSZerun Fu if (ret != 0) { 1721c7a6970fSZerun Fu PMD_INIT_LOG(ERR, "Failed to set hwinfo."); 1722c7a6970fSZerun Fu ret = -EIO; 1723c7a6970fSZerun Fu goto sym_tbl_cleanup; 1724c7a6970fSZerun Fu } 1725c7a6970fSZerun Fu 1726646ea79cSHeinrich Kuhn /* Populate the newly created PF device */ 1727968ec1c3SChaoyong He pf_dev->app_fw_id = app_fw_id; 1728646ea79cSHeinrich Kuhn pf_dev->cpp = cpp; 1729646ea79cSHeinrich Kuhn pf_dev->hwinfo = hwinfo; 1730646ea79cSHeinrich Kuhn pf_dev->sym_tbl = sym_tbl; 1731646ea79cSHeinrich Kuhn pf_dev->pci_dev = pci_dev; 1732968ec1c3SChaoyong He pf_dev->nfp_eth_table = nfp_eth_table; 1733646ea79cSHeinrich Kuhn 17343110ab73SZerun Fu /* Get the speed capability */ 17353110ab73SZerun Fu for (i = 0; i < nfp_eth_table->count; i++) { 17363110ab73SZerun Fu id = nfp_function_id_get(pf_dev, i); 17373110ab73SZerun Fu ret = nfp_net_speed_capa_get(pf_dev, id); 17383110ab73SZerun Fu if (ret != 0) { 17393110ab73SZerun Fu PMD_INIT_LOG(ERR, "Failed to get speed capability."); 17403110ab73SZerun Fu ret = -EIO; 17413110ab73SZerun Fu goto sym_tbl_cleanup; 17423110ab73SZerun Fu } 17433110ab73SZerun Fu } 17443110ab73SZerun Fu 174540688372SChaoyong He /* Configure access to tx/rx vNIC BARs */ 17460314a8ffSChaoyong He addr = nfp_qcp_queue_offset(dev_info, 0); 1747925c27ecSChaoyong He cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0); 17480314a8ffSChaoyong He 1749711e4559SChaoyong He pf_dev->qc_bar = nfp_cpp_map_area(pf_dev->cpp, cpp_id, 17500314a8ffSChaoyong He addr, dev_info->qc_area_sz, &pf_dev->qc_area); 1751711e4559SChaoyong He if (pf_dev->qc_bar == NULL) { 1752646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for net.qc"); 1753646ea79cSHeinrich Kuhn ret = -EIO; 17548ad2cc8fSPeng Zhang goto sym_tbl_cleanup; 1755646ea79cSHeinrich Kuhn } 1756646ea79cSHeinrich Kuhn 1757030b2b19SChaoyong He PMD_INIT_LOG(DEBUG, "qc_bar address: %p", pf_dev->qc_bar); 1758646ea79cSHeinrich Kuhn 1759a6189a67SJin Liu /* 1760968ec1c3SChaoyong He * PF initialization has been done at this point. Call app specific 176140688372SChaoyong He * init code now. 1762646ea79cSHeinrich Kuhn */ 1763968ec1c3SChaoyong He switch (pf_dev->app_fw_id) { 1764968ec1c3SChaoyong He case NFP_APP_FW_CORE_NIC: 176595f978efSPeng Zhang if (pf_dev->multi_pf.enabled) { 176695f978efSPeng Zhang ret = nfp_enable_multi_pf(pf_dev); 176795f978efSPeng Zhang if (ret != 0) 176895f978efSPeng Zhang goto hwqueues_cleanup; 176995f978efSPeng Zhang } 177095f978efSPeng Zhang 1771968ec1c3SChaoyong He PMD_INIT_LOG(INFO, "Initializing coreNIC"); 17720314a8ffSChaoyong He ret = nfp_init_app_fw_nic(pf_dev, dev_info); 1773968ec1c3SChaoyong He if (ret != 0) { 1774968ec1c3SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize coreNIC!"); 1775968ec1c3SChaoyong He goto hwqueues_cleanup; 1776968ec1c3SChaoyong He } 1777968ec1c3SChaoyong He break; 1778b1880421SChaoyong He case NFP_APP_FW_FLOWER_NIC: 1779b1880421SChaoyong He PMD_INIT_LOG(INFO, "Initializing Flower"); 17800314a8ffSChaoyong He ret = nfp_init_app_fw_flower(pf_dev, dev_info); 1781b1880421SChaoyong He if (ret != 0) { 1782b1880421SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize Flower!"); 1783b1880421SChaoyong He goto hwqueues_cleanup; 1784b1880421SChaoyong He } 1785b1880421SChaoyong He break; 1786968ec1c3SChaoyong He default: 1787968ec1c3SChaoyong He PMD_INIT_LOG(ERR, "Unsupported Firmware loaded"); 1788968ec1c3SChaoyong He ret = -EINVAL; 1789646ea79cSHeinrich Kuhn goto hwqueues_cleanup; 1790646ea79cSHeinrich Kuhn } 1791646ea79cSHeinrich Kuhn 179240688372SChaoyong He /* Register the CPP bridge service here for primary use */ 1793bab0e6f4SChaoyong He ret = nfp_enable_cpp_service(pf_dev); 1794dee23e6cSChaoyong He if (ret != 0) 1795dee23e6cSChaoyong He PMD_INIT_LOG(INFO, "Enable cpp service failed."); 1796646ea79cSHeinrich Kuhn 1797646ea79cSHeinrich Kuhn return 0; 1798646ea79cSHeinrich Kuhn 1799646ea79cSHeinrich Kuhn hwqueues_cleanup: 1800528812a6SChaoyong He nfp_cpp_area_release_free(pf_dev->qc_area); 1801646ea79cSHeinrich Kuhn sym_tbl_cleanup: 1802646ea79cSHeinrich Kuhn free(sym_tbl); 18033b00109dSPeng Zhang fw_cleanup: 18043b00109dSPeng Zhang nfp_fw_unload(cpp); 18058ba461d1SPeng Zhang nfp_net_keepalive_stop(&pf_dev->multi_pf); 1806*b67a7b40SPeng Zhang nfp_net_keepalive_clear(pf_dev->multi_pf.beat_addr, pf_dev->multi_pf.function_id); 1807528812a6SChaoyong He nfp_net_keepalive_uninit(&pf_dev->multi_pf); 1808646ea79cSHeinrich Kuhn eth_table_cleanup: 1809646ea79cSHeinrich Kuhn free(nfp_eth_table); 1810646ea79cSHeinrich Kuhn hwinfo_cleanup: 1811646ea79cSHeinrich Kuhn free(hwinfo); 1812968ec1c3SChaoyong He cpp_cleanup: 1813968ec1c3SChaoyong He nfp_cpp_free(cpp); 18148ad2cc8fSPeng Zhang pf_cleanup: 18158ad2cc8fSPeng Zhang rte_free(pf_dev); 18167feb8909SChaoyong He 1817646ea79cSHeinrich Kuhn return ret; 1818646ea79cSHeinrich Kuhn } 1819646ea79cSHeinrich Kuhn 1820d5f39e07SChaoyong He static int 1821016141b1SChaoyong He nfp_secondary_init_app_fw_nic(struct nfp_pf_dev *pf_dev) 1822d5f39e07SChaoyong He { 18238ceb85c3SChaoyong He uint32_t i; 1824d5f39e07SChaoyong He int err = 0; 1825d5f39e07SChaoyong He int ret = 0; 18263b00109dSPeng Zhang uint8_t function_id; 18278ceb85c3SChaoyong He uint32_t total_vnics; 1828d5f39e07SChaoyong He struct nfp_net_hw *hw; 18293b00109dSPeng Zhang char pf_name[RTE_ETH_NAME_MAX_LEN]; 1830d5f39e07SChaoyong He 1831d5f39e07SChaoyong He /* Read the number of vNIC's created for the PF */ 18323b00109dSPeng Zhang function_id = (pf_dev->pci_dev->addr.function) & 0x07; 18333b00109dSPeng Zhang snprintf(pf_name, sizeof(pf_name), "nfd_cfg_pf%u_num_ports", function_id); 18343b00109dSPeng Zhang total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, pf_name, &err); 18358ceb85c3SChaoyong He if (err != 0 || total_vnics == 0 || total_vnics > 8) { 18363b00109dSPeng Zhang PMD_INIT_LOG(ERR, "%s symbol with wrong value", pf_name); 1837d5f39e07SChaoyong He return -ENODEV; 1838d5f39e07SChaoyong He } 1839d5f39e07SChaoyong He 1840d5f39e07SChaoyong He for (i = 0; i < total_vnics; i++) { 18413b00109dSPeng Zhang uint32_t id = i; 1842d5f39e07SChaoyong He struct rte_eth_dev *eth_dev; 1843d5f39e07SChaoyong He char port_name[RTE_ETH_NAME_MAX_LEN]; 18443b00109dSPeng Zhang 18453b00109dSPeng Zhang if (nfp_check_multi_pf_from_fw(total_vnics)) 18463b00109dSPeng Zhang id = function_id; 18478ceb85c3SChaoyong He snprintf(port_name, sizeof(port_name), "%s_port%u", 18483b00109dSPeng Zhang pf_dev->pci_dev->device.name, id); 1849d5f39e07SChaoyong He 1850d5f39e07SChaoyong He PMD_INIT_LOG(DEBUG, "Secondary attaching to port %s", port_name); 1851d5f39e07SChaoyong He eth_dev = rte_eth_dev_attach_secondary(port_name); 1852d5f39e07SChaoyong He if (eth_dev == NULL) { 1853d5f39e07SChaoyong He PMD_INIT_LOG(ERR, "Secondary process attach to port %s failed", port_name); 1854d5f39e07SChaoyong He ret = -ENODEV; 1855d5f39e07SChaoyong He break; 1856d5f39e07SChaoyong He } 1857d5f39e07SChaoyong He 1858acb6bebfSChaoyong He eth_dev->process_private = pf_dev; 18599d723baaSChaoyong He hw = eth_dev->data->dev_private; 1860ee8ca64eSChaoyong He nfp_net_ethdev_ops_mount(hw, eth_dev); 1861d5f39e07SChaoyong He 1862d5f39e07SChaoyong He rte_eth_dev_probing_finish(eth_dev); 1863d5f39e07SChaoyong He } 1864d5f39e07SChaoyong He 1865d5f39e07SChaoyong He return ret; 1866d5f39e07SChaoyong He } 1867d5f39e07SChaoyong He 1868646ea79cSHeinrich Kuhn /* 1869646ea79cSHeinrich Kuhn * When attaching to the NFP4000/6000 PF on a secondary process there 1870646ea79cSHeinrich Kuhn * is no need to initialise the PF again. Only minimal work is required 187140688372SChaoyong He * here. 1872646ea79cSHeinrich Kuhn */ 1873a6189a67SJin Liu static int 1874a6189a67SJin Liu nfp_pf_secondary_init(struct rte_pci_device *pci_dev) 1875646ea79cSHeinrich Kuhn { 1876968ec1c3SChaoyong He int ret = 0; 1877a6189a67SJin Liu struct nfp_cpp *cpp; 18783b00109dSPeng Zhang uint8_t function_id; 1879016141b1SChaoyong He struct nfp_pf_dev *pf_dev; 1880d5f39e07SChaoyong He enum nfp_app_fw_id app_fw_id; 1881016141b1SChaoyong He char name[RTE_ETH_NAME_MAX_LEN]; 1882a6189a67SJin Liu struct nfp_rtsym_table *sym_tbl; 18830314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 18843b00109dSPeng Zhang char app_name[RTE_ETH_NAME_MAX_LEN]; 1885646ea79cSHeinrich Kuhn 1886a6189a67SJin Liu if (pci_dev == NULL) 1887646ea79cSHeinrich Kuhn return -ENODEV; 1888646ea79cSHeinrich Kuhn 188984aaba5aSChaoyong He if (pci_dev->mem_resource[0].addr == NULL) { 189084aaba5aSChaoyong He PMD_INIT_LOG(ERR, "The address of BAR0 is NULL."); 189184aaba5aSChaoyong He return -ENODEV; 189284aaba5aSChaoyong He } 189384aaba5aSChaoyong He 18940314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 18950314a8ffSChaoyong He if (dev_info == NULL) { 18960314a8ffSChaoyong He PMD_INIT_LOG(ERR, "Not supported device ID"); 18970314a8ffSChaoyong He return -ENODEV; 18980314a8ffSChaoyong He } 18990314a8ffSChaoyong He 1900016141b1SChaoyong He /* Allocate memory for the PF "device" */ 1901016141b1SChaoyong He snprintf(name, sizeof(name), "nfp_pf%d", 0); 1902016141b1SChaoyong He pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); 1903016141b1SChaoyong He if (pf_dev == NULL) { 1904016141b1SChaoyong He PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device"); 1905016141b1SChaoyong He return -ENOMEM; 1906016141b1SChaoyong He } 1907016141b1SChaoyong He 1908646ea79cSHeinrich Kuhn /* 1909646ea79cSHeinrich Kuhn * When device bound to UIO, the device could be used, by mistake, 1910646ea79cSHeinrich Kuhn * by two DPDK apps, and the UIO driver does not avoid it. This 1911646ea79cSHeinrich Kuhn * could lead to a serious problem when configuring the NFP CPP 1912646ea79cSHeinrich Kuhn * interface. Here we avoid this telling to the CPP init code to 1913646ea79cSHeinrich Kuhn * use a lock file if UIO is being used. 1914646ea79cSHeinrich Kuhn */ 1915646ea79cSHeinrich Kuhn if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) 19161fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false); 1917646ea79cSHeinrich Kuhn else 19181fbe51cdSChaoyong He cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true); 1919646ea79cSHeinrich Kuhn 1920a6189a67SJin Liu if (cpp == NULL) { 1921646ea79cSHeinrich Kuhn PMD_INIT_LOG(ERR, "A CPP handle can not be obtained"); 1922016141b1SChaoyong He ret = -EIO; 1923016141b1SChaoyong He goto pf_cleanup; 1924646ea79cSHeinrich Kuhn } 1925646ea79cSHeinrich Kuhn 1926646ea79cSHeinrich Kuhn /* 1927646ea79cSHeinrich Kuhn * We don't have access to the PF created in the primary process 192840688372SChaoyong He * here so we have to read the number of ports from firmware. 1929646ea79cSHeinrich Kuhn */ 1930646ea79cSHeinrich Kuhn sym_tbl = nfp_rtsym_table_read(cpp); 1931a6189a67SJin Liu if (sym_tbl == NULL) { 1932f4d24fe9SChaoyong He PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table"); 1933016141b1SChaoyong He ret = -EIO; 1934016141b1SChaoyong He goto pf_cleanup; 1935646ea79cSHeinrich Kuhn } 1936646ea79cSHeinrich Kuhn 1937d5f39e07SChaoyong He /* Read the app ID of the firmware loaded */ 19383b00109dSPeng Zhang function_id = pci_dev->addr.function & 0x7; 19393b00109dSPeng Zhang snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id); 19403b00109dSPeng Zhang app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret); 1941e7978635SChaoyong He if (ret != 0) { 19423b00109dSPeng Zhang PMD_INIT_LOG(ERR, "Couldn't read %s from fw", app_name); 1943016141b1SChaoyong He ret = -EIO; 1944968ec1c3SChaoyong He goto sym_tbl_cleanup; 1945968ec1c3SChaoyong He } 1946646ea79cSHeinrich Kuhn 1947016141b1SChaoyong He /* Populate the newly created PF device */ 1948016141b1SChaoyong He pf_dev->app_fw_id = app_fw_id; 1949016141b1SChaoyong He pf_dev->cpp = cpp; 1950016141b1SChaoyong He pf_dev->sym_tbl = sym_tbl; 1951016141b1SChaoyong He pf_dev->pci_dev = pci_dev; 1952016141b1SChaoyong He 1953016141b1SChaoyong He /* Call app specific init code now */ 1954d5f39e07SChaoyong He switch (app_fw_id) { 1955d5f39e07SChaoyong He case NFP_APP_FW_CORE_NIC: 1956d5f39e07SChaoyong He PMD_INIT_LOG(INFO, "Initializing coreNIC"); 1957016141b1SChaoyong He ret = nfp_secondary_init_app_fw_nic(pf_dev); 1958d5f39e07SChaoyong He if (ret != 0) { 1959d5f39e07SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize coreNIC!"); 1960d5f39e07SChaoyong He goto sym_tbl_cleanup; 1961646ea79cSHeinrich Kuhn } 1962d5f39e07SChaoyong He break; 1963b1880421SChaoyong He case NFP_APP_FW_FLOWER_NIC: 1964b1880421SChaoyong He PMD_INIT_LOG(INFO, "Initializing Flower"); 1965016141b1SChaoyong He ret = nfp_secondary_init_app_fw_flower(pf_dev); 1966b1880421SChaoyong He if (ret != 0) { 1967b1880421SChaoyong He PMD_INIT_LOG(ERR, "Could not initialize Flower!"); 1968b1880421SChaoyong He goto sym_tbl_cleanup; 1969b1880421SChaoyong He } 1970b1880421SChaoyong He break; 1971d5f39e07SChaoyong He default: 1972d5f39e07SChaoyong He PMD_INIT_LOG(ERR, "Unsupported Firmware loaded"); 1973d5f39e07SChaoyong He ret = -EINVAL; 1974d5f39e07SChaoyong He goto sym_tbl_cleanup; 1975646ea79cSHeinrich Kuhn } 1976646ea79cSHeinrich Kuhn 1977016141b1SChaoyong He return 0; 1978016141b1SChaoyong He 1979968ec1c3SChaoyong He sym_tbl_cleanup: 1980968ec1c3SChaoyong He free(sym_tbl); 1981016141b1SChaoyong He pf_cleanup: 1982016141b1SChaoyong He rte_free(pf_dev); 1983968ec1c3SChaoyong He 1984968ec1c3SChaoyong He return ret; 1985646ea79cSHeinrich Kuhn } 1986646ea79cSHeinrich Kuhn 1987a6189a67SJin Liu static int 1988a6189a67SJin Liu nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 1989646ea79cSHeinrich Kuhn struct rte_pci_device *dev) 1990646ea79cSHeinrich Kuhn { 1991646ea79cSHeinrich Kuhn if (rte_eal_process_type() == RTE_PROC_PRIMARY) 1992646ea79cSHeinrich Kuhn return nfp_pf_init(dev); 1993646ea79cSHeinrich Kuhn else 1994646ea79cSHeinrich Kuhn return nfp_pf_secondary_init(dev); 1995646ea79cSHeinrich Kuhn } 1996646ea79cSHeinrich Kuhn 1997646ea79cSHeinrich Kuhn static const struct rte_pci_id pci_id_nfp_pf_net_map[] = { 1998646ea79cSHeinrich Kuhn { 1999646ea79cSHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 20005c464d6aSJin Liu PCI_DEVICE_ID_NFP3800_PF_NIC) 20015c464d6aSJin Liu }, 20025c464d6aSJin Liu { 20035c464d6aSJin Liu RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 2004646ea79cSHeinrich Kuhn PCI_DEVICE_ID_NFP4000_PF_NIC) 2005646ea79cSHeinrich Kuhn }, 2006646ea79cSHeinrich Kuhn { 2007646ea79cSHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 2008646ea79cSHeinrich Kuhn PCI_DEVICE_ID_NFP6000_PF_NIC) 2009646ea79cSHeinrich Kuhn }, 2010646ea79cSHeinrich Kuhn { 20115aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 20125aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP3800_PF_NIC) 20135aedd4c3SJames Hershaw }, 20145aedd4c3SJames Hershaw { 20155aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 20165aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP4000_PF_NIC) 20175aedd4c3SJames Hershaw }, 20185aedd4c3SJames Hershaw { 20195aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 20205aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP6000_PF_NIC) 20215aedd4c3SJames Hershaw }, 20225aedd4c3SJames Hershaw { 2023646ea79cSHeinrich Kuhn .vendor_id = 0, 2024646ea79cSHeinrich Kuhn }, 2025646ea79cSHeinrich Kuhn }; 2026646ea79cSHeinrich Kuhn 2027a6189a67SJin Liu static int 2028a6189a67SJin Liu nfp_pci_uninit(struct rte_eth_dev *eth_dev) 2029646ea79cSHeinrich Kuhn { 2030646ea79cSHeinrich Kuhn uint16_t port_id; 203149952141SChaoyong He struct rte_pci_device *pci_dev; 2032646ea79cSHeinrich Kuhn 2033646ea79cSHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 2034646ea79cSHeinrich Kuhn 2035646ea79cSHeinrich Kuhn /* Free up all physical ports under PF */ 2036646ea79cSHeinrich Kuhn RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) 2037646ea79cSHeinrich Kuhn rte_eth_dev_close(port_id); 2038646ea79cSHeinrich Kuhn /* 2039646ea79cSHeinrich Kuhn * Ports can be closed and freed but hotplugging is not 204040688372SChaoyong He * currently supported. 2041646ea79cSHeinrich Kuhn */ 2042646ea79cSHeinrich Kuhn return -ENOTSUP; 2043646ea79cSHeinrich Kuhn } 2044646ea79cSHeinrich Kuhn 2045a6189a67SJin Liu static int 2046a6189a67SJin Liu eth_nfp_pci_remove(struct rte_pci_device *pci_dev) 2047646ea79cSHeinrich Kuhn { 2048646ea79cSHeinrich Kuhn return rte_eth_dev_pci_generic_remove(pci_dev, nfp_pci_uninit); 2049646ea79cSHeinrich Kuhn } 2050646ea79cSHeinrich Kuhn 2051646ea79cSHeinrich Kuhn static struct rte_pci_driver rte_nfp_net_pf_pmd = { 2052646ea79cSHeinrich Kuhn .id_table = pci_id_nfp_pf_net_map, 2053646ea79cSHeinrich Kuhn .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 2054646ea79cSHeinrich Kuhn .probe = nfp_pf_pci_probe, 2055646ea79cSHeinrich Kuhn .remove = eth_nfp_pci_remove, 2056646ea79cSHeinrich Kuhn }; 2057646ea79cSHeinrich Kuhn 2058d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI(NFP_PF_DRIVER_NAME, rte_nfp_net_pf_pmd); 2059d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI_TABLE(NFP_PF_DRIVER_NAME, pci_id_nfp_pf_net_map); 2060d505ee1dSChaoyong He RTE_PMD_REGISTER_KMOD_DEP(NFP_PF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio"); 2061