xref: /dpdk/drivers/net/nfp/nfp_ethdev_vf.c (revision 4dcbf32ffefd84dbb5924de3b2c6dd517f7809c8)
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