17f8e7320SHeinrich Kuhn /* SPDX-License-Identifier: BSD-3-Clause 27f8e7320SHeinrich Kuhn * Copyright (c) 2014-2021 Netronome Systems, Inc. 37f8e7320SHeinrich Kuhn * All rights reserved. 47f8e7320SHeinrich Kuhn * 57f8e7320SHeinrich Kuhn * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation. 67f8e7320SHeinrich Kuhn */ 77f8e7320SHeinrich Kuhn 8851f03e1SHeinrich Kuhn #include <rte_alarm.h> 9214fb306SChaoyong He #include <nfp_common_pci.h> 10851f03e1SHeinrich Kuhn 11ffe84fcbSChaoyong He #include "nfd3/nfp_nfd3.h" 12fc756151SChaoyong He #include "nfdk/nfp_nfdk.h" 135a95b024SChaoyong He #include "nfpcore/nfp_cpp.h" 145a95b024SChaoyong He 155a95b024SChaoyong He #include "nfp_logs.h" 1611e9eae4SChaoyong He #include "nfp_net_common.h" 17fb6befdfSLong Wu #include "nfp_rxtx_vec.h" 187f8e7320SHeinrich Kuhn 19d505ee1dSChaoyong He #define NFP_VF_DRIVER_NAME net_nfp_vf 20d505ee1dSChaoyong He 217f8e7320SHeinrich Kuhn static int 227f8e7320SHeinrich Kuhn nfp_netvf_start(struct rte_eth_dev *dev) 237f8e7320SHeinrich Kuhn { 2449952141SChaoyong He int ret; 2549952141SChaoyong He uint16_t i; 2672d1dea6SChaoyong He struct nfp_hw *hw; 2749952141SChaoyong He uint32_t new_ctrl; 2849952141SChaoyong He uint32_t update = 0; 2949952141SChaoyong He uint32_t intr_vector; 3072d1dea6SChaoyong He struct nfp_net_hw *net_hw; 317f8e7320SHeinrich Kuhn struct rte_eth_conf *dev_conf; 327f8e7320SHeinrich Kuhn struct rte_eth_rxmode *rxmode; 3349952141SChaoyong He struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 3449952141SChaoyong He struct rte_intr_handle *intr_handle = pci_dev->intr_handle; 357f8e7320SHeinrich Kuhn 367f8e7320SHeinrich Kuhn /* Disabling queues just in case... */ 377f8e7320SHeinrich Kuhn nfp_net_disable_queues(dev); 387f8e7320SHeinrich Kuhn 397f8e7320SHeinrich Kuhn /* Enabling the required queues in the device */ 407f8e7320SHeinrich Kuhn nfp_net_enable_queues(dev); 417f8e7320SHeinrich Kuhn 4240688372SChaoyong He /* Check and configure queue intr-vector mapping */ 437f8e7320SHeinrich Kuhn if (dev->data->dev_conf.intr_conf.rxq != 0) { 44f4d24fe9SChaoyong He if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) { 457f8e7320SHeinrich Kuhn /* 467f8e7320SHeinrich Kuhn * Better not to share LSC with RX interrupts. 4740688372SChaoyong He * Unregistering LSC interrupt handler. 487f8e7320SHeinrich Kuhn */ 49e7978635SChaoyong He rte_intr_callback_unregister(intr_handle, 507f8e7320SHeinrich Kuhn nfp_net_dev_interrupt_handler, (void *)dev); 517f8e7320SHeinrich Kuhn 527f8e7320SHeinrich Kuhn if (dev->data->nb_rx_queues > 1) { 537f8e7320SHeinrich Kuhn PMD_INIT_LOG(ERR, "PMD rx interrupt only " 54b6de4353SZerun Fu "supports 1 queue with UIO."); 557f8e7320SHeinrich Kuhn return -EIO; 567f8e7320SHeinrich Kuhn } 577f8e7320SHeinrich Kuhn } 58b0c496abSChaoyong He 597f8e7320SHeinrich Kuhn intr_vector = dev->data->nb_rx_queues; 60c01e5c0cSChaoyong He if (rte_intr_efd_enable(intr_handle, intr_vector) != 0) 617f8e7320SHeinrich Kuhn return -1; 627f8e7320SHeinrich Kuhn 637f8e7320SHeinrich Kuhn nfp_configure_rx_interrupt(dev, intr_handle); 647f8e7320SHeinrich Kuhn update = NFP_NET_CFG_UPDATE_MSIX; 657f8e7320SHeinrich Kuhn } 667f8e7320SHeinrich Kuhn 677f8e7320SHeinrich Kuhn rte_intr_enable(intr_handle); 687f8e7320SHeinrich Kuhn 697f8e7320SHeinrich Kuhn new_ctrl = nfp_check_offloads(dev); 707f8e7320SHeinrich Kuhn 717f8e7320SHeinrich Kuhn /* Writing configuration parameters in the device */ 729d723baaSChaoyong He net_hw = dev->data->dev_private; 7372d1dea6SChaoyong He hw = &net_hw->super; 7472d1dea6SChaoyong He nfp_net_params_setup(net_hw); 757f8e7320SHeinrich Kuhn 767f8e7320SHeinrich Kuhn dev_conf = &dev->data->dev_conf; 777f8e7320SHeinrich Kuhn rxmode = &dev_conf->rxmode; 787f8e7320SHeinrich Kuhn 79b8e15e9fSLong Wu if ((rxmode->offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) != 0) { 807f8e7320SHeinrich Kuhn nfp_net_rss_config_default(dev); 817f8e7320SHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_RSS; 8272d1dea6SChaoyong He new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap); 837f8e7320SHeinrich Kuhn } 847f8e7320SHeinrich Kuhn 857f8e7320SHeinrich Kuhn /* Enable device */ 867f8e7320SHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; 877f8e7320SHeinrich Kuhn 887f8e7320SHeinrich Kuhn update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING; 897f8e7320SHeinrich Kuhn 9072d1dea6SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0) 917f8e7320SHeinrich Kuhn new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; 927f8e7320SHeinrich Kuhn 9372d1dea6SChaoyong He nn_cfg_writel(hw, NFP_NET_CFG_CTRL, new_ctrl); 9472d1dea6SChaoyong He if (nfp_reconfig(hw, new_ctrl, update) != 0) 957f8e7320SHeinrich Kuhn return -EIO; 967f8e7320SHeinrich Kuhn 9761847adcSChaoyong He hw->ctrl = new_ctrl; 9861847adcSChaoyong He 997f8e7320SHeinrich Kuhn /* 1007f8e7320SHeinrich Kuhn * Allocating rte mbufs for configured rx queues. 10140688372SChaoyong He * This requires queues being enabled before. 1027f8e7320SHeinrich Kuhn */ 103c01e5c0cSChaoyong He if (nfp_net_rx_freelist_setup(dev) != 0) { 1047f8e7320SHeinrich Kuhn ret = -ENOMEM; 1057f8e7320SHeinrich Kuhn goto error; 1067f8e7320SHeinrich Kuhn } 1077f8e7320SHeinrich Kuhn 108c46216e7SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 109c46216e7SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 110c46216e7SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 111c46216e7SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 112c46216e7SJie Hai 1137f8e7320SHeinrich Kuhn return 0; 1147f8e7320SHeinrich Kuhn 1157f8e7320SHeinrich Kuhn error: 1167f8e7320SHeinrich Kuhn /* 1177f8e7320SHeinrich Kuhn * An error returned by this function should mean the app 1187f8e7320SHeinrich Kuhn * exiting and then the system releasing all the memory 1197f8e7320SHeinrich Kuhn * allocated even memory coming from hugepages. 1207f8e7320SHeinrich Kuhn * 1217f8e7320SHeinrich Kuhn * The device could be enabled at this point with some queues 1227f8e7320SHeinrich Kuhn * ready for getting packets. This is true if the call to 1237f8e7320SHeinrich Kuhn * nfp_net_rx_freelist_setup() succeeds for some queues but 1247f8e7320SHeinrich Kuhn * fails for subsequent queues. 1257f8e7320SHeinrich Kuhn * 1267f8e7320SHeinrich Kuhn * This should make the app exiting but better if we tell the 1277f8e7320SHeinrich Kuhn * device first. 1287f8e7320SHeinrich Kuhn */ 1297f8e7320SHeinrich Kuhn nfp_net_disable_queues(dev); 1307f8e7320SHeinrich Kuhn 1317f8e7320SHeinrich Kuhn return ret; 1327f8e7320SHeinrich Kuhn } 1337f8e7320SHeinrich Kuhn 1347f8e7320SHeinrich Kuhn static int 1357f8e7320SHeinrich Kuhn nfp_netvf_stop(struct rte_eth_dev *dev) 1367f8e7320SHeinrich Kuhn { 1377f8e7320SHeinrich Kuhn nfp_net_disable_queues(dev); 1387f8e7320SHeinrich Kuhn 1397f8e7320SHeinrich Kuhn /* Clear queues */ 1401c8d02bbSJin Liu nfp_net_stop_tx_queue(dev); 1417f8e7320SHeinrich Kuhn 1421c8d02bbSJin Liu nfp_net_stop_rx_queue(dev); 1437f8e7320SHeinrich Kuhn 1447f8e7320SHeinrich Kuhn return 0; 1457f8e7320SHeinrich Kuhn } 1467f8e7320SHeinrich Kuhn 1477f8e7320SHeinrich Kuhn static int 1487f8e7320SHeinrich Kuhn nfp_netvf_set_link_up(struct rte_eth_dev *dev __rte_unused) 1497f8e7320SHeinrich Kuhn { 1507f8e7320SHeinrich Kuhn return -ENOTSUP; 1517f8e7320SHeinrich Kuhn } 1527f8e7320SHeinrich Kuhn 1537f8e7320SHeinrich Kuhn /* Set the link down. */ 1547f8e7320SHeinrich Kuhn static int 1557f8e7320SHeinrich Kuhn nfp_netvf_set_link_down(struct rte_eth_dev *dev __rte_unused) 1567f8e7320SHeinrich Kuhn { 1577f8e7320SHeinrich Kuhn return -ENOTSUP; 1587f8e7320SHeinrich Kuhn } 1597f8e7320SHeinrich Kuhn 1607f8e7320SHeinrich Kuhn /* Reset and stop device. The device can not be restarted. */ 1617f8e7320SHeinrich Kuhn static int 1627f8e7320SHeinrich Kuhn nfp_netvf_close(struct rte_eth_dev *dev) 1637f8e7320SHeinrich Kuhn { 164a7904d1cSChaoyong He struct nfp_net_hw *net_hw; 1657f8e7320SHeinrich Kuhn struct rte_pci_device *pci_dev; 166d81e2b51SChaoyong He struct nfp_net_hw_priv *hw_priv; 1677f8e7320SHeinrich Kuhn 1687f8e7320SHeinrich Kuhn if (rte_eal_process_type() != RTE_PROC_PRIMARY) 1697f8e7320SHeinrich Kuhn return 0; 1707f8e7320SHeinrich Kuhn 171a7904d1cSChaoyong He net_hw = dev->data->dev_private; 1727f8e7320SHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(dev); 173d81e2b51SChaoyong He hw_priv = dev->process_private; 1747f8e7320SHeinrich Kuhn 175a7904d1cSChaoyong He rte_free(net_hw->eth_xstats_base); 176d81e2b51SChaoyong He rte_free(hw_priv); 177a7904d1cSChaoyong He 1787f8e7320SHeinrich Kuhn /* 1797f8e7320SHeinrich Kuhn * We assume that the DPDK application is stopping all the 1807f8e7320SHeinrich Kuhn * threads/queues before calling the device close function. 1817f8e7320SHeinrich Kuhn */ 1827f8e7320SHeinrich Kuhn nfp_net_disable_queues(dev); 1837f8e7320SHeinrich Kuhn 1847f8e7320SHeinrich Kuhn /* Clear queues */ 1851c8d02bbSJin Liu nfp_net_close_tx_queue(dev); 1861c8d02bbSJin Liu nfp_net_close_rx_queue(dev); 1877f8e7320SHeinrich Kuhn 188d61138d4SHarman Kalra rte_intr_disable(pci_dev->intr_handle); 1897f8e7320SHeinrich Kuhn 19040688372SChaoyong He /* Unregister callback func from eal lib */ 191d61138d4SHarman Kalra rte_intr_callback_unregister(pci_dev->intr_handle, 192f4d24fe9SChaoyong He nfp_net_dev_interrupt_handler, (void *)dev); 1937f8e7320SHeinrich Kuhn 194851f03e1SHeinrich Kuhn /* Cancel possible impending LSC work here before releasing the port */ 195f4d24fe9SChaoyong He rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev); 196851f03e1SHeinrich Kuhn 1977f8e7320SHeinrich Kuhn return 0; 1987f8e7320SHeinrich Kuhn } 1997f8e7320SHeinrich Kuhn 2007f8e7320SHeinrich Kuhn /* Initialise and register VF driver with DPDK Application */ 2018d961320SJin Liu static const struct eth_dev_ops nfp_netvf_eth_dev_ops = { 2027f8e7320SHeinrich Kuhn .dev_configure = nfp_net_configure, 2037f8e7320SHeinrich Kuhn .dev_start = nfp_netvf_start, 2047f8e7320SHeinrich Kuhn .dev_stop = nfp_netvf_stop, 2057f8e7320SHeinrich Kuhn .dev_set_link_up = nfp_netvf_set_link_up, 2067f8e7320SHeinrich Kuhn .dev_set_link_down = nfp_netvf_set_link_down, 2077f8e7320SHeinrich Kuhn .dev_close = nfp_netvf_close, 2087f8e7320SHeinrich Kuhn .promiscuous_enable = nfp_net_promisc_enable, 2097f8e7320SHeinrich Kuhn .promiscuous_disable = nfp_net_promisc_disable, 2104a86c36bSQin Ke .allmulticast_enable = nfp_net_allmulticast_enable, 2114a86c36bSQin Ke .allmulticast_disable = nfp_net_allmulticast_disable, 2127f8e7320SHeinrich Kuhn .link_update = nfp_net_link_update, 2137f8e7320SHeinrich Kuhn .stats_get = nfp_net_stats_get, 2147f8e7320SHeinrich Kuhn .stats_reset = nfp_net_stats_reset, 215f26e8239SJames Hershaw .xstats_get = nfp_net_xstats_get, 216f26e8239SJames Hershaw .xstats_reset = nfp_net_xstats_reset, 217f26e8239SJames Hershaw .xstats_get_names = nfp_net_xstats_get_names, 218f26e8239SJames Hershaw .xstats_get_by_id = nfp_net_xstats_get_by_id, 219f26e8239SJames Hershaw .xstats_get_names_by_id = nfp_net_xstats_get_names_by_id, 2207f8e7320SHeinrich Kuhn .dev_infos_get = nfp_net_infos_get, 2217f8e7320SHeinrich Kuhn .dev_supported_ptypes_get = nfp_net_supported_ptypes_get, 2227f8e7320SHeinrich Kuhn .mtu_set = nfp_net_dev_mtu_set, 2230a94d6bcSJin Liu .mac_addr_set = nfp_net_set_mac_addr, 2247f8e7320SHeinrich Kuhn .vlan_offload_set = nfp_net_vlan_offload_set, 2257f8e7320SHeinrich Kuhn .reta_update = nfp_net_reta_update, 2267f8e7320SHeinrich Kuhn .reta_query = nfp_net_reta_query, 2277f8e7320SHeinrich Kuhn .rss_hash_update = nfp_net_rss_hash_update, 2287f8e7320SHeinrich Kuhn .rss_hash_conf_get = nfp_net_rss_hash_conf_get, 2297f8e7320SHeinrich Kuhn .rx_queue_setup = nfp_net_rx_queue_setup, 2307f8e7320SHeinrich Kuhn .rx_queue_release = nfp_net_rx_queue_release, 2318d961320SJin Liu .tx_queue_setup = nfp_net_tx_queue_setup, 23252ddc4c2SJin Liu .tx_queue_release = nfp_net_tx_queue_release, 23352ddc4c2SJin Liu .rx_queue_intr_enable = nfp_rx_queue_intr_enable, 23452ddc4c2SJin Liu .rx_queue_intr_disable = nfp_rx_queue_intr_disable, 235*4dcbf32fSChaoyong He .rx_burst_mode_get = nfp_net_rx_burst_mode_get, 236*4dcbf32fSChaoyong He .tx_burst_mode_get = nfp_net_tx_burst_mode_get, 23752ddc4c2SJin Liu }; 23852ddc4c2SJin Liu 239ee8ca64eSChaoyong He static inline void 240000feb4cSChaoyong He nfp_netvf_ethdev_ops_mount(struct nfp_pf_dev *pf_dev, 241ee8ca64eSChaoyong He struct rte_eth_dev *eth_dev) 242266470b2SJin Liu { 243000feb4cSChaoyong He if (pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3) 244ee8ca64eSChaoyong He eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts; 245ee8ca64eSChaoyong He else 246fb6befdfSLong Wu nfp_net_nfdk_xmit_pkts_set(eth_dev); 247266470b2SJin Liu 2488d961320SJin Liu eth_dev->dev_ops = &nfp_netvf_eth_dev_ops; 249266470b2SJin Liu eth_dev->rx_queue_count = nfp_net_rx_queue_count; 250b6755530SLong Wu nfp_net_recv_pkts_set(eth_dev); 251266470b2SJin Liu } 252266470b2SJin Liu 2537f8e7320SHeinrich Kuhn static int 2547f8e7320SHeinrich Kuhn nfp_netvf_init(struct rte_eth_dev *eth_dev) 2557f8e7320SHeinrich Kuhn { 25649952141SChaoyong He int err; 257e7978635SChaoyong He uint16_t port; 2587f8e7320SHeinrich Kuhn uint32_t start_q; 2594a9bb682SChaoyong He struct nfp_hw *hw; 2604a9bb682SChaoyong He struct nfp_net_hw *net_hw; 261000feb4cSChaoyong He struct nfp_pf_dev *pf_dev; 26249952141SChaoyong He uint64_t tx_bar_off = 0; 26349952141SChaoyong He uint64_t rx_bar_off = 0; 26449952141SChaoyong He struct rte_pci_device *pci_dev; 265d81e2b51SChaoyong He struct nfp_net_hw_priv *hw_priv; 2660314a8ffSChaoyong He const struct nfp_dev_info *dev_info; 2677f8e7320SHeinrich Kuhn 268e7978635SChaoyong He port = eth_dev->data->port_id; 2697f8e7320SHeinrich Kuhn pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 2707f8e7320SHeinrich Kuhn 2710314a8ffSChaoyong He dev_info = nfp_dev_info_get(pci_dev->id.device_id); 2720314a8ffSChaoyong He if (dev_info == NULL) { 273b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Not supported device ID."); 2740314a8ffSChaoyong He return -ENODEV; 2750314a8ffSChaoyong He } 2760314a8ffSChaoyong He 2779d723baaSChaoyong He net_hw = eth_dev->data->dev_private; 2784a9bb682SChaoyong He hw = &net_hw->super; 2797f8e7320SHeinrich Kuhn 2804a9bb682SChaoyong He hw->ctrl_bar = pci_dev->mem_resource[0].addr; 2814a9bb682SChaoyong He if (hw->ctrl_bar == NULL) { 282b6de4353SZerun Fu PMD_DRV_LOG(ERR, "The hw->super.ctrl_bar is NULL. BAR0 not configured."); 283266470b2SJin Liu return -ENODEV; 284266470b2SJin Liu } 285266470b2SJin Liu 286000feb4cSChaoyong He pf_dev = rte_zmalloc(NULL, sizeof(*pf_dev), 0); 287000feb4cSChaoyong He if (pf_dev == NULL) { 288000feb4cSChaoyong He PMD_INIT_LOG(ERR, "Can not allocate memory for the PF device."); 289000feb4cSChaoyong He return -ENOMEM; 290000feb4cSChaoyong He } 291000feb4cSChaoyong He 292000feb4cSChaoyong He pf_dev->pci_dev = pci_dev; 293000feb4cSChaoyong He 294000feb4cSChaoyong He /* Check the version from firmware */ 295000feb4cSChaoyong He if (!nfp_net_version_check(hw, pf_dev)) { 296000feb4cSChaoyong He err = -EINVAL; 297000feb4cSChaoyong He goto pf_dev_free; 298000feb4cSChaoyong He } 299000feb4cSChaoyong He 30019bd7cceSChaoyong He /* Set the ctrl bar size */ 30119bd7cceSChaoyong He nfp_net_ctrl_bar_size_set(pf_dev); 30219bd7cceSChaoyong He 303b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "Ctrl bar: %p.", hw->ctrl_bar); 304266470b2SJin Liu 305000feb4cSChaoyong He err = nfp_net_common_init(pf_dev, net_hw); 306cd4397ebSPeng Zhang if (err != 0) 307000feb4cSChaoyong He goto pf_dev_free; 308fd392f84SPeng Zhang 309000feb4cSChaoyong He nfp_netvf_ethdev_ops_mount(pf_dev, eth_dev); 3107f8e7320SHeinrich Kuhn 311d81e2b51SChaoyong He hw_priv = rte_zmalloc(NULL, sizeof(*hw_priv), 0); 312d81e2b51SChaoyong He if (hw_priv == NULL) { 313b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Can not alloc memory for hw priv data."); 314d81e2b51SChaoyong He err = -ENOMEM; 315d81e2b51SChaoyong He goto hw_priv_free; 316d81e2b51SChaoyong He } 317d81e2b51SChaoyong He 318d81e2b51SChaoyong He hw_priv->dev_info = dev_info; 319000feb4cSChaoyong He hw_priv->pf_dev = pf_dev; 320d81e2b51SChaoyong He 321636e133eSPeng Zhang if (!nfp_net_recv_pkt_meta_check_register(hw_priv)) { 322636e133eSPeng Zhang PMD_INIT_LOG(ERR, "VF register meta check function failed."); 323636e133eSPeng Zhang err = -EINVAL; 324636e133eSPeng Zhang goto hw_priv_free; 325636e133eSPeng Zhang } 326636e133eSPeng Zhang 327d81e2b51SChaoyong He eth_dev->process_private = hw_priv; 328d81e2b51SChaoyong He 3297f8e7320SHeinrich Kuhn /* For secondary processes, the primary has done all the work */ 3307f8e7320SHeinrich Kuhn if (rte_eal_process_type() != RTE_PROC_PRIMARY) 3317f8e7320SHeinrich Kuhn return 0; 3327f8e7320SHeinrich Kuhn 3339fa4d03fSChaoyong He net_hw->eth_xstats_base = rte_calloc("rte_eth_xstat", 3349fa4d03fSChaoyong He nfp_net_xstats_size(eth_dev), sizeof(struct rte_eth_xstat), 0); 3354a9bb682SChaoyong He if (net_hw->eth_xstats_base == NULL) { 336030b2b19SChaoyong He PMD_INIT_LOG(ERR, "No memory for xstats base values on device %s!", 337f26e8239SJames Hershaw pci_dev->device.name); 3389fa4d03fSChaoyong He err = -ENOMEM; 3399fa4d03fSChaoyong He goto hw_priv_free; 340f26e8239SJames Hershaw } 341f26e8239SJames Hershaw 3427f8e7320SHeinrich Kuhn /* Work out where in the BAR the queues start. */ 3434a9bb682SChaoyong He start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ); 3440314a8ffSChaoyong He tx_bar_off = nfp_qcp_queue_offset(dev_info, start_q); 3454a9bb682SChaoyong He start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ); 3460314a8ffSChaoyong He rx_bar_off = nfp_qcp_queue_offset(dev_info, start_q); 3477f8e7320SHeinrich Kuhn 3484a9bb682SChaoyong He net_hw->tx_bar = (uint8_t *)pci_dev->mem_resource[2].addr + tx_bar_off; 3494a9bb682SChaoyong He net_hw->rx_bar = (uint8_t *)pci_dev->mem_resource[2].addr + rx_bar_off; 3507f8e7320SHeinrich Kuhn 351b6de4353SZerun Fu PMD_INIT_LOG(DEBUG, "The ctrl_bar: %p, tx_bar: %p, rx_bar: %p.", 3524a9bb682SChaoyong He hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar); 3537f8e7320SHeinrich Kuhn 3544a9bb682SChaoyong He nfp_net_cfg_queue_setup(net_hw); 3554a9bb682SChaoyong He net_hw->mtu = RTE_ETHER_MTU; 3567f8e7320SHeinrich Kuhn 3577f8e7320SHeinrich Kuhn /* VLAN insertion is incompatible with LSOv2 */ 3584a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0) 3594a9bb682SChaoyong He hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN; 3607f8e7320SHeinrich Kuhn 361000feb4cSChaoyong He nfp_net_log_device_information(net_hw, pf_dev); 3627f8e7320SHeinrich Kuhn 3637f8e7320SHeinrich Kuhn /* Initializing spinlock for reconfigs */ 3644a9bb682SChaoyong He rte_spinlock_init(&hw->reconfig_lock); 3657f8e7320SHeinrich Kuhn 3667f8e7320SHeinrich Kuhn /* Allocating memory for mac addr */ 367f4d24fe9SChaoyong He eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0); 3687f8e7320SHeinrich Kuhn if (eth_dev->data->mac_addrs == NULL) { 369b6de4353SZerun Fu PMD_INIT_LOG(ERR, "Failed to space for MAC address."); 3707f8e7320SHeinrich Kuhn err = -ENOMEM; 371a7904d1cSChaoyong He goto free_xstats; 3727f8e7320SHeinrich Kuhn } 3737f8e7320SHeinrich Kuhn 374503ac807SChaoyong He nfp_read_mac(hw); 3754a9bb682SChaoyong He if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) { 376b6de4353SZerun Fu PMD_INIT_LOG(INFO, "Using random mac address for port %hu.", port); 3777f8e7320SHeinrich Kuhn /* Using random mac addresses for VFs */ 3784a9bb682SChaoyong He rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]); 379503ac807SChaoyong He nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]); 3807f8e7320SHeinrich Kuhn } 3817f8e7320SHeinrich Kuhn 3827f8e7320SHeinrich Kuhn /* Copying mac address to DPDK eth_dev struct */ 3834a9bb682SChaoyong He rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs); 3847f8e7320SHeinrich Kuhn 3854a9bb682SChaoyong He if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) 3867f8e7320SHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR; 3877f8e7320SHeinrich Kuhn 3887f8e7320SHeinrich Kuhn eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 3897f8e7320SHeinrich Kuhn 390f6272c7aSZerun Fu PMD_INIT_LOG(INFO, "Port %hu VendorID=%#x DeviceID=%#x " 391393e5822SChaoyong He "mac=" RTE_ETHER_ADDR_PRT_FMT, 392e7978635SChaoyong He port, pci_dev->id.vendor_id, 3937f8e7320SHeinrich Kuhn pci_dev->id.device_id, 3944a9bb682SChaoyong He RTE_ETHER_ADDR_BYTES(&hw->mac_addr)); 3957f8e7320SHeinrich Kuhn 3967f8e7320SHeinrich Kuhn /* Registering LSC interrupt handler */ 397d61138d4SHarman Kalra rte_intr_callback_register(pci_dev->intr_handle, 398f4d24fe9SChaoyong He nfp_net_dev_interrupt_handler, (void *)eth_dev); 3997f8e7320SHeinrich Kuhn /* Telling the firmware about the LSC interrupt entry */ 4004a9bb682SChaoyong He nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); 40194d0631aSPeng Zhang /* Unmask the LSC interrupt */ 40294d0631aSPeng Zhang nfp_net_irq_unmask(eth_dev); 4037f8e7320SHeinrich Kuhn /* Recording current stats counters values */ 4047f8e7320SHeinrich Kuhn nfp_net_stats_reset(eth_dev); 4057f8e7320SHeinrich Kuhn 4067f8e7320SHeinrich Kuhn return 0; 4077f8e7320SHeinrich Kuhn 408a7904d1cSChaoyong He free_xstats: 409a7904d1cSChaoyong He rte_free(net_hw->eth_xstats_base); 410d81e2b51SChaoyong He hw_priv_free: 411d81e2b51SChaoyong He rte_free(hw_priv); 412000feb4cSChaoyong He pf_dev_free: 413000feb4cSChaoyong He rte_free(pf_dev); 4147f8e7320SHeinrich Kuhn 4157f8e7320SHeinrich Kuhn return err; 4167f8e7320SHeinrich Kuhn } 4177f8e7320SHeinrich Kuhn 4187f8e7320SHeinrich Kuhn static const struct rte_pci_id pci_id_nfp_vf_net_map[] = { 4197f8e7320SHeinrich Kuhn { 4207f8e7320SHeinrich Kuhn RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 4215c464d6aSJin Liu PCI_DEVICE_ID_NFP3800_VF_NIC) 4225c464d6aSJin Liu }, 4235c464d6aSJin Liu { 4245c464d6aSJin Liu RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME, 4257f8e7320SHeinrich Kuhn PCI_DEVICE_ID_NFP6000_VF_NIC) 4267f8e7320SHeinrich Kuhn }, 4277f8e7320SHeinrich Kuhn { 4285aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 4295aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP3800_VF_NIC) 4305aedd4c3SJames Hershaw }, 4315aedd4c3SJames Hershaw { 4325aedd4c3SJames Hershaw RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE, 4335aedd4c3SJames Hershaw PCI_DEVICE_ID_NFP6000_VF_NIC) 4345aedd4c3SJames Hershaw }, 4355aedd4c3SJames Hershaw { 4367f8e7320SHeinrich Kuhn .vendor_id = 0, 4377f8e7320SHeinrich Kuhn }, 4387f8e7320SHeinrich Kuhn }; 4397f8e7320SHeinrich Kuhn 440f4d24fe9SChaoyong He static int 441f4d24fe9SChaoyong He nfp_vf_pci_uninit(struct rte_eth_dev *eth_dev) 4427f8e7320SHeinrich Kuhn { 4437f8e7320SHeinrich Kuhn /* VF cleanup, just free private port data */ 4447f8e7320SHeinrich Kuhn return nfp_netvf_close(eth_dev); 4457f8e7320SHeinrich Kuhn } 4467f8e7320SHeinrich Kuhn 447f4d24fe9SChaoyong He static int 448214fb306SChaoyong He nfp_vf_pci_probe(struct rte_pci_device *pci_dev) 4497f8e7320SHeinrich Kuhn { 4507f8e7320SHeinrich Kuhn return rte_eth_dev_pci_generic_probe(pci_dev, 4519d723baaSChaoyong He sizeof(struct nfp_net_hw), nfp_netvf_init); 4527f8e7320SHeinrich Kuhn } 4537f8e7320SHeinrich Kuhn 454f4d24fe9SChaoyong He static int 455845fcd13SChaoyong He nfp_vf_pci_remove(struct rte_pci_device *pci_dev) 4567f8e7320SHeinrich Kuhn { 4577f8e7320SHeinrich Kuhn return rte_eth_dev_pci_generic_remove(pci_dev, nfp_vf_pci_uninit); 4587f8e7320SHeinrich Kuhn } 4597f8e7320SHeinrich Kuhn 460214fb306SChaoyong He static struct nfp_class_driver rte_nfp_net_vf_pmd = { 461214fb306SChaoyong He .drv_class = NFP_CLASS_ETH, 462214fb306SChaoyong He .name = RTE_STR(net_nfp_vf), 4637f8e7320SHeinrich Kuhn .id_table = pci_id_nfp_vf_net_map, 4647f8e7320SHeinrich Kuhn .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 465845fcd13SChaoyong He .probe = nfp_vf_pci_probe, 466845fcd13SChaoyong He .remove = nfp_vf_pci_remove, 4677f8e7320SHeinrich Kuhn }; 4687f8e7320SHeinrich Kuhn 469214fb306SChaoyong He RTE_INIT(rte_nfp_vf_pmd_init) 470214fb306SChaoyong He { 471214fb306SChaoyong He nfp_class_driver_register(&rte_nfp_net_vf_pmd); 472214fb306SChaoyong He } 473214fb306SChaoyong He 474d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI_TABLE(NFP_VF_DRIVER_NAME, pci_id_nfp_vf_net_map); 475d505ee1dSChaoyong He RTE_PMD_REGISTER_KMOD_DEP(NFP_VF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio"); 476