xref: /dpdk/drivers/net/nfp/nfp_ethdev.c (revision c7a6970fc63782fee97a0af4f57326b46bcd9de9)
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 
28*c7a6970fSZerun Fu /* 64-bit per app capabilities */
29*c7a6970fSZerun Fu #define NFP_NET_APP_CAP_SP_INDIFF       RTE_BIT64(0) /* Indifferent to port speed */
30*c7a6970fSZerun 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 
48646ea79cSHeinrich Kuhn static int
49646ea79cSHeinrich Kuhn nfp_net_start(struct rte_eth_dev *dev)
50646ea79cSHeinrich Kuhn {
5149952141SChaoyong He 	int ret;
5249952141SChaoyong He 	uint16_t i;
5372d1dea6SChaoyong He 	struct nfp_hw *hw;
5449952141SChaoyong He 	uint32_t new_ctrl;
55acb6bebfSChaoyong He 	struct nfp_cpp *cpp;
5649952141SChaoyong He 	uint32_t update = 0;
572e7c3612SQin Ke 	uint32_t cap_extend;
5849952141SChaoyong He 	uint32_t intr_vector;
5949952141SChaoyong He 	uint32_t ctrl_extend = 0;
6072d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
61646ea79cSHeinrich Kuhn 	struct nfp_pf_dev *pf_dev;
62646ea79cSHeinrich Kuhn 	struct rte_eth_rxmode *rxmode;
6349952141SChaoyong He 	struct nfp_app_fw_nic *app_fw_nic;
6449952141SChaoyong He 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
6549952141SChaoyong He 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
66646ea79cSHeinrich Kuhn 
679d723baaSChaoyong He 	net_hw = dev->data->dev_private;
6865f6915dSChaoyong He 	pf_dev = net_hw->pf_dev;
69968ec1c3SChaoyong He 	app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
7072d1dea6SChaoyong He 	hw = &net_hw->super;
71646ea79cSHeinrich Kuhn 
72646ea79cSHeinrich Kuhn 	/* Disabling queues just in case... */
73646ea79cSHeinrich Kuhn 	nfp_net_disable_queues(dev);
74646ea79cSHeinrich Kuhn 
75646ea79cSHeinrich Kuhn 	/* Enabling the required queues in the device */
76646ea79cSHeinrich Kuhn 	nfp_net_enable_queues(dev);
77646ea79cSHeinrich Kuhn 
7840688372SChaoyong He 	/* Check and configure queue intr-vector mapping */
79646ea79cSHeinrich Kuhn 	if (dev->data->dev_conf.intr_conf.rxq != 0) {
80968ec1c3SChaoyong He 		if (app_fw_nic->multiport) {
81646ea79cSHeinrich Kuhn 			PMD_INIT_LOG(ERR, "PMD rx interrupt is not supported "
82646ea79cSHeinrich Kuhn 					"with NFP multiport PF");
83646ea79cSHeinrich Kuhn 				return -EINVAL;
84646ea79cSHeinrich Kuhn 		}
85b0c496abSChaoyong He 
86f4d24fe9SChaoyong He 		if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) {
87646ea79cSHeinrich Kuhn 			/*
88646ea79cSHeinrich Kuhn 			 * Better not to share LSC with RX interrupts.
8940688372SChaoyong He 			 * Unregistering LSC interrupt handler.
90646ea79cSHeinrich Kuhn 			 */
91e7978635SChaoyong He 			rte_intr_callback_unregister(intr_handle,
92646ea79cSHeinrich Kuhn 					nfp_net_dev_interrupt_handler, (void *)dev);
93646ea79cSHeinrich Kuhn 
94646ea79cSHeinrich Kuhn 			if (dev->data->nb_rx_queues > 1) {
95646ea79cSHeinrich Kuhn 				PMD_INIT_LOG(ERR, "PMD rx interrupt only "
96646ea79cSHeinrich Kuhn 						"supports 1 queue with UIO");
97646ea79cSHeinrich Kuhn 				return -EIO;
98646ea79cSHeinrich Kuhn 			}
99646ea79cSHeinrich Kuhn 		}
100b0c496abSChaoyong He 
101646ea79cSHeinrich Kuhn 		intr_vector = dev->data->nb_rx_queues;
102c01e5c0cSChaoyong He 		if (rte_intr_efd_enable(intr_handle, intr_vector) != 0)
103646ea79cSHeinrich Kuhn 			return -1;
104646ea79cSHeinrich Kuhn 
105646ea79cSHeinrich Kuhn 		nfp_configure_rx_interrupt(dev, intr_handle);
106646ea79cSHeinrich Kuhn 		update = NFP_NET_CFG_UPDATE_MSIX;
107646ea79cSHeinrich Kuhn 	}
108646ea79cSHeinrich Kuhn 
109dbad6f64SPeng Zhang 	/* Checking MTU set */
11072d1dea6SChaoyong He 	if (dev->data->mtu > net_hw->flbufsz) {
111dbad6f64SPeng Zhang 		PMD_INIT_LOG(ERR, "MTU (%u) can't be larger than the current NFP_FRAME_SIZE (%u)",
11272d1dea6SChaoyong He 				dev->data->mtu, net_hw->flbufsz);
113dbad6f64SPeng Zhang 		return -ERANGE;
114dbad6f64SPeng Zhang 	}
115dbad6f64SPeng Zhang 
116646ea79cSHeinrich Kuhn 	rte_intr_enable(intr_handle);
117646ea79cSHeinrich Kuhn 
118646ea79cSHeinrich Kuhn 	new_ctrl = nfp_check_offloads(dev);
119646ea79cSHeinrich Kuhn 
120646ea79cSHeinrich Kuhn 	/* Writing configuration parameters in the device */
12172d1dea6SChaoyong He 	nfp_net_params_setup(net_hw);
122646ea79cSHeinrich Kuhn 
123c4de52ecSChaoyong He 	rxmode = &dev->data->dev_conf.rxmode;
124c01e5c0cSChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS) != 0) {
125646ea79cSHeinrich Kuhn 		nfp_net_rss_config_default(dev);
126646ea79cSHeinrich Kuhn 		update |= NFP_NET_CFG_UPDATE_RSS;
12772d1dea6SChaoyong He 		new_ctrl |= nfp_net_cfg_ctrl_rss(hw->cap);
128646ea79cSHeinrich Kuhn 	}
129646ea79cSHeinrich Kuhn 
130646ea79cSHeinrich Kuhn 	/* Enable device */
131646ea79cSHeinrich Kuhn 	new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
132646ea79cSHeinrich Kuhn 
133646ea79cSHeinrich Kuhn 	update |= NFP_NET_CFG_UPDATE_GEN | NFP_NET_CFG_UPDATE_RING;
134646ea79cSHeinrich Kuhn 
135c55abf61SChaoyong He 	/* Enable vxlan */
13672d1dea6SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_VXLAN) != 0) {
137c55abf61SChaoyong He 		new_ctrl |= NFP_NET_CFG_CTRL_VXLAN;
138c55abf61SChaoyong He 		update |= NFP_NET_CFG_UPDATE_VXLAN;
139c925a157SFei Qin 	}
140c55abf61SChaoyong He 
14172d1dea6SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
142646ea79cSHeinrich Kuhn 		new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG;
143646ea79cSHeinrich Kuhn 
14472d1dea6SChaoyong He 	if (nfp_reconfig(hw, new_ctrl, update) != 0)
145646ea79cSHeinrich Kuhn 		return -EIO;
146646ea79cSHeinrich Kuhn 
1471e80c074SChaoyong He 	hw->ctrl = new_ctrl;
1481e80c074SChaoyong He 
1492e7c3612SQin Ke 	/* Enable packet type offload by extend ctrl word1. */
15072d1dea6SChaoyong He 	cap_extend = hw->cap_ext;
1512e7c3612SQin Ke 	if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0)
1522e7c3612SQin Ke 		ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE;
1532e7c3612SQin Ke 
15454713740SChang Miao 	if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0)
15554713740SChang Miao 		ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP
15654713740SChang Miao 				| NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP;
15754713740SChang Miao 
1588153bc6fSChaoyong He 	/* Enable flow steer by extend ctrl word1. */
1598153bc6fSChaoyong He 	if ((cap_extend & NFP_NET_CFG_CTRL_FLOW_STEER) != 0)
1608153bc6fSChaoyong He 		ctrl_extend |= NFP_NET_CFG_CTRL_FLOW_STEER;
1618153bc6fSChaoyong He 
1622e7c3612SQin Ke 	update = NFP_NET_CFG_UPDATE_GEN;
16372d1dea6SChaoyong He 	if (nfp_ext_reconfig(hw, ctrl_extend, update) != 0)
1642e7c3612SQin Ke 		return -EIO;
1652e7c3612SQin Ke 
16672d1dea6SChaoyong He 	hw->ctrl_ext = ctrl_extend;
167b4b6988aSChaoyong He 
168646ea79cSHeinrich Kuhn 	/*
169646ea79cSHeinrich Kuhn 	 * Allocating rte mbufs for configured rx queues.
17040688372SChaoyong He 	 * This requires queues being enabled before.
171646ea79cSHeinrich Kuhn 	 */
172c01e5c0cSChaoyong He 	if (nfp_net_rx_freelist_setup(dev) != 0) {
173646ea79cSHeinrich Kuhn 		ret = -ENOMEM;
174646ea79cSHeinrich Kuhn 		goto error;
175646ea79cSHeinrich Kuhn 	}
176646ea79cSHeinrich Kuhn 
177646ea79cSHeinrich Kuhn 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
178acb6bebfSChaoyong He 		cpp = net_hw->cpp;
179646ea79cSHeinrich Kuhn 	else
180acb6bebfSChaoyong He 		cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
181acb6bebfSChaoyong He 
182acb6bebfSChaoyong He 	/* Configure the physical port up */
183acb6bebfSChaoyong He 	nfp_eth_set_configured(cpp, net_hw->nfp_idx, 1);
184646ea79cSHeinrich Kuhn 
185c46216e7SJie Hai 	for (i = 0; i < dev->data->nb_rx_queues; i++)
186c46216e7SJie Hai 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
187c46216e7SJie Hai 	for (i = 0; i < dev->data->nb_tx_queues; i++)
188c46216e7SJie Hai 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
189c46216e7SJie Hai 
190646ea79cSHeinrich Kuhn 	return 0;
191646ea79cSHeinrich Kuhn 
192646ea79cSHeinrich Kuhn error:
193646ea79cSHeinrich Kuhn 	/*
194646ea79cSHeinrich Kuhn 	 * An error returned by this function should mean the app
195646ea79cSHeinrich Kuhn 	 * exiting and then the system releasing all the memory
196646ea79cSHeinrich Kuhn 	 * allocated even memory coming from hugepages.
197646ea79cSHeinrich Kuhn 	 *
198646ea79cSHeinrich Kuhn 	 * The device could be enabled at this point with some queues
199646ea79cSHeinrich Kuhn 	 * ready for getting packets. This is true if the call to
200646ea79cSHeinrich Kuhn 	 * nfp_net_rx_freelist_setup() succeeds for some queues but
201646ea79cSHeinrich Kuhn 	 * fails for subsequent queues.
202646ea79cSHeinrich Kuhn 	 *
203646ea79cSHeinrich Kuhn 	 * This should make the app exiting but better if we tell the
204646ea79cSHeinrich Kuhn 	 * device first.
205646ea79cSHeinrich Kuhn 	 */
206646ea79cSHeinrich Kuhn 	nfp_net_disable_queues(dev);
207646ea79cSHeinrich Kuhn 
208646ea79cSHeinrich Kuhn 	return ret;
209646ea79cSHeinrich Kuhn }
210646ea79cSHeinrich Kuhn 
211646ea79cSHeinrich Kuhn /* Set the link up. */
212646ea79cSHeinrich Kuhn static int
213646ea79cSHeinrich Kuhn nfp_net_set_link_up(struct rte_eth_dev *dev)
214646ea79cSHeinrich Kuhn {
215acb6bebfSChaoyong He 	struct nfp_cpp *cpp;
216646ea79cSHeinrich Kuhn 	struct nfp_net_hw *hw;
217646ea79cSHeinrich Kuhn 
2189d723baaSChaoyong He 	hw = dev->data->dev_private;
219646ea79cSHeinrich Kuhn 
220646ea79cSHeinrich Kuhn 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
221acb6bebfSChaoyong He 		cpp = hw->cpp;
222646ea79cSHeinrich Kuhn 	else
223acb6bebfSChaoyong He 		cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
224acb6bebfSChaoyong He 
225acb6bebfSChaoyong He 	return nfp_eth_set_configured(cpp, hw->nfp_idx, 1);
226646ea79cSHeinrich Kuhn }
227646ea79cSHeinrich Kuhn 
228646ea79cSHeinrich Kuhn /* Set the link down. */
229646ea79cSHeinrich Kuhn static int
230646ea79cSHeinrich Kuhn nfp_net_set_link_down(struct rte_eth_dev *dev)
231646ea79cSHeinrich Kuhn {
232acb6bebfSChaoyong He 	struct nfp_cpp *cpp;
233646ea79cSHeinrich Kuhn 	struct nfp_net_hw *hw;
234646ea79cSHeinrich Kuhn 
2359d723baaSChaoyong He 	hw = dev->data->dev_private;
236646ea79cSHeinrich Kuhn 
237646ea79cSHeinrich Kuhn 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
238acb6bebfSChaoyong He 		cpp = hw->cpp;
239646ea79cSHeinrich Kuhn 	else
240acb6bebfSChaoyong He 		cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
241acb6bebfSChaoyong He 
242acb6bebfSChaoyong He 	return nfp_eth_set_configured(cpp, hw->nfp_idx, 0);
243646ea79cSHeinrich Kuhn }
244646ea79cSHeinrich Kuhn 
2453b00109dSPeng Zhang static uint8_t
2463b00109dSPeng Zhang nfp_function_id_get(const struct nfp_pf_dev *pf_dev,
2473b00109dSPeng Zhang 		uint8_t phy_port)
2483b00109dSPeng Zhang {
2493b00109dSPeng Zhang 	if (pf_dev->multi_pf.enabled)
2503b00109dSPeng Zhang 		return pf_dev->multi_pf.function_id;
2513b00109dSPeng Zhang 
2523b00109dSPeng Zhang 	return phy_port;
2533b00109dSPeng Zhang }
2543b00109dSPeng Zhang 
2558ba461d1SPeng Zhang static void
2568ba461d1SPeng Zhang nfp_net_beat_timer(void *arg)
2578ba461d1SPeng Zhang {
2588ba461d1SPeng Zhang 	uint64_t cur_sec;
2598ba461d1SPeng Zhang 	struct nfp_multi_pf *multi_pf = arg;
2608ba461d1SPeng Zhang 
2618ba461d1SPeng Zhang 	cur_sec = rte_rdtsc();
2628ba461d1SPeng Zhang 	nn_writeq(cur_sec, multi_pf->beat_addr + NFP_BEAT_OFFSET(multi_pf->function_id));
2638ba461d1SPeng Zhang 
2648ba461d1SPeng Zhang 	/* Beat once per second. */
2658ba461d1SPeng Zhang 	if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer,
2668ba461d1SPeng Zhang 			(void *)multi_pf) < 0) {
2678ba461d1SPeng Zhang 		PMD_DRV_LOG(ERR, "Error setting alarm");
2688ba461d1SPeng Zhang 	}
2698ba461d1SPeng Zhang }
2708ba461d1SPeng Zhang 
2718ba461d1SPeng Zhang static int
2728ba461d1SPeng Zhang nfp_net_keepalive_init(struct nfp_cpp *cpp,
2738ba461d1SPeng Zhang 		struct nfp_multi_pf *multi_pf)
2748ba461d1SPeng Zhang {
2758ba461d1SPeng Zhang 	uint8_t *base;
2768ba461d1SPeng Zhang 	uint64_t addr;
2778ba461d1SPeng Zhang 	uint32_t size;
2788ba461d1SPeng Zhang 	uint32_t cpp_id;
2798ba461d1SPeng Zhang 	struct nfp_resource *res;
2808ba461d1SPeng Zhang 
2818ba461d1SPeng Zhang 	res = nfp_resource_acquire(cpp, NFP_RESOURCE_KEEPALIVE);
2828ba461d1SPeng Zhang 	if (res == NULL)
2838ba461d1SPeng Zhang 		return -EIO;
2848ba461d1SPeng Zhang 
2858ba461d1SPeng Zhang 	cpp_id = nfp_resource_cpp_id(res);
2868ba461d1SPeng Zhang 	addr = nfp_resource_address(res);
2878ba461d1SPeng Zhang 	size = nfp_resource_size(res);
2888ba461d1SPeng Zhang 
2898ba461d1SPeng Zhang 	nfp_resource_release(res);
2908ba461d1SPeng Zhang 
2918ba461d1SPeng Zhang 	/* Allocate a fixed area for keepalive. */
2928ba461d1SPeng Zhang 	base = nfp_cpp_map_area(cpp, cpp_id, addr, size, &multi_pf->beat_area);
2938ba461d1SPeng Zhang 	if (base == NULL) {
2948ba461d1SPeng Zhang 		PMD_DRV_LOG(ERR, "Failed to map area for keepalive.");
2958ba461d1SPeng Zhang 		return -EIO;
2968ba461d1SPeng Zhang 	}
2978ba461d1SPeng Zhang 
2988ba461d1SPeng Zhang 	multi_pf->beat_addr = base;
2998ba461d1SPeng Zhang 
3008ba461d1SPeng Zhang 	return 0;
3018ba461d1SPeng Zhang }
3028ba461d1SPeng Zhang 
3038ba461d1SPeng Zhang static void
3048ba461d1SPeng Zhang nfp_net_keepalive_uninit(struct nfp_multi_pf *multi_pf)
3058ba461d1SPeng Zhang {
3068ba461d1SPeng Zhang 	nfp_cpp_area_release_free(multi_pf->beat_area);
3078ba461d1SPeng Zhang }
3088ba461d1SPeng Zhang 
3098ba461d1SPeng Zhang static int
3108ba461d1SPeng Zhang nfp_net_keepalive_start(struct nfp_multi_pf *multi_pf)
3118ba461d1SPeng Zhang {
3128ba461d1SPeng Zhang 	if (rte_eal_alarm_set(1000 * 1000, nfp_net_beat_timer,
3138ba461d1SPeng Zhang 			(void *)multi_pf) < 0) {
3148ba461d1SPeng Zhang 		PMD_DRV_LOG(ERR, "Error setting alarm");
3158ba461d1SPeng Zhang 		return -EIO;
3168ba461d1SPeng Zhang 	}
3178ba461d1SPeng Zhang 
3188ba461d1SPeng Zhang 	return 0;
3198ba461d1SPeng Zhang }
3208ba461d1SPeng Zhang 
3218ba461d1SPeng Zhang static void
3228ba461d1SPeng Zhang nfp_net_keepalive_stop(struct nfp_multi_pf *multi_pf)
3238ba461d1SPeng Zhang {
3248ba461d1SPeng Zhang 	/* Cancel keepalive for multiple PF setup */
3258ba461d1SPeng Zhang 	rte_eal_alarm_cancel(nfp_net_beat_timer, (void *)multi_pf);
3268ba461d1SPeng Zhang }
3278ba461d1SPeng Zhang 
3288b8f116bSChaoyong He static void
3298b8f116bSChaoyong He nfp_net_uninit(struct rte_eth_dev *eth_dev)
3308b8f116bSChaoyong He {
3318b8f116bSChaoyong He 	struct nfp_net_hw *net_hw;
3328b8f116bSChaoyong He 
3338b8f116bSChaoyong He 	net_hw = eth_dev->data->dev_private;
3348153bc6fSChaoyong He 
3358153bc6fSChaoyong He 	if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0)
3368153bc6fSChaoyong He 		nfp_net_flow_priv_uninit(net_hw->pf_dev, net_hw->idx);
3378153bc6fSChaoyong He 
3388b8f116bSChaoyong He 	rte_free(net_hw->eth_xstats_base);
3398b8f116bSChaoyong He 	nfp_ipsec_uninit(eth_dev);
3408b8f116bSChaoyong He 	if (net_hw->mac_stats_area != NULL)
3418b8f116bSChaoyong He 		nfp_cpp_area_release_free(net_hw->mac_stats_area);
3428b8f116bSChaoyong He }
3438b8f116bSChaoyong He 
34466d5f53dSChaoyong He static void
34566d5f53dSChaoyong He nfp_cleanup_port_app_fw_nic(struct nfp_pf_dev *pf_dev,
34666d5f53dSChaoyong He 		uint8_t id)
34766d5f53dSChaoyong He {
34866d5f53dSChaoyong He 	struct rte_eth_dev *eth_dev;
34966d5f53dSChaoyong He 	struct nfp_app_fw_nic *app_fw_nic;
35066d5f53dSChaoyong He 
35166d5f53dSChaoyong He 	app_fw_nic = pf_dev->app_fw_priv;
35266d5f53dSChaoyong He 	if (app_fw_nic->ports[id] != NULL) {
35366d5f53dSChaoyong He 		eth_dev = app_fw_nic->ports[id]->eth_dev;
35466d5f53dSChaoyong He 		if (eth_dev != NULL)
35566d5f53dSChaoyong He 			nfp_net_uninit(eth_dev);
35666d5f53dSChaoyong He 
35766d5f53dSChaoyong He 		app_fw_nic->ports[id] = NULL;
35866d5f53dSChaoyong He 	}
35966d5f53dSChaoyong He }
36066d5f53dSChaoyong He 
36166d5f53dSChaoyong He static void
36266d5f53dSChaoyong He nfp_uninit_app_fw_nic(struct nfp_pf_dev *pf_dev)
36366d5f53dSChaoyong He {
36466d5f53dSChaoyong He 	nfp_cpp_area_release_free(pf_dev->ctrl_area);
36566d5f53dSChaoyong He 	rte_free(pf_dev->app_fw_priv);
36666d5f53dSChaoyong He }
36766d5f53dSChaoyong He 
36866d5f53dSChaoyong He void
36966d5f53dSChaoyong He nfp_pf_uninit(struct nfp_pf_dev *pf_dev)
37066d5f53dSChaoyong He {
37166d5f53dSChaoyong He 	nfp_cpp_area_release_free(pf_dev->qc_area);
37266d5f53dSChaoyong He 	free(pf_dev->sym_tbl);
37366d5f53dSChaoyong He 	if (pf_dev->multi_pf.enabled) {
37466d5f53dSChaoyong He 		nfp_net_keepalive_stop(&pf_dev->multi_pf);
37566d5f53dSChaoyong He 		nfp_net_keepalive_uninit(&pf_dev->multi_pf);
37666d5f53dSChaoyong He 	}
37766d5f53dSChaoyong He 	free(pf_dev->nfp_eth_table);
37866d5f53dSChaoyong He 	free(pf_dev->hwinfo);
37966d5f53dSChaoyong He 	nfp_cpp_free(pf_dev->cpp);
38066d5f53dSChaoyong He 	rte_free(pf_dev);
38166d5f53dSChaoyong He }
38266d5f53dSChaoyong He 
38366d5f53dSChaoyong He static int
38466d5f53dSChaoyong He nfp_pf_secondary_uninit(struct nfp_pf_dev *pf_dev)
38566d5f53dSChaoyong He {
38666d5f53dSChaoyong He 	free(pf_dev->sym_tbl);
38766d5f53dSChaoyong He 	nfp_cpp_free(pf_dev->cpp);
38866d5f53dSChaoyong He 	rte_free(pf_dev);
38966d5f53dSChaoyong He 
39066d5f53dSChaoyong He 	return 0;
39166d5f53dSChaoyong He }
39266d5f53dSChaoyong He 
393646ea79cSHeinrich Kuhn /* Reset and stop device. The device can not be restarted. */
394646ea79cSHeinrich Kuhn static int
395646ea79cSHeinrich Kuhn nfp_net_close(struct rte_eth_dev *dev)
396646ea79cSHeinrich Kuhn {
3978ceb85c3SChaoyong He 	uint8_t i;
3983b00109dSPeng Zhang 	uint8_t id;
39949952141SChaoyong He 	struct nfp_net_hw *hw;
40049952141SChaoyong He 	struct nfp_pf_dev *pf_dev;
40149952141SChaoyong He 	struct rte_pci_device *pci_dev;
40249952141SChaoyong He 	struct nfp_app_fw_nic *app_fw_nic;
403646ea79cSHeinrich Kuhn 
40466d5f53dSChaoyong He 	/*
40566d5f53dSChaoyong He 	 * In secondary process, a released eth device can be found by its name
40666d5f53dSChaoyong He 	 * in shared memory.
40766d5f53dSChaoyong He 	 * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the
40866d5f53dSChaoyong He 	 * eth device has been released.
40966d5f53dSChaoyong He 	 */
41066d5f53dSChaoyong He 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
41166d5f53dSChaoyong He 		if (dev->state == RTE_ETH_DEV_UNUSED)
412646ea79cSHeinrich Kuhn 			return 0;
413646ea79cSHeinrich Kuhn 
41466d5f53dSChaoyong He 		nfp_pf_secondary_uninit(dev->process_private);
41566d5f53dSChaoyong He 		return 0;
41666d5f53dSChaoyong He 	}
41766d5f53dSChaoyong He 
4189d723baaSChaoyong He 	hw = dev->data->dev_private;
41965f6915dSChaoyong He 	pf_dev = hw->pf_dev;
420646ea79cSHeinrich Kuhn 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
421968ec1c3SChaoyong He 	app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
422646ea79cSHeinrich Kuhn 
423646ea79cSHeinrich Kuhn 	/*
424646ea79cSHeinrich Kuhn 	 * We assume that the DPDK application is stopping all the
425646ea79cSHeinrich Kuhn 	 * threads/queues before calling the device close function.
426646ea79cSHeinrich Kuhn 	 */
427646ea79cSHeinrich Kuhn 	nfp_net_disable_queues(dev);
428646ea79cSHeinrich Kuhn 
429646ea79cSHeinrich Kuhn 	/* Clear queues */
4301c8d02bbSJin Liu 	nfp_net_close_tx_queue(dev);
4311c8d02bbSJin Liu 	nfp_net_close_rx_queue(dev);
432646ea79cSHeinrich Kuhn 
433851f03e1SHeinrich Kuhn 	/* Cancel possible impending LSC work here before releasing the port */
434f4d24fe9SChaoyong He 	rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler, (void *)dev);
435851f03e1SHeinrich Kuhn 
436646ea79cSHeinrich Kuhn 	/* Only free PF resources after all physical ports have been closed */
437646ea79cSHeinrich Kuhn 	/* Mark this port as unused and free device priv resources */
438f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_LSC, 0xff);
43966d5f53dSChaoyong He 
44066d5f53dSChaoyong He 	if (pf_dev->app_fw_id != NFP_APP_FW_CORE_NIC)
44166d5f53dSChaoyong He 		return -EINVAL;
44266d5f53dSChaoyong He 
44366d5f53dSChaoyong He 	nfp_cleanup_port_app_fw_nic(pf_dev, hw->idx);
444646ea79cSHeinrich Kuhn 
445968ec1c3SChaoyong He 	for (i = 0; i < app_fw_nic->total_phyports; i++) {
4463b00109dSPeng Zhang 		id = nfp_function_id_get(pf_dev, i);
4473b00109dSPeng Zhang 
448646ea79cSHeinrich Kuhn 		/* Check to see if ports are still in use */
4493b00109dSPeng Zhang 		if (app_fw_nic->ports[id] != NULL)
450646ea79cSHeinrich Kuhn 			return 0;
451646ea79cSHeinrich Kuhn 	}
452646ea79cSHeinrich Kuhn 
45366d5f53dSChaoyong He 	/* Enable in nfp_net_start() */
454d61138d4SHarman Kalra 	rte_intr_disable(pci_dev->intr_handle);
455646ea79cSHeinrich Kuhn 
45666d5f53dSChaoyong He 	/* Register in nfp_net_init() */
457d61138d4SHarman Kalra 	rte_intr_callback_unregister(pci_dev->intr_handle,
458a6189a67SJin Liu 			nfp_net_dev_interrupt_handler, (void *)dev);
459646ea79cSHeinrich Kuhn 
46066d5f53dSChaoyong He 	nfp_uninit_app_fw_nic(pf_dev);
46166d5f53dSChaoyong He 	nfp_pf_uninit(pf_dev);
46266d5f53dSChaoyong He 
463646ea79cSHeinrich Kuhn 	return 0;
464646ea79cSHeinrich Kuhn }
465646ea79cSHeinrich Kuhn 
466c55abf61SChaoyong He static int
467c55abf61SChaoyong He nfp_net_find_vxlan_idx(struct nfp_net_hw *hw,
468c55abf61SChaoyong He 		uint16_t port,
469c55abf61SChaoyong He 		uint32_t *idx)
470c55abf61SChaoyong He {
471c55abf61SChaoyong He 	uint32_t i;
472c55abf61SChaoyong He 	int free_idx = -1;
473c55abf61SChaoyong He 
474c55abf61SChaoyong He 	for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i++) {
475c55abf61SChaoyong He 		if (hw->vxlan_ports[i] == port) {
476c55abf61SChaoyong He 			free_idx = i;
477c55abf61SChaoyong He 			break;
478c55abf61SChaoyong He 		}
479c55abf61SChaoyong He 
480c55abf61SChaoyong He 		if (hw->vxlan_usecnt[i] == 0) {
481c55abf61SChaoyong He 			free_idx = i;
482c55abf61SChaoyong He 			break;
483c55abf61SChaoyong He 		}
484c55abf61SChaoyong He 	}
485c55abf61SChaoyong He 
486c55abf61SChaoyong He 	if (free_idx == -1)
487c55abf61SChaoyong He 		return -EINVAL;
488c55abf61SChaoyong He 
489c55abf61SChaoyong He 	*idx = free_idx;
490c55abf61SChaoyong He 
491c55abf61SChaoyong He 	return 0;
492c55abf61SChaoyong He }
493c55abf61SChaoyong He 
494c55abf61SChaoyong He static int
495c55abf61SChaoyong He nfp_udp_tunnel_port_add(struct rte_eth_dev *dev,
496c55abf61SChaoyong He 		struct rte_eth_udp_tunnel *tunnel_udp)
497c55abf61SChaoyong He {
498c55abf61SChaoyong He 	int ret;
499c55abf61SChaoyong He 	uint32_t idx;
500c55abf61SChaoyong He 	uint16_t vxlan_port;
501c55abf61SChaoyong He 	struct nfp_net_hw *hw;
502c55abf61SChaoyong He 	enum rte_eth_tunnel_type tnl_type;
503c55abf61SChaoyong He 
5049d723baaSChaoyong He 	hw = dev->data->dev_private;
505c55abf61SChaoyong He 	vxlan_port = tunnel_udp->udp_port;
506c55abf61SChaoyong He 	tnl_type   = tunnel_udp->prot_type;
507c55abf61SChaoyong He 
508c55abf61SChaoyong He 	if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) {
509c55abf61SChaoyong He 		PMD_DRV_LOG(ERR, "Not VXLAN tunnel");
510c55abf61SChaoyong He 		return -ENOTSUP;
511c55abf61SChaoyong He 	}
512c55abf61SChaoyong He 
513c55abf61SChaoyong He 	ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx);
514c55abf61SChaoyong He 	if (ret != 0) {
515c55abf61SChaoyong He 		PMD_DRV_LOG(ERR, "Failed find valid vxlan idx");
516c55abf61SChaoyong He 		return -EINVAL;
517c55abf61SChaoyong He 	}
518c55abf61SChaoyong He 
519c55abf61SChaoyong He 	if (hw->vxlan_usecnt[idx] == 0) {
520c55abf61SChaoyong He 		ret = nfp_net_set_vxlan_port(hw, idx, vxlan_port);
521c55abf61SChaoyong He 		if (ret != 0) {
522c55abf61SChaoyong He 			PMD_DRV_LOG(ERR, "Failed set vxlan port");
523c55abf61SChaoyong He 			return -EINVAL;
524c55abf61SChaoyong He 		}
525c55abf61SChaoyong He 	}
526c55abf61SChaoyong He 
527c55abf61SChaoyong He 	hw->vxlan_usecnt[idx]++;
528c55abf61SChaoyong He 
529c55abf61SChaoyong He 	return 0;
530c55abf61SChaoyong He }
531c55abf61SChaoyong He 
532c55abf61SChaoyong He static int
533c55abf61SChaoyong He nfp_udp_tunnel_port_del(struct rte_eth_dev *dev,
534c55abf61SChaoyong He 		struct rte_eth_udp_tunnel *tunnel_udp)
535c55abf61SChaoyong He {
536c55abf61SChaoyong He 	int ret;
537c55abf61SChaoyong He 	uint32_t idx;
538c55abf61SChaoyong He 	uint16_t vxlan_port;
539c55abf61SChaoyong He 	struct nfp_net_hw *hw;
540c55abf61SChaoyong He 	enum rte_eth_tunnel_type tnl_type;
541c55abf61SChaoyong He 
5429d723baaSChaoyong He 	hw = dev->data->dev_private;
543c55abf61SChaoyong He 	vxlan_port = tunnel_udp->udp_port;
544c55abf61SChaoyong He 	tnl_type   = tunnel_udp->prot_type;
545c55abf61SChaoyong He 
546c55abf61SChaoyong He 	if (tnl_type != RTE_ETH_TUNNEL_TYPE_VXLAN) {
547c55abf61SChaoyong He 		PMD_DRV_LOG(ERR, "Not VXLAN tunnel");
548c55abf61SChaoyong He 		return -ENOTSUP;
549c55abf61SChaoyong He 	}
550c55abf61SChaoyong He 
551c55abf61SChaoyong He 	ret = nfp_net_find_vxlan_idx(hw, vxlan_port, &idx);
552c55abf61SChaoyong He 	if (ret != 0 || hw->vxlan_usecnt[idx] == 0) {
553c55abf61SChaoyong He 		PMD_DRV_LOG(ERR, "Failed find valid vxlan idx");
554c55abf61SChaoyong He 		return -EINVAL;
555c55abf61SChaoyong He 	}
556c55abf61SChaoyong He 
557c55abf61SChaoyong He 	hw->vxlan_usecnt[idx]--;
558c55abf61SChaoyong He 
559c55abf61SChaoyong He 	if (hw->vxlan_usecnt[idx] == 0) {
560c55abf61SChaoyong He 		ret = nfp_net_set_vxlan_port(hw, idx, 0);
561c55abf61SChaoyong He 		if (ret != 0) {
562c55abf61SChaoyong He 			PMD_DRV_LOG(ERR, "Failed set vxlan port");
563c55abf61SChaoyong He 			return -EINVAL;
564c55abf61SChaoyong He 		}
565c55abf61SChaoyong He 	}
566c55abf61SChaoyong He 
567c55abf61SChaoyong He 	return 0;
568c55abf61SChaoyong He }
569c55abf61SChaoyong He 
570646ea79cSHeinrich Kuhn /* Initialise and register driver with DPDK Application */
5718d961320SJin Liu static const struct eth_dev_ops nfp_net_eth_dev_ops = {
572646ea79cSHeinrich Kuhn 	.dev_configure          = nfp_net_configure,
573646ea79cSHeinrich Kuhn 	.dev_start              = nfp_net_start,
574646ea79cSHeinrich Kuhn 	.dev_stop               = nfp_net_stop,
575646ea79cSHeinrich Kuhn 	.dev_set_link_up        = nfp_net_set_link_up,
576646ea79cSHeinrich Kuhn 	.dev_set_link_down      = nfp_net_set_link_down,
577646ea79cSHeinrich Kuhn 	.dev_close              = nfp_net_close,
578646ea79cSHeinrich Kuhn 	.promiscuous_enable     = nfp_net_promisc_enable,
579646ea79cSHeinrich Kuhn 	.promiscuous_disable    = nfp_net_promisc_disable,
5804a86c36bSQin Ke 	.allmulticast_enable    = nfp_net_allmulticast_enable,
5814a86c36bSQin Ke 	.allmulticast_disable   = nfp_net_allmulticast_disable,
582646ea79cSHeinrich Kuhn 	.link_update            = nfp_net_link_update,
583646ea79cSHeinrich Kuhn 	.stats_get              = nfp_net_stats_get,
584646ea79cSHeinrich Kuhn 	.stats_reset            = nfp_net_stats_reset,
585f26e8239SJames Hershaw 	.xstats_get             = nfp_net_xstats_get,
586f26e8239SJames Hershaw 	.xstats_reset           = nfp_net_xstats_reset,
587f26e8239SJames Hershaw 	.xstats_get_names       = nfp_net_xstats_get_names,
588f26e8239SJames Hershaw 	.xstats_get_by_id       = nfp_net_xstats_get_by_id,
589f26e8239SJames Hershaw 	.xstats_get_names_by_id = nfp_net_xstats_get_names_by_id,
590646ea79cSHeinrich Kuhn 	.dev_infos_get          = nfp_net_infos_get,
591646ea79cSHeinrich Kuhn 	.dev_supported_ptypes_get = nfp_net_supported_ptypes_get,
592646ea79cSHeinrich Kuhn 	.mtu_set                = nfp_net_dev_mtu_set,
5930a94d6bcSJin Liu 	.mac_addr_set           = nfp_net_set_mac_addr,
594646ea79cSHeinrich Kuhn 	.vlan_offload_set       = nfp_net_vlan_offload_set,
595646ea79cSHeinrich Kuhn 	.reta_update            = nfp_net_reta_update,
596646ea79cSHeinrich Kuhn 	.reta_query             = nfp_net_reta_query,
597646ea79cSHeinrich Kuhn 	.rss_hash_update        = nfp_net_rss_hash_update,
598646ea79cSHeinrich Kuhn 	.rss_hash_conf_get      = nfp_net_rss_hash_conf_get,
599646ea79cSHeinrich Kuhn 	.rx_queue_setup         = nfp_net_rx_queue_setup,
600646ea79cSHeinrich Kuhn 	.rx_queue_release       = nfp_net_rx_queue_release,
6018d961320SJin Liu 	.tx_queue_setup         = nfp_net_tx_queue_setup,
60252ddc4c2SJin Liu 	.tx_queue_release       = nfp_net_tx_queue_release,
60352ddc4c2SJin Liu 	.rx_queue_intr_enable   = nfp_rx_queue_intr_enable,
60452ddc4c2SJin Liu 	.rx_queue_intr_disable  = nfp_rx_queue_intr_disable,
605c55abf61SChaoyong He 	.udp_tunnel_port_add    = nfp_udp_tunnel_port_add,
606c55abf61SChaoyong He 	.udp_tunnel_port_del    = nfp_udp_tunnel_port_del,
607128c8ad9SChaoyong He 	.fw_version_get         = nfp_net_firmware_version_get,
60851d15e82SZerun Fu 	.flow_ctrl_get          = nfp_net_flow_ctrl_get,
60968aa3537SZerun Fu 	.flow_ctrl_set          = nfp_net_flow_ctrl_set,
6100b9079d2SChaoyong He 	.flow_ops_get           = nfp_net_flow_ops_get,
61152ddc4c2SJin Liu };
61252ddc4c2SJin Liu 
613ee8ca64eSChaoyong He static inline void
614ee8ca64eSChaoyong He nfp_net_ethdev_ops_mount(struct nfp_net_hw *hw,
615ee8ca64eSChaoyong He 		struct rte_eth_dev *eth_dev)
616266470b2SJin Liu {
617ee8ca64eSChaoyong He 	if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
618ee8ca64eSChaoyong He 		eth_dev->tx_pkt_burst = nfp_net_nfd3_xmit_pkts;
619ee8ca64eSChaoyong He 	else
620ee8ca64eSChaoyong He 		eth_dev->tx_pkt_burst = nfp_net_nfdk_xmit_pkts;
621266470b2SJin Liu 
6228d961320SJin Liu 	eth_dev->dev_ops = &nfp_net_eth_dev_ops;
623266470b2SJin Liu 	eth_dev->rx_queue_count = nfp_net_rx_queue_count;
624266470b2SJin Liu 	eth_dev->rx_pkt_burst = &nfp_net_recv_pkts;
625266470b2SJin Liu }
626266470b2SJin Liu 
627646ea79cSHeinrich Kuhn static int
628646ea79cSHeinrich Kuhn nfp_net_init(struct rte_eth_dev *eth_dev)
629646ea79cSHeinrich Kuhn {
63049952141SChaoyong He 	int err;
63149952141SChaoyong He 	uint16_t port;
6320314a8ffSChaoyong He 	uint64_t rx_base;
6330314a8ffSChaoyong He 	uint64_t tx_base;
6344a9bb682SChaoyong He 	struct nfp_hw *hw;
6354a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
63649952141SChaoyong He 	struct nfp_pf_dev *pf_dev;
63749952141SChaoyong He 	struct rte_pci_device *pci_dev;
63849952141SChaoyong He 	struct nfp_app_fw_nic *app_fw_nic;
639646ea79cSHeinrich Kuhn 
640646ea79cSHeinrich Kuhn 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
64165f6915dSChaoyong He 	net_hw = eth_dev->data->dev_private;
642646ea79cSHeinrich Kuhn 
643646ea79cSHeinrich Kuhn 	/* Use backpointer here to the PF of this eth_dev */
64465f6915dSChaoyong He 	pf_dev = net_hw->pf_dev;
645646ea79cSHeinrich Kuhn 
646968ec1c3SChaoyong He 	/* Use backpointer to the CoreNIC app struct */
647968ec1c3SChaoyong He 	app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
648968ec1c3SChaoyong He 
649646ea79cSHeinrich Kuhn 	port = ((struct nfp_net_hw *)eth_dev->data->dev_private)->idx;
6508ceb85c3SChaoyong He 	if (port > 7) {
651646ea79cSHeinrich Kuhn 		PMD_DRV_LOG(ERR, "Port value is wrong");
652646ea79cSHeinrich Kuhn 		return -ENODEV;
653646ea79cSHeinrich Kuhn 	}
654646ea79cSHeinrich Kuhn 
6554a9bb682SChaoyong He 	hw = &net_hw->super;
656646ea79cSHeinrich Kuhn 
657030b2b19SChaoyong He 	PMD_INIT_LOG(DEBUG, "Working with physical port number: %hu, "
6584a9bb682SChaoyong He 			"NFP internal port number: %d", port, net_hw->nfp_idx);
659646ea79cSHeinrich Kuhn 
660646ea79cSHeinrich Kuhn 	rte_eth_copy_pci_info(eth_dev, pci_dev);
661646ea79cSHeinrich Kuhn 
6628ad2cc8fSPeng Zhang 	if (port == 0 || pf_dev->multi_pf.enabled) {
663f26e8239SJames Hershaw 		uint32_t min_size;
664f26e8239SJames Hershaw 
6654a9bb682SChaoyong He 		hw->ctrl_bar = pf_dev->ctrl_bar;
6664a9bb682SChaoyong He 		min_size = NFP_MAC_STATS_SIZE * net_hw->pf_dev->nfp_eth_table->max_index;
6674a9bb682SChaoyong He 		net_hw->mac_stats_bar = nfp_rtsym_map(net_hw->pf_dev->sym_tbl, "_mac_stats",
6684a9bb682SChaoyong He 				min_size, &net_hw->mac_stats_area);
6694a9bb682SChaoyong He 		if (net_hw->mac_stats_bar == NULL) {
670f26e8239SJames Hershaw 			PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for _mac_stats_bar");
671f26e8239SJames Hershaw 			return -EIO;
672f26e8239SJames Hershaw 		}
673b0c496abSChaoyong He 
6744a9bb682SChaoyong He 		net_hw->mac_stats = net_hw->mac_stats_bar;
675646ea79cSHeinrich Kuhn 	} else {
676a6189a67SJin Liu 		/* Use port offset in pf ctrl_bar for this ports control bar */
6774a9bb682SChaoyong He 		hw->ctrl_bar = pf_dev->ctrl_bar + (port * NFP_NET_CFG_BAR_SZ);
6784a9bb682SChaoyong He 		net_hw->mac_stats = app_fw_nic->ports[0]->mac_stats_bar +
6794a9bb682SChaoyong He 				(net_hw->nfp_idx * NFP_MAC_STATS_SIZE);
680646ea79cSHeinrich Kuhn 	}
681646ea79cSHeinrich Kuhn 
6824a9bb682SChaoyong He 	PMD_INIT_LOG(DEBUG, "ctrl bar: %p", hw->ctrl_bar);
6834a9bb682SChaoyong He 	PMD_INIT_LOG(DEBUG, "MAC stats: %p", net_hw->mac_stats);
684646ea79cSHeinrich Kuhn 
6854a9bb682SChaoyong He 	err = nfp_net_common_init(pci_dev, net_hw);
686cd4397ebSPeng Zhang 	if (err != 0)
68736994566SChaoyong He 		goto free_area;
688fd392f84SPeng Zhang 
689eecdfcc1SShihong Wang 	err = nfp_net_tlv_caps_parse(eth_dev);
690eecdfcc1SShihong Wang 	if (err != 0) {
691eecdfcc1SShihong Wang 		PMD_INIT_LOG(ERR, "Failed to parser TLV caps");
692eecdfcc1SShihong Wang 		return err;
69336994566SChaoyong He 		goto free_area;
694eecdfcc1SShihong Wang 	}
695eecdfcc1SShihong Wang 
69654713740SChang Miao 	err = nfp_ipsec_init(eth_dev);
69754713740SChang Miao 	if (err != 0) {
69854713740SChang Miao 		PMD_INIT_LOG(ERR, "Failed to init IPsec module");
69936994566SChaoyong He 		goto free_area;
70054713740SChang Miao 	}
70154713740SChang Miao 
7024a9bb682SChaoyong He 	nfp_net_ethdev_ops_mount(net_hw, eth_dev);
703266470b2SJin Liu 
7044a9bb682SChaoyong He 	net_hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) *
705f26e8239SJames Hershaw 			nfp_net_xstats_size(eth_dev), 0);
7064a9bb682SChaoyong He 	if (net_hw->eth_xstats_base == NULL) {
707f26e8239SJames Hershaw 		PMD_INIT_LOG(ERR, "no memory for xstats base values on device %s!",
708f26e8239SJames Hershaw 				pci_dev->device.name);
70936994566SChaoyong He 		err = -ENOMEM;
71036994566SChaoyong He 		goto ipsec_exit;
711f26e8239SJames Hershaw 	}
712f26e8239SJames Hershaw 
713646ea79cSHeinrich Kuhn 	/* Work out where in the BAR the queues start. */
7144a9bb682SChaoyong He 	tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
7154a9bb682SChaoyong He 	rx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ);
716646ea79cSHeinrich Kuhn 
7174a9bb682SChaoyong He 	net_hw->tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;
7184a9bb682SChaoyong He 	net_hw->rx_bar = pf_dev->qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ;
7194a9bb682SChaoyong He 	eth_dev->data->dev_private = net_hw;
720646ea79cSHeinrich Kuhn 
721646ea79cSHeinrich Kuhn 	PMD_INIT_LOG(DEBUG, "ctrl_bar: %p, tx_bar: %p, rx_bar: %p",
7224a9bb682SChaoyong He 			hw->ctrl_bar, net_hw->tx_bar, net_hw->rx_bar);
723646ea79cSHeinrich Kuhn 
7244a9bb682SChaoyong He 	nfp_net_cfg_queue_setup(net_hw);
7254a9bb682SChaoyong He 	net_hw->mtu = RTE_ETHER_MTU;
726646ea79cSHeinrich Kuhn 
727646ea79cSHeinrich Kuhn 	/* VLAN insertion is incompatible with LSOv2 */
7284a9bb682SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_LSO2) != 0)
7294a9bb682SChaoyong He 		hw->cap &= ~NFP_NET_CFG_CTRL_TXVLAN;
730646ea79cSHeinrich Kuhn 
7314a9bb682SChaoyong He 	nfp_net_log_device_information(net_hw);
732646ea79cSHeinrich Kuhn 
733646ea79cSHeinrich Kuhn 	/* Initializing spinlock for reconfigs */
7344a9bb682SChaoyong He 	rte_spinlock_init(&hw->reconfig_lock);
735646ea79cSHeinrich Kuhn 
736646ea79cSHeinrich Kuhn 	/* Allocating memory for mac addr */
737f4d24fe9SChaoyong He 	eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", RTE_ETHER_ADDR_LEN, 0);
738646ea79cSHeinrich Kuhn 	if (eth_dev->data->mac_addrs == NULL) {
739646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "Failed to space for MAC address");
74036994566SChaoyong He 		err = -ENOMEM;
74136994566SChaoyong He 		goto xstats_free;
742646ea79cSHeinrich Kuhn 	}
743646ea79cSHeinrich Kuhn 
744968ec1c3SChaoyong He 	nfp_net_pf_read_mac(app_fw_nic, port);
745503ac807SChaoyong He 	nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]);
746646ea79cSHeinrich Kuhn 
7474a9bb682SChaoyong He 	if (rte_is_valid_assigned_ether_addr(&hw->mac_addr) == 0) {
748a6189a67SJin Liu 		PMD_INIT_LOG(INFO, "Using random mac address for port %d", port);
749646ea79cSHeinrich Kuhn 		/* Using random mac addresses for VFs */
7504a9bb682SChaoyong He 		rte_eth_random_addr(&hw->mac_addr.addr_bytes[0]);
751503ac807SChaoyong He 		nfp_write_mac(hw, &hw->mac_addr.addr_bytes[0]);
752646ea79cSHeinrich Kuhn 	}
753646ea79cSHeinrich Kuhn 
754646ea79cSHeinrich Kuhn 	/* Copying mac address to DPDK eth_dev struct */
7554a9bb682SChaoyong He 	rte_ether_addr_copy(&hw->mac_addr, eth_dev->data->mac_addrs);
756646ea79cSHeinrich Kuhn 
7574a9bb682SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0)
758646ea79cSHeinrich Kuhn 		eth_dev->data->dev_flags |= RTE_ETH_DEV_NOLIVE_MAC_ADDR;
759646ea79cSHeinrich Kuhn 
760646ea79cSHeinrich Kuhn 	eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
761646ea79cSHeinrich Kuhn 
762030b2b19SChaoyong He 	PMD_INIT_LOG(INFO, "port %d VendorID=%#x DeviceID=%#x "
763c2c4f87bSAman Deep Singh 			"mac=" RTE_ETHER_ADDR_PRT_FMT,
764646ea79cSHeinrich Kuhn 			eth_dev->data->port_id, pci_dev->id.vendor_id,
765646ea79cSHeinrich Kuhn 			pci_dev->id.device_id,
7664a9bb682SChaoyong He 			RTE_ETHER_ADDR_BYTES(&hw->mac_addr));
767646ea79cSHeinrich Kuhn 
768646ea79cSHeinrich Kuhn 	/* Registering LSC interrupt handler */
769d61138d4SHarman Kalra 	rte_intr_callback_register(pci_dev->intr_handle,
770a6189a67SJin Liu 			nfp_net_dev_interrupt_handler, (void *)eth_dev);
771646ea79cSHeinrich Kuhn 	/* Telling the firmware about the LSC interrupt entry */
7724a9bb682SChaoyong He 	nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
77394d0631aSPeng Zhang 	/* Unmask the LSC interrupt */
77494d0631aSPeng Zhang 	nfp_net_irq_unmask(eth_dev);
775646ea79cSHeinrich Kuhn 	/* Recording current stats counters values */
776646ea79cSHeinrich Kuhn 	nfp_net_stats_reset(eth_dev);
777646ea79cSHeinrich Kuhn 
7788153bc6fSChaoyong He 	if ((hw->cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) {
7798153bc6fSChaoyong He 		err = nfp_net_flow_priv_init(pf_dev, port);
7808153bc6fSChaoyong He 		if (err != 0) {
7818153bc6fSChaoyong He 			PMD_INIT_LOG(ERR, "Init net flow priv failed");
7828153bc6fSChaoyong He 			goto xstats_free;
7838153bc6fSChaoyong He 		}
7848153bc6fSChaoyong He 	}
7858153bc6fSChaoyong He 
786646ea79cSHeinrich Kuhn 	return 0;
78736994566SChaoyong He 
78836994566SChaoyong He xstats_free:
78936994566SChaoyong He 	rte_free(net_hw->eth_xstats_base);
79036994566SChaoyong He ipsec_exit:
79136994566SChaoyong He 	nfp_ipsec_uninit(eth_dev);
79236994566SChaoyong He free_area:
79336994566SChaoyong He 	if (net_hw->mac_stats_area != NULL)
79436994566SChaoyong He 		nfp_cpp_area_release_free(net_hw->mac_stats_area);
79536994566SChaoyong He 
79636994566SChaoyong He 	return err;
797646ea79cSHeinrich Kuhn }
798646ea79cSHeinrich Kuhn 
799646ea79cSHeinrich Kuhn #define DEFAULT_FW_PATH       "/lib/firmware/netronome"
800646ea79cSHeinrich Kuhn 
801646ea79cSHeinrich Kuhn static int
802f4d24fe9SChaoyong He nfp_fw_upload(struct rte_pci_device *dev,
803f4d24fe9SChaoyong He 		struct nfp_nsp *nsp,
804f4d24fe9SChaoyong He 		char *card)
805646ea79cSHeinrich Kuhn {
806646ea79cSHeinrich Kuhn 	void *fw_buf;
807646ea79cSHeinrich Kuhn 	size_t fsize;
80849952141SChaoyong He 	char serial[40];
80949952141SChaoyong He 	char fw_name[125];
810ff627b74SChaoyong He 	uint16_t interface;
811ff627b74SChaoyong He 	uint32_t cpp_serial_len;
812ff627b74SChaoyong He 	const uint8_t *cpp_serial;
81349952141SChaoyong He 	struct nfp_cpp *cpp = nfp_nsp_cpp(nsp);
814ff627b74SChaoyong He 
815ff627b74SChaoyong He 	cpp_serial_len = nfp_cpp_serial(cpp, &cpp_serial);
816ff627b74SChaoyong He 	if (cpp_serial_len != NFP_SERIAL_LEN)
817ff627b74SChaoyong He 		return -ERANGE;
818ff627b74SChaoyong He 
819ff627b74SChaoyong He 	interface = nfp_cpp_interface(cpp);
820646ea79cSHeinrich Kuhn 
821646ea79cSHeinrich Kuhn 	/* Looking for firmware file in order of priority */
822646ea79cSHeinrich Kuhn 
823646ea79cSHeinrich Kuhn 	/* First try to find a firmware image specific for this device */
824646ea79cSHeinrich Kuhn 	snprintf(serial, sizeof(serial),
825646ea79cSHeinrich Kuhn 			"serial-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
826ff627b74SChaoyong He 			cpp_serial[0], cpp_serial[1], cpp_serial[2], cpp_serial[3],
827ff627b74SChaoyong He 			cpp_serial[4], cpp_serial[5], interface >> 8, interface & 0xff);
828f4d24fe9SChaoyong He 	snprintf(fw_name, sizeof(fw_name), "%s/%s.nffw", DEFAULT_FW_PATH, serial);
829646ea79cSHeinrich Kuhn 
830646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
831646ea79cSHeinrich Kuhn 	if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0)
832646ea79cSHeinrich Kuhn 		goto load_fw;
833b0c496abSChaoyong He 
834646ea79cSHeinrich Kuhn 	/* Then try the PCI name */
835646ea79cSHeinrich Kuhn 	snprintf(fw_name, sizeof(fw_name), "%s/pci-%s.nffw", DEFAULT_FW_PATH,
8363ddb4cc0SPeng Zhang 			dev->name);
837646ea79cSHeinrich Kuhn 
838646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
839646ea79cSHeinrich Kuhn 	if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0)
840646ea79cSHeinrich Kuhn 		goto load_fw;
841646ea79cSHeinrich Kuhn 
842646ea79cSHeinrich Kuhn 	/* Finally try the card type and media */
843646ea79cSHeinrich Kuhn 	snprintf(fw_name, sizeof(fw_name), "%s/%s", DEFAULT_FW_PATH, card);
844646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
845c01e5c0cSChaoyong He 	if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0)
846c01e5c0cSChaoyong He 		goto load_fw;
847c01e5c0cSChaoyong He 
848c01e5c0cSChaoyong He 	PMD_DRV_LOG(ERR, "Can't find suitable firmware.");
849646ea79cSHeinrich Kuhn 	return -ENOENT;
850646ea79cSHeinrich Kuhn 
851646ea79cSHeinrich Kuhn load_fw:
852646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu",
853646ea79cSHeinrich Kuhn 			fw_name, fsize);
854646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(INFO, "Uploading the firmware ...");
8552e634b03SPeng Zhang 	if (nfp_nsp_load_fw(nsp, fw_buf, fsize) < 0) {
8562e634b03SPeng Zhang 		free(fw_buf);
8572e634b03SPeng Zhang 		PMD_DRV_LOG(ERR, "Firmware load failed.");
8582e634b03SPeng Zhang 		return -EIO;
8592e634b03SPeng Zhang 	}
8602e634b03SPeng Zhang 
861646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(INFO, "Done");
862646ea79cSHeinrich Kuhn 
863646ea79cSHeinrich Kuhn 	free(fw_buf);
864646ea79cSHeinrich Kuhn 
865646ea79cSHeinrich Kuhn 	return 0;
866646ea79cSHeinrich Kuhn }
867646ea79cSHeinrich Kuhn 
8683b00109dSPeng Zhang static void
8693b00109dSPeng Zhang nfp_fw_unload(struct nfp_cpp *cpp)
8703b00109dSPeng Zhang {
8713b00109dSPeng Zhang 	struct nfp_nsp *nsp;
8723b00109dSPeng Zhang 
8733b00109dSPeng Zhang 	nsp = nfp_nsp_open(cpp);
8743b00109dSPeng Zhang 	if (nsp == NULL)
8753b00109dSPeng Zhang 		return;
8763b00109dSPeng Zhang 
8773b00109dSPeng Zhang 	nfp_nsp_device_soft_reset(nsp);
8783b00109dSPeng Zhang 	nfp_nsp_close(nsp);
8793b00109dSPeng Zhang }
8803b00109dSPeng Zhang 
881646ea79cSHeinrich Kuhn static int
8828ba461d1SPeng Zhang nfp_fw_reload(struct rte_pci_device *dev,
8838ba461d1SPeng Zhang 		struct nfp_nsp *nsp,
8848ba461d1SPeng Zhang 		char *card_desc)
8858ba461d1SPeng Zhang {
8868ba461d1SPeng Zhang 	int err;
8878ba461d1SPeng Zhang 
8888ba461d1SPeng Zhang 	nfp_nsp_device_soft_reset(nsp);
8898ba461d1SPeng Zhang 	err = nfp_fw_upload(dev, nsp, card_desc);
8908ba461d1SPeng Zhang 	if (err != 0)
8918ba461d1SPeng Zhang 		PMD_DRV_LOG(ERR, "NFP firmware load failed");
8928ba461d1SPeng Zhang 
8938ba461d1SPeng Zhang 	return err;
8948ba461d1SPeng Zhang }
8958ba461d1SPeng Zhang 
8968ba461d1SPeng Zhang static int
8978ba461d1SPeng Zhang nfp_fw_loaded_check_alive(struct rte_pci_device *dev,
8988ba461d1SPeng Zhang 		struct nfp_nsp *nsp,
8998ba461d1SPeng Zhang 		char *card_desc,
9008ba461d1SPeng Zhang 		const struct nfp_dev_info *dev_info,
9018ba461d1SPeng Zhang 		struct nfp_multi_pf *multi_pf)
9028ba461d1SPeng Zhang {
9038ba461d1SPeng Zhang 	int offset;
9048ba461d1SPeng Zhang 	uint32_t i;
9058ba461d1SPeng Zhang 	uint64_t beat;
9068ba461d1SPeng Zhang 	uint32_t port_num;
9078ba461d1SPeng Zhang 
9088ba461d1SPeng Zhang 	/*
9098ba461d1SPeng Zhang 	 * If the beats of any other port changed in 3s,
9108ba461d1SPeng Zhang 	 * we should not reload the firmware.
9118ba461d1SPeng Zhang 	 */
9128ba461d1SPeng Zhang 	for (port_num = 0; port_num < dev_info->pf_num_per_unit; port_num++) {
9138ba461d1SPeng Zhang 		if (port_num == multi_pf->function_id)
9148ba461d1SPeng Zhang 			continue;
9158ba461d1SPeng Zhang 
9168ba461d1SPeng Zhang 		offset = NFP_BEAT_OFFSET(port_num);
9178ba461d1SPeng Zhang 		beat = nn_readq(multi_pf->beat_addr + offset);
9188ba461d1SPeng Zhang 		for (i = 0; i < 3; i++) {
9198ba461d1SPeng Zhang 			sleep(1);
9208ba461d1SPeng Zhang 			if (nn_readq(multi_pf->beat_addr + offset) != beat)
9218ba461d1SPeng Zhang 				return 0;
9228ba461d1SPeng Zhang 		}
9238ba461d1SPeng Zhang 	}
9248ba461d1SPeng Zhang 
9258ba461d1SPeng Zhang 	return nfp_fw_reload(dev, nsp, card_desc);
9268ba461d1SPeng Zhang }
9278ba461d1SPeng Zhang 
9288ba461d1SPeng Zhang static int
9298ba461d1SPeng Zhang nfp_fw_reload_for_multipf(struct rte_pci_device *dev,
9308ba461d1SPeng Zhang 		struct nfp_nsp *nsp,
9318ba461d1SPeng Zhang 		char *card_desc,
9328ba461d1SPeng Zhang 		struct nfp_cpp *cpp,
9338ba461d1SPeng Zhang 		const struct nfp_dev_info *dev_info,
9348ba461d1SPeng Zhang 		struct nfp_multi_pf *multi_pf)
9358ba461d1SPeng Zhang {
9368ba461d1SPeng Zhang 	int err;
9378ba461d1SPeng Zhang 
9388ba461d1SPeng Zhang 	err = nfp_net_keepalive_init(cpp, multi_pf);
9398ba461d1SPeng Zhang 	if (err != 0)
9408ba461d1SPeng Zhang 		PMD_DRV_LOG(ERR, "NFP write beat failed");
9418ba461d1SPeng Zhang 
9428ba461d1SPeng Zhang 	if (nfp_nsp_fw_loaded(nsp))
9438ba461d1SPeng Zhang 		err = nfp_fw_loaded_check_alive(dev, nsp, card_desc, dev_info, multi_pf);
9448ba461d1SPeng Zhang 	else
9458ba461d1SPeng Zhang 		err = nfp_fw_reload(dev, nsp, card_desc);
9468ba461d1SPeng Zhang 	if (err != 0) {
9478ba461d1SPeng Zhang 		nfp_net_keepalive_uninit(multi_pf);
9488ba461d1SPeng Zhang 		return err;
9498ba461d1SPeng Zhang 	}
9508ba461d1SPeng Zhang 
9518ba461d1SPeng Zhang 	err = nfp_net_keepalive_start(multi_pf);
9528ba461d1SPeng Zhang 	if (err != 0) {
9538ba461d1SPeng Zhang 		nfp_net_keepalive_uninit(multi_pf);
9548ba461d1SPeng Zhang 		PMD_DRV_LOG(ERR, "NFP write beat failed");
9558ba461d1SPeng Zhang 	}
9568ba461d1SPeng Zhang 
9578ba461d1SPeng Zhang 	return err;
9588ba461d1SPeng Zhang }
9598ba461d1SPeng Zhang 
9608ba461d1SPeng Zhang static int
961a6189a67SJin Liu nfp_fw_setup(struct rte_pci_device *dev,
962a6189a67SJin Liu 		struct nfp_cpp *cpp,
963a6189a67SJin Liu 		struct nfp_eth_table *nfp_eth_table,
9648ba461d1SPeng Zhang 		struct nfp_hwinfo *hwinfo,
9658ba461d1SPeng Zhang 		const struct nfp_dev_info *dev_info,
9668ba461d1SPeng Zhang 		struct nfp_multi_pf *multi_pf)
967646ea79cSHeinrich Kuhn {
96849952141SChaoyong He 	int err;
96949952141SChaoyong He 	char card_desc[100];
970646ea79cSHeinrich Kuhn 	struct nfp_nsp *nsp;
971646ea79cSHeinrich Kuhn 	const char *nfp_fw_model;
972646ea79cSHeinrich Kuhn 
97306be30d4SPeng Zhang 	nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "nffw.partno");
97406be30d4SPeng Zhang 	if (nfp_fw_model == NULL)
975646ea79cSHeinrich Kuhn 		nfp_fw_model = nfp_hwinfo_lookup(hwinfo, "assembly.partno");
976646ea79cSHeinrich Kuhn 
977c01e5c0cSChaoyong He 	if (nfp_fw_model != NULL) {
978646ea79cSHeinrich Kuhn 		PMD_DRV_LOG(INFO, "firmware model found: %s", nfp_fw_model);
979646ea79cSHeinrich Kuhn 	} else {
980646ea79cSHeinrich Kuhn 		PMD_DRV_LOG(ERR, "firmware model NOT found");
981646ea79cSHeinrich Kuhn 		return -EIO;
982646ea79cSHeinrich Kuhn 	}
983646ea79cSHeinrich Kuhn 
984646ea79cSHeinrich Kuhn 	if (nfp_eth_table->count == 0 || nfp_eth_table->count > 8) {
985646ea79cSHeinrich Kuhn 		PMD_DRV_LOG(ERR, "NFP ethernet table reports wrong ports: %u",
986646ea79cSHeinrich Kuhn 				nfp_eth_table->count);
987646ea79cSHeinrich Kuhn 		return -EIO;
988646ea79cSHeinrich Kuhn 	}
989646ea79cSHeinrich Kuhn 
990646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(INFO, "NFP ethernet port table reports %u ports",
991646ea79cSHeinrich Kuhn 			nfp_eth_table->count);
992646ea79cSHeinrich Kuhn 
993646ea79cSHeinrich Kuhn 	PMD_DRV_LOG(INFO, "Port speed: %u", nfp_eth_table->ports[0].speed);
994646ea79cSHeinrich Kuhn 
995646ea79cSHeinrich Kuhn 	snprintf(card_desc, sizeof(card_desc), "nic_%s_%dx%d.nffw",
996646ea79cSHeinrich Kuhn 			nfp_fw_model, nfp_eth_table->count,
997646ea79cSHeinrich Kuhn 			nfp_eth_table->ports[0].speed / 1000);
998646ea79cSHeinrich Kuhn 
999646ea79cSHeinrich Kuhn 	nsp = nfp_nsp_open(cpp);
1000a6189a67SJin Liu 	if (nsp == NULL) {
1001646ea79cSHeinrich Kuhn 		PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle");
1002646ea79cSHeinrich Kuhn 		return -EIO;
1003646ea79cSHeinrich Kuhn 	}
1004646ea79cSHeinrich Kuhn 
10058ba461d1SPeng Zhang 	if (multi_pf->enabled)
10068ba461d1SPeng Zhang 		err = nfp_fw_reload_for_multipf(dev, nsp, card_desc, cpp, dev_info, multi_pf);
10078ba461d1SPeng Zhang 	else
10088ba461d1SPeng Zhang 		err = nfp_fw_reload(dev, nsp, card_desc);
1009646ea79cSHeinrich Kuhn 
1010646ea79cSHeinrich Kuhn 	nfp_nsp_close(nsp);
1011646ea79cSHeinrich Kuhn 	return err;
1012646ea79cSHeinrich Kuhn }
1013646ea79cSHeinrich Kuhn 
10148ad2cc8fSPeng Zhang static inline bool
1015a508fa23SPeng Zhang nfp_check_multi_pf_from_fw(uint32_t total_vnics)
1016a508fa23SPeng Zhang {
1017a508fa23SPeng Zhang 	if (total_vnics == 1)
1018a508fa23SPeng Zhang 		return true;
1019a508fa23SPeng Zhang 
1020a508fa23SPeng Zhang 	return false;
1021a508fa23SPeng Zhang }
1022a508fa23SPeng Zhang 
1023a508fa23SPeng Zhang static inline bool
10248ad2cc8fSPeng Zhang nfp_check_multi_pf_from_nsp(struct rte_pci_device *pci_dev,
10258ad2cc8fSPeng Zhang 		struct nfp_cpp *cpp)
10268ad2cc8fSPeng Zhang {
10278ad2cc8fSPeng Zhang 	bool flag;
10288ad2cc8fSPeng Zhang 	struct nfp_nsp *nsp;
10298ad2cc8fSPeng Zhang 
10308ad2cc8fSPeng Zhang 	nsp = nfp_nsp_open(cpp);
10318ad2cc8fSPeng Zhang 	if (nsp == NULL) {
10328ad2cc8fSPeng Zhang 		PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle");
10338ad2cc8fSPeng Zhang 		return false;
10348ad2cc8fSPeng Zhang 	}
10358ad2cc8fSPeng Zhang 
10368ad2cc8fSPeng Zhang 	flag = (nfp_nsp_get_abi_ver_major(nsp) > 0) &&
10378ad2cc8fSPeng Zhang 			(pci_dev->id.device_id == PCI_DEVICE_ID_NFP3800_PF_NIC);
10388ad2cc8fSPeng Zhang 
10398ad2cc8fSPeng Zhang 	nfp_nsp_close(nsp);
10408ad2cc8fSPeng Zhang 	return flag;
10418ad2cc8fSPeng Zhang }
10428ad2cc8fSPeng Zhang 
1043a6189a67SJin Liu static int
104495f978efSPeng Zhang nfp_enable_multi_pf(struct nfp_pf_dev *pf_dev)
104595f978efSPeng Zhang {
104695f978efSPeng Zhang 	int err = 0;
104795f978efSPeng Zhang 	uint64_t tx_base;
104895f978efSPeng Zhang 	uint8_t *ctrl_bar;
104995f978efSPeng Zhang 	struct nfp_hw *hw;
105095f978efSPeng Zhang 	uint32_t cap_extend;
105195f978efSPeng Zhang 	struct nfp_net_hw net_hw;
105295f978efSPeng Zhang 	struct nfp_cpp_area *area;
105395f978efSPeng Zhang 	char name[RTE_ETH_NAME_MAX_LEN];
105495f978efSPeng Zhang 
105595f978efSPeng Zhang 	memset(&net_hw, 0, sizeof(struct nfp_net_hw));
105695f978efSPeng Zhang 
105795f978efSPeng Zhang 	/* Map the symbol table */
105895f978efSPeng Zhang 	snprintf(name, sizeof(name), "_pf%u_net_bar0",
105995f978efSPeng Zhang 			pf_dev->multi_pf.function_id);
106095f978efSPeng Zhang 	ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, name, NFP_NET_CFG_BAR_SZ,
106195f978efSPeng Zhang 			&area);
106295f978efSPeng Zhang 	if (ctrl_bar == NULL) {
106395f978efSPeng Zhang 		PMD_INIT_LOG(ERR, "Failed to find data vNIC memory symbol");
106495f978efSPeng Zhang 		return -ENODEV;
106595f978efSPeng Zhang 	}
106695f978efSPeng Zhang 
106795f978efSPeng Zhang 	hw = &net_hw.super;
106895f978efSPeng Zhang 	hw->ctrl_bar = ctrl_bar;
106995f978efSPeng Zhang 
107095f978efSPeng Zhang 	cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
107195f978efSPeng Zhang 	if ((cap_extend & NFP_NET_CFG_CTRL_MULTI_PF) == 0) {
107295f978efSPeng Zhang 		PMD_INIT_LOG(ERR, "Loaded firmware doesn't support multiple PF");
107395f978efSPeng Zhang 		err = -EINVAL;
107495f978efSPeng Zhang 		goto end;
107595f978efSPeng Zhang 	}
107695f978efSPeng Zhang 
107795f978efSPeng Zhang 	tx_base = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
107895f978efSPeng Zhang 	net_hw.tx_bar = pf_dev->qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;
107995f978efSPeng Zhang 	nfp_net_cfg_queue_setup(&net_hw);
108095f978efSPeng Zhang 	rte_spinlock_init(&hw->reconfig_lock);
108195f978efSPeng Zhang 	nfp_ext_reconfig(&net_hw.super, NFP_NET_CFG_CTRL_MULTI_PF, NFP_NET_CFG_UPDATE_GEN);
108295f978efSPeng Zhang end:
108395f978efSPeng Zhang 	nfp_cpp_area_release_free(area);
108495f978efSPeng Zhang 	return err;
108595f978efSPeng Zhang }
108695f978efSPeng Zhang 
108795f978efSPeng Zhang static int
10880314a8ffSChaoyong He nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev,
10890314a8ffSChaoyong He 		const struct nfp_dev_info *dev_info)
1090646ea79cSHeinrich Kuhn {
10918ceb85c3SChaoyong He 	uint8_t i;
10923b00109dSPeng Zhang 	uint8_t id;
1093e7978635SChaoyong He 	int ret = 0;
10948ceb85c3SChaoyong He 	uint32_t total_vnics;
1095646ea79cSHeinrich Kuhn 	struct nfp_net_hw *hw;
1096968ec1c3SChaoyong He 	unsigned int numa_node;
1097646ea79cSHeinrich Kuhn 	struct rte_eth_dev *eth_dev;
1098968ec1c3SChaoyong He 	struct nfp_app_fw_nic *app_fw_nic;
1099a6189a67SJin Liu 	struct nfp_eth_table *nfp_eth_table;
11003b00109dSPeng Zhang 	char bar_name[RTE_ETH_NAME_MAX_LEN];
1101646ea79cSHeinrich Kuhn 	char port_name[RTE_ETH_NAME_MAX_LEN];
11023b00109dSPeng Zhang 	char vnic_name[RTE_ETH_NAME_MAX_LEN];
1103646ea79cSHeinrich Kuhn 
1104968ec1c3SChaoyong He 	nfp_eth_table = pf_dev->nfp_eth_table;
1105968ec1c3SChaoyong He 	PMD_INIT_LOG(INFO, "Total physical ports: %d", nfp_eth_table->count);
11063b00109dSPeng Zhang 	id = nfp_function_id_get(pf_dev, 0);
1107968ec1c3SChaoyong He 
1108968ec1c3SChaoyong He 	/* Allocate memory for the CoreNIC app */
1109968ec1c3SChaoyong He 	app_fw_nic = rte_zmalloc("nfp_app_fw_nic", sizeof(*app_fw_nic), 0);
1110968ec1c3SChaoyong He 	if (app_fw_nic == NULL)
1111968ec1c3SChaoyong He 		return -ENOMEM;
1112968ec1c3SChaoyong He 
1113968ec1c3SChaoyong He 	/* Point the app_fw_priv pointer in the PF to the coreNIC app */
1114968ec1c3SChaoyong He 	pf_dev->app_fw_priv = app_fw_nic;
1115968ec1c3SChaoyong He 
1116968ec1c3SChaoyong He 	/* Read the number of vNIC's created for the PF */
11173b00109dSPeng Zhang 	snprintf(vnic_name, sizeof(vnic_name), "nfd_cfg_pf%u_num_ports", id);
11183b00109dSPeng Zhang 	total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, vnic_name, &ret);
1119e7978635SChaoyong He 	if (ret != 0 || total_vnics == 0 || total_vnics > 8) {
11203b00109dSPeng Zhang 		PMD_INIT_LOG(ERR, "%s symbol with wrong value", vnic_name);
1121968ec1c3SChaoyong He 		ret = -ENODEV;
1122968ec1c3SChaoyong He 		goto app_cleanup;
1123968ec1c3SChaoyong He 	}
1124968ec1c3SChaoyong He 
1125a508fa23SPeng Zhang 	if (pf_dev->multi_pf.enabled) {
1126a508fa23SPeng Zhang 		if (!nfp_check_multi_pf_from_fw(total_vnics)) {
1127a508fa23SPeng Zhang 			PMD_INIT_LOG(ERR, "NSP report multipf, but FW report not multipf");
1128a508fa23SPeng Zhang 			ret = -ENODEV;
1129a508fa23SPeng Zhang 			goto app_cleanup;
1130a508fa23SPeng Zhang 		}
1131a508fa23SPeng Zhang 	} else {
1132968ec1c3SChaoyong He 		/*
1133968ec1c3SChaoyong He 		 * For coreNIC the number of vNICs exposed should be the same as the
113440688372SChaoyong He 		 * number of physical ports.
1135968ec1c3SChaoyong He 		 */
11368ceb85c3SChaoyong He 		if (total_vnics != nfp_eth_table->count) {
1137968ec1c3SChaoyong He 			PMD_INIT_LOG(ERR, "Total physical ports do not match number of vNICs");
1138968ec1c3SChaoyong He 			ret = -ENODEV;
1139968ec1c3SChaoyong He 			goto app_cleanup;
1140968ec1c3SChaoyong He 		}
1141a508fa23SPeng Zhang 	}
1142968ec1c3SChaoyong He 
1143968ec1c3SChaoyong He 	/* Populate coreNIC app properties */
1144968ec1c3SChaoyong He 	app_fw_nic->total_phyports = total_vnics;
1145968ec1c3SChaoyong He 	app_fw_nic->pf_dev = pf_dev;
1146968ec1c3SChaoyong He 	if (total_vnics > 1)
1147968ec1c3SChaoyong He 		app_fw_nic->multiport = true;
1148968ec1c3SChaoyong He 
1149968ec1c3SChaoyong He 	/* Map the symbol table */
11503b00109dSPeng Zhang 	snprintf(bar_name, sizeof(bar_name), "_pf%u_net_bar0", id);
11513b00109dSPeng Zhang 	pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, bar_name,
1152d5e9fc86SChaoyong He 			app_fw_nic->total_phyports * NFP_NET_CFG_BAR_SZ,
1153d5e9fc86SChaoyong He 			&pf_dev->ctrl_area);
1154968ec1c3SChaoyong He 	if (pf_dev->ctrl_bar == NULL) {
11553b00109dSPeng Zhang 		PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for %s", bar_name);
1156968ec1c3SChaoyong He 		ret = -EIO;
1157968ec1c3SChaoyong He 		goto app_cleanup;
1158968ec1c3SChaoyong He 	}
1159968ec1c3SChaoyong He 
1160968ec1c3SChaoyong He 	PMD_INIT_LOG(DEBUG, "ctrl bar: %p", pf_dev->ctrl_bar);
1161968ec1c3SChaoyong He 
1162968ec1c3SChaoyong He 	/* Loop through all physical ports on PF */
1163968ec1c3SChaoyong He 	numa_node = rte_socket_id();
1164968ec1c3SChaoyong He 	for (i = 0; i < app_fw_nic->total_phyports; i++) {
11653b00109dSPeng Zhang 		id = nfp_function_id_get(pf_dev, i);
11663b00109dSPeng Zhang 		snprintf(port_name, sizeof(port_name), "%s_port%u",
11673b00109dSPeng Zhang 				pf_dev->pci_dev->device.name, id);
1168646ea79cSHeinrich Kuhn 
1169646ea79cSHeinrich Kuhn 		/* Allocate a eth_dev for this phyport */
1170646ea79cSHeinrich Kuhn 		eth_dev = rte_eth_dev_allocate(port_name);
1171a6189a67SJin Liu 		if (eth_dev == NULL) {
1172646ea79cSHeinrich Kuhn 			ret = -ENODEV;
1173646ea79cSHeinrich Kuhn 			goto port_cleanup;
1174646ea79cSHeinrich Kuhn 		}
1175646ea79cSHeinrich Kuhn 
1176646ea79cSHeinrich Kuhn 		/* Allocate memory for this phyport */
1177f4d24fe9SChaoyong He 		eth_dev->data->dev_private = rte_zmalloc_socket(port_name,
1178f4d24fe9SChaoyong He 				sizeof(struct nfp_net_hw),
1179646ea79cSHeinrich Kuhn 				RTE_CACHE_LINE_SIZE, numa_node);
1180a6189a67SJin Liu 		if (eth_dev->data->dev_private == NULL) {
1181646ea79cSHeinrich Kuhn 			ret = -ENOMEM;
1182646ea79cSHeinrich Kuhn 			rte_eth_dev_release_port(eth_dev);
1183646ea79cSHeinrich Kuhn 			goto port_cleanup;
1184646ea79cSHeinrich Kuhn 		}
1185646ea79cSHeinrich Kuhn 
11869d723baaSChaoyong He 		hw = eth_dev->data->dev_private;
1187646ea79cSHeinrich Kuhn 
1188646ea79cSHeinrich Kuhn 		/* Add this device to the PF's array of physical ports */
11893b00109dSPeng Zhang 		app_fw_nic->ports[id] = hw;
1190646ea79cSHeinrich Kuhn 
11910314a8ffSChaoyong He 		hw->dev_info = dev_info;
1192646ea79cSHeinrich Kuhn 		hw->pf_dev = pf_dev;
1193646ea79cSHeinrich Kuhn 		hw->cpp = pf_dev->cpp;
1194646ea79cSHeinrich Kuhn 		hw->eth_dev = eth_dev;
11953b00109dSPeng Zhang 		hw->idx = id;
11963b00109dSPeng Zhang 		hw->nfp_idx = nfp_eth_table->ports[id].index;
1197646ea79cSHeinrich Kuhn 
1198646ea79cSHeinrich Kuhn 		eth_dev->device = &pf_dev->pci_dev->device;
1199646ea79cSHeinrich Kuhn 
120040688372SChaoyong He 		/*
120140688372SChaoyong He 		 * Ctrl/tx/rx BAR mappings and remaining init happens in
120240688372SChaoyong He 		 * @nfp_net_init()
1203646ea79cSHeinrich Kuhn 		 */
1204646ea79cSHeinrich Kuhn 		ret = nfp_net_init(eth_dev);
1205c01e5c0cSChaoyong He 		if (ret != 0) {
1206646ea79cSHeinrich Kuhn 			ret = -ENODEV;
1207646ea79cSHeinrich Kuhn 			goto port_cleanup;
1208646ea79cSHeinrich Kuhn 		}
1209646ea79cSHeinrich Kuhn 
1210646ea79cSHeinrich Kuhn 		rte_eth_dev_probing_finish(eth_dev);
1211646ea79cSHeinrich Kuhn 
1212646ea79cSHeinrich Kuhn 	} /* End loop, all ports on this PF */
1213968ec1c3SChaoyong He 
1214968ec1c3SChaoyong He 	return 0;
1215646ea79cSHeinrich Kuhn 
1216646ea79cSHeinrich Kuhn port_cleanup:
1217968ec1c3SChaoyong He 	for (i = 0; i < app_fw_nic->total_phyports; i++) {
12183b00109dSPeng Zhang 		id = nfp_function_id_get(pf_dev, i);
12198153bc6fSChaoyong He 		hw = app_fw_nic->ports[id];
12203b00109dSPeng Zhang 
12218153bc6fSChaoyong He 		if (hw != NULL && hw->eth_dev != NULL) {
12228153bc6fSChaoyong He 			nfp_net_uninit(hw->eth_dev);
12238153bc6fSChaoyong He 			rte_eth_dev_release_port(hw->eth_dev);
1224646ea79cSHeinrich Kuhn 		}
1225646ea79cSHeinrich Kuhn 	}
12268b8f116bSChaoyong He 	nfp_cpp_area_release_free(pf_dev->ctrl_area);
1227968ec1c3SChaoyong He app_cleanup:
1228968ec1c3SChaoyong He 	rte_free(app_fw_nic);
1229a6189a67SJin Liu 
1230646ea79cSHeinrich Kuhn 	return ret;
1231646ea79cSHeinrich Kuhn }
1232646ea79cSHeinrich Kuhn 
1233a6189a67SJin Liu static int
1234*c7a6970fSZerun Fu nfp_net_hwinfo_set(uint8_t function_id,
1235*c7a6970fSZerun Fu 		struct nfp_rtsym_table *sym_tbl,
1236*c7a6970fSZerun Fu 		struct nfp_cpp *cpp)
1237*c7a6970fSZerun Fu {
1238*c7a6970fSZerun Fu 	int ret = 0;
1239*c7a6970fSZerun Fu 	uint64_t app_cap;
1240*c7a6970fSZerun Fu 	uint8_t sp_indiff;
1241*c7a6970fSZerun Fu 	struct nfp_nsp *nsp;
1242*c7a6970fSZerun Fu 	char hw_info[RTE_ETH_NAME_MAX_LEN];
1243*c7a6970fSZerun Fu 	char app_cap_name[RTE_ETH_NAME_MAX_LEN];
1244*c7a6970fSZerun Fu 
1245*c7a6970fSZerun Fu 	/* Read the app capabilities of the firmware loaded */
1246*c7a6970fSZerun Fu 	snprintf(app_cap_name, sizeof(app_cap_name), "_pf%u_net_app_cap", function_id);
1247*c7a6970fSZerun Fu 	app_cap = nfp_rtsym_read_le(sym_tbl, app_cap_name, &ret);
1248*c7a6970fSZerun Fu 	if (ret != 0) {
1249*c7a6970fSZerun Fu 		PMD_INIT_LOG(ERR, "Couldn't read app_fw_cap from firmware.");
1250*c7a6970fSZerun Fu 		return ret;
1251*c7a6970fSZerun Fu 	}
1252*c7a6970fSZerun Fu 
1253*c7a6970fSZerun Fu 	/* Calculate the value of sp_indiff and write to hw_info */
1254*c7a6970fSZerun Fu 	sp_indiff = app_cap & NFP_NET_APP_CAP_SP_INDIFF;
1255*c7a6970fSZerun Fu 	snprintf(hw_info, sizeof(hw_info), "sp_indiff=%u", sp_indiff);
1256*c7a6970fSZerun Fu 
1257*c7a6970fSZerun Fu 	nsp = nfp_nsp_open(cpp);
1258*c7a6970fSZerun Fu 	if (nsp == NULL) {
1259*c7a6970fSZerun Fu 		PMD_INIT_LOG(ERR, "Couldn't get NSP.");
1260*c7a6970fSZerun Fu 		return -EIO;
1261*c7a6970fSZerun Fu 	}
1262*c7a6970fSZerun Fu 
1263*c7a6970fSZerun Fu 	ret = nfp_nsp_hwinfo_set(nsp, hw_info, sizeof(hw_info));
1264*c7a6970fSZerun Fu 	nfp_nsp_close(nsp);
1265*c7a6970fSZerun Fu 	if (ret != 0) {
1266*c7a6970fSZerun Fu 		PMD_INIT_LOG(ERR, "Failed to set parameter to hwinfo.");
1267*c7a6970fSZerun Fu 		return ret;
1268*c7a6970fSZerun Fu 	}
1269*c7a6970fSZerun Fu 
1270*c7a6970fSZerun Fu 	return 0;
1271*c7a6970fSZerun Fu }
1272*c7a6970fSZerun Fu 
1273*c7a6970fSZerun Fu static int
1274a6189a67SJin Liu nfp_pf_init(struct rte_pci_device *pci_dev)
1275646ea79cSHeinrich Kuhn {
12769e442599SShihong Wang 	uint32_t i;
12773b00109dSPeng Zhang 	uint32_t id;
1278e7978635SChaoyong He 	int ret = 0;
12795c464d6aSJin Liu 	uint64_t addr;
12803b00109dSPeng Zhang 	uint32_t index;
1281925c27ecSChaoyong He 	uint32_t cpp_id;
12823b00109dSPeng Zhang 	uint8_t function_id;
1283a6189a67SJin Liu 	struct nfp_cpp *cpp;
1284a6189a67SJin Liu 	struct nfp_pf_dev *pf_dev;
1285a6189a67SJin Liu 	struct nfp_hwinfo *hwinfo;
128649952141SChaoyong He 	enum nfp_app_fw_id app_fw_id;
1287a6189a67SJin Liu 	char name[RTE_ETH_NAME_MAX_LEN];
1288a6189a67SJin Liu 	struct nfp_rtsym_table *sym_tbl;
12893b00109dSPeng Zhang 	char app_name[RTE_ETH_NAME_MAX_LEN];
1290a6189a67SJin Liu 	struct nfp_eth_table *nfp_eth_table;
12910314a8ffSChaoyong He 	const struct nfp_dev_info *dev_info;
1292646ea79cSHeinrich Kuhn 
1293a6189a67SJin Liu 	if (pci_dev == NULL)
1294a6189a67SJin Liu 		return -ENODEV;
1295646ea79cSHeinrich Kuhn 
129684aaba5aSChaoyong He 	if (pci_dev->mem_resource[0].addr == NULL) {
129784aaba5aSChaoyong He 		PMD_INIT_LOG(ERR, "The address of BAR0 is NULL.");
129884aaba5aSChaoyong He 		return -ENODEV;
129984aaba5aSChaoyong He 	}
130084aaba5aSChaoyong He 
13010314a8ffSChaoyong He 	dev_info = nfp_dev_info_get(pci_dev->id.device_id);
13020314a8ffSChaoyong He 	if (dev_info == NULL) {
13030314a8ffSChaoyong He 		PMD_INIT_LOG(ERR, "Not supported device ID");
13040314a8ffSChaoyong He 		return -ENODEV;
13050314a8ffSChaoyong He 	}
13060314a8ffSChaoyong He 
13078ad2cc8fSPeng Zhang 	/* Allocate memory for the PF "device" */
13083b00109dSPeng Zhang 	function_id = (pci_dev->addr.function) & 0x07;
13093b00109dSPeng Zhang 	snprintf(name, sizeof(name), "nfp_pf%u", function_id);
13108ad2cc8fSPeng Zhang 	pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0);
13118ad2cc8fSPeng Zhang 	if (pf_dev == NULL) {
13128ad2cc8fSPeng Zhang 		PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device");
13138ad2cc8fSPeng Zhang 		return -ENOMEM;
13148ad2cc8fSPeng Zhang 	}
13158ad2cc8fSPeng Zhang 
1316646ea79cSHeinrich Kuhn 	/*
1317646ea79cSHeinrich Kuhn 	 * When device bound to UIO, the device could be used, by mistake,
1318646ea79cSHeinrich Kuhn 	 * by two DPDK apps, and the UIO driver does not avoid it. This
1319646ea79cSHeinrich Kuhn 	 * could lead to a serious problem when configuring the NFP CPP
1320646ea79cSHeinrich Kuhn 	 * interface. Here we avoid this telling to the CPP init code to
1321646ea79cSHeinrich Kuhn 	 * use a lock file if UIO is being used.
1322646ea79cSHeinrich Kuhn 	 */
1323646ea79cSHeinrich Kuhn 	if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO)
13241fbe51cdSChaoyong He 		cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false);
1325646ea79cSHeinrich Kuhn 	else
13261fbe51cdSChaoyong He 		cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true);
1327646ea79cSHeinrich Kuhn 
1328a6189a67SJin Liu 	if (cpp == NULL) {
1329646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
13308ad2cc8fSPeng Zhang 		ret = -EIO;
13318ad2cc8fSPeng Zhang 		goto pf_cleanup;
1332646ea79cSHeinrich Kuhn 	}
1333646ea79cSHeinrich Kuhn 
1334646ea79cSHeinrich Kuhn 	hwinfo = nfp_hwinfo_read(cpp);
1335a6189a67SJin Liu 	if (hwinfo == NULL) {
1336646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "Error reading hwinfo table");
1337646ea79cSHeinrich Kuhn 		ret = -EIO;
1338968ec1c3SChaoyong He 		goto cpp_cleanup;
1339646ea79cSHeinrich Kuhn 	}
1340646ea79cSHeinrich Kuhn 
1341968ec1c3SChaoyong He 	/* Read the number of physical ports from hardware */
1342646ea79cSHeinrich Kuhn 	nfp_eth_table = nfp_eth_read_ports(cpp);
1343a6189a67SJin Liu 	if (nfp_eth_table == NULL) {
1344646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "Error reading NFP ethernet table");
1345646ea79cSHeinrich Kuhn 		ret = -EIO;
1346646ea79cSHeinrich Kuhn 		goto hwinfo_cleanup;
1347646ea79cSHeinrich Kuhn 	}
1348646ea79cSHeinrich Kuhn 
13498ad2cc8fSPeng Zhang 	pf_dev->multi_pf.enabled = nfp_check_multi_pf_from_nsp(pci_dev, cpp);
13503b00109dSPeng Zhang 	pf_dev->multi_pf.function_id = function_id;
13518ad2cc8fSPeng Zhang 
13529e442599SShihong Wang 	/* Force the physical port down to clear the possible DMA error */
13533b00109dSPeng Zhang 	for (i = 0; i < nfp_eth_table->count; i++) {
13543b00109dSPeng Zhang 		id = nfp_function_id_get(pf_dev, i);
13553b00109dSPeng Zhang 		index = nfp_eth_table->ports[id].index;
13563b00109dSPeng Zhang 		nfp_eth_set_configured(cpp, index, 0);
13573b00109dSPeng Zhang 	}
13589e442599SShihong Wang 
13598ba461d1SPeng Zhang 	if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo,
13608ba461d1SPeng Zhang 			dev_info, &pf_dev->multi_pf) != 0) {
1361646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "Error when uploading firmware");
1362646ea79cSHeinrich Kuhn 		ret = -EIO;
1363646ea79cSHeinrich Kuhn 		goto eth_table_cleanup;
1364646ea79cSHeinrich Kuhn 	}
1365646ea79cSHeinrich Kuhn 
1366646ea79cSHeinrich Kuhn 	/* Now the symbol table should be there */
1367646ea79cSHeinrich Kuhn 	sym_tbl = nfp_rtsym_table_read(cpp);
1368a6189a67SJin Liu 	if (sym_tbl == NULL) {
1369f4d24fe9SChaoyong He 		PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table");
1370646ea79cSHeinrich Kuhn 		ret = -EIO;
13713b00109dSPeng Zhang 		goto fw_cleanup;
1372646ea79cSHeinrich Kuhn 	}
1373646ea79cSHeinrich Kuhn 
1374968ec1c3SChaoyong He 	/* Read the app ID of the firmware loaded */
13753b00109dSPeng Zhang 	snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id);
13763b00109dSPeng Zhang 	app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret);
1377e7978635SChaoyong He 	if (ret != 0) {
13783b00109dSPeng Zhang 		PMD_INIT_LOG(ERR, "Couldn't read %s from firmware", app_name);
1379646ea79cSHeinrich Kuhn 		ret = -EIO;
1380646ea79cSHeinrich Kuhn 		goto sym_tbl_cleanup;
1381646ea79cSHeinrich Kuhn 	}
1382646ea79cSHeinrich Kuhn 
1383*c7a6970fSZerun Fu 	/* Write sp_indiff to hw_info */
1384*c7a6970fSZerun Fu 	ret = nfp_net_hwinfo_set(function_id, sym_tbl, cpp);
1385*c7a6970fSZerun Fu 	if (ret != 0) {
1386*c7a6970fSZerun Fu 		PMD_INIT_LOG(ERR, "Failed to set hwinfo.");
1387*c7a6970fSZerun Fu 		ret = -EIO;
1388*c7a6970fSZerun Fu 		goto sym_tbl_cleanup;
1389*c7a6970fSZerun Fu 	}
1390*c7a6970fSZerun Fu 
1391646ea79cSHeinrich Kuhn 	/* Populate the newly created PF device */
1392968ec1c3SChaoyong He 	pf_dev->app_fw_id = app_fw_id;
1393646ea79cSHeinrich Kuhn 	pf_dev->cpp = cpp;
1394646ea79cSHeinrich Kuhn 	pf_dev->hwinfo = hwinfo;
1395646ea79cSHeinrich Kuhn 	pf_dev->sym_tbl = sym_tbl;
1396646ea79cSHeinrich Kuhn 	pf_dev->pci_dev = pci_dev;
1397968ec1c3SChaoyong He 	pf_dev->nfp_eth_table = nfp_eth_table;
1398646ea79cSHeinrich Kuhn 
139940688372SChaoyong He 	/* Configure access to tx/rx vNIC BARs */
14000314a8ffSChaoyong He 	addr = nfp_qcp_queue_offset(dev_info, 0);
1401925c27ecSChaoyong He 	cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0);
14020314a8ffSChaoyong He 
1403711e4559SChaoyong He 	pf_dev->qc_bar = nfp_cpp_map_area(pf_dev->cpp, cpp_id,
14040314a8ffSChaoyong He 			addr, dev_info->qc_area_sz, &pf_dev->qc_area);
1405711e4559SChaoyong He 	if (pf_dev->qc_bar == NULL) {
1406646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for net.qc");
1407646ea79cSHeinrich Kuhn 		ret = -EIO;
14088ad2cc8fSPeng Zhang 		goto sym_tbl_cleanup;
1409646ea79cSHeinrich Kuhn 	}
1410646ea79cSHeinrich Kuhn 
1411030b2b19SChaoyong He 	PMD_INIT_LOG(DEBUG, "qc_bar address: %p", pf_dev->qc_bar);
1412646ea79cSHeinrich Kuhn 
1413a6189a67SJin Liu 	/*
1414968ec1c3SChaoyong He 	 * PF initialization has been done at this point. Call app specific
141540688372SChaoyong He 	 * init code now.
1416646ea79cSHeinrich Kuhn 	 */
1417968ec1c3SChaoyong He 	switch (pf_dev->app_fw_id) {
1418968ec1c3SChaoyong He 	case NFP_APP_FW_CORE_NIC:
141995f978efSPeng Zhang 		if (pf_dev->multi_pf.enabled) {
142095f978efSPeng Zhang 			ret = nfp_enable_multi_pf(pf_dev);
142195f978efSPeng Zhang 			if (ret != 0)
142295f978efSPeng Zhang 				goto hwqueues_cleanup;
142395f978efSPeng Zhang 		}
142495f978efSPeng Zhang 
1425968ec1c3SChaoyong He 		PMD_INIT_LOG(INFO, "Initializing coreNIC");
14260314a8ffSChaoyong He 		ret = nfp_init_app_fw_nic(pf_dev, dev_info);
1427968ec1c3SChaoyong He 		if (ret != 0) {
1428968ec1c3SChaoyong He 			PMD_INIT_LOG(ERR, "Could not initialize coreNIC!");
1429968ec1c3SChaoyong He 			goto hwqueues_cleanup;
1430968ec1c3SChaoyong He 		}
1431968ec1c3SChaoyong He 		break;
1432b1880421SChaoyong He 	case NFP_APP_FW_FLOWER_NIC:
1433b1880421SChaoyong He 		PMD_INIT_LOG(INFO, "Initializing Flower");
14340314a8ffSChaoyong He 		ret = nfp_init_app_fw_flower(pf_dev, dev_info);
1435b1880421SChaoyong He 		if (ret != 0) {
1436b1880421SChaoyong He 			PMD_INIT_LOG(ERR, "Could not initialize Flower!");
1437b1880421SChaoyong He 			goto hwqueues_cleanup;
1438b1880421SChaoyong He 		}
1439b1880421SChaoyong He 		break;
1440968ec1c3SChaoyong He 	default:
1441968ec1c3SChaoyong He 		PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
1442968ec1c3SChaoyong He 		ret = -EINVAL;
1443646ea79cSHeinrich Kuhn 		goto hwqueues_cleanup;
1444646ea79cSHeinrich Kuhn 	}
1445646ea79cSHeinrich Kuhn 
144640688372SChaoyong He 	/* Register the CPP bridge service here for primary use */
1447bab0e6f4SChaoyong He 	ret = nfp_enable_cpp_service(pf_dev);
1448dee23e6cSChaoyong He 	if (ret != 0)
1449dee23e6cSChaoyong He 		PMD_INIT_LOG(INFO, "Enable cpp service failed.");
1450646ea79cSHeinrich Kuhn 
1451646ea79cSHeinrich Kuhn 	return 0;
1452646ea79cSHeinrich Kuhn 
1453646ea79cSHeinrich Kuhn hwqueues_cleanup:
1454528812a6SChaoyong He 	nfp_cpp_area_release_free(pf_dev->qc_area);
1455646ea79cSHeinrich Kuhn sym_tbl_cleanup:
1456646ea79cSHeinrich Kuhn 	free(sym_tbl);
14573b00109dSPeng Zhang fw_cleanup:
14583b00109dSPeng Zhang 	nfp_fw_unload(cpp);
14598ba461d1SPeng Zhang 	nfp_net_keepalive_stop(&pf_dev->multi_pf);
1460528812a6SChaoyong He 	nfp_net_keepalive_uninit(&pf_dev->multi_pf);
1461646ea79cSHeinrich Kuhn eth_table_cleanup:
1462646ea79cSHeinrich Kuhn 	free(nfp_eth_table);
1463646ea79cSHeinrich Kuhn hwinfo_cleanup:
1464646ea79cSHeinrich Kuhn 	free(hwinfo);
1465968ec1c3SChaoyong He cpp_cleanup:
1466968ec1c3SChaoyong He 	nfp_cpp_free(cpp);
14678ad2cc8fSPeng Zhang pf_cleanup:
14688ad2cc8fSPeng Zhang 	rte_free(pf_dev);
14697feb8909SChaoyong He 
1470646ea79cSHeinrich Kuhn 	return ret;
1471646ea79cSHeinrich Kuhn }
1472646ea79cSHeinrich Kuhn 
1473d5f39e07SChaoyong He static int
1474016141b1SChaoyong He nfp_secondary_init_app_fw_nic(struct nfp_pf_dev *pf_dev)
1475d5f39e07SChaoyong He {
14768ceb85c3SChaoyong He 	uint32_t i;
1477d5f39e07SChaoyong He 	int err = 0;
1478d5f39e07SChaoyong He 	int ret = 0;
14793b00109dSPeng Zhang 	uint8_t function_id;
14808ceb85c3SChaoyong He 	uint32_t total_vnics;
1481d5f39e07SChaoyong He 	struct nfp_net_hw *hw;
14823b00109dSPeng Zhang 	char pf_name[RTE_ETH_NAME_MAX_LEN];
1483d5f39e07SChaoyong He 
1484d5f39e07SChaoyong He 	/* Read the number of vNIC's created for the PF */
14853b00109dSPeng Zhang 	function_id = (pf_dev->pci_dev->addr.function) & 0x07;
14863b00109dSPeng Zhang 	snprintf(pf_name, sizeof(pf_name), "nfd_cfg_pf%u_num_ports", function_id);
14873b00109dSPeng Zhang 	total_vnics = nfp_rtsym_read_le(pf_dev->sym_tbl, pf_name, &err);
14888ceb85c3SChaoyong He 	if (err != 0 || total_vnics == 0 || total_vnics > 8) {
14893b00109dSPeng Zhang 		PMD_INIT_LOG(ERR, "%s symbol with wrong value", pf_name);
1490d5f39e07SChaoyong He 		return -ENODEV;
1491d5f39e07SChaoyong He 	}
1492d5f39e07SChaoyong He 
1493d5f39e07SChaoyong He 	for (i = 0; i < total_vnics; i++) {
14943b00109dSPeng Zhang 		uint32_t id = i;
1495d5f39e07SChaoyong He 		struct rte_eth_dev *eth_dev;
1496d5f39e07SChaoyong He 		char port_name[RTE_ETH_NAME_MAX_LEN];
14973b00109dSPeng Zhang 
14983b00109dSPeng Zhang 		if (nfp_check_multi_pf_from_fw(total_vnics))
14993b00109dSPeng Zhang 			id = function_id;
15008ceb85c3SChaoyong He 		snprintf(port_name, sizeof(port_name), "%s_port%u",
15013b00109dSPeng Zhang 				pf_dev->pci_dev->device.name, id);
1502d5f39e07SChaoyong He 
1503d5f39e07SChaoyong He 		PMD_INIT_LOG(DEBUG, "Secondary attaching to port %s", port_name);
1504d5f39e07SChaoyong He 		eth_dev = rte_eth_dev_attach_secondary(port_name);
1505d5f39e07SChaoyong He 		if (eth_dev == NULL) {
1506d5f39e07SChaoyong He 			PMD_INIT_LOG(ERR, "Secondary process attach to port %s failed", port_name);
1507d5f39e07SChaoyong He 			ret = -ENODEV;
1508d5f39e07SChaoyong He 			break;
1509d5f39e07SChaoyong He 		}
1510d5f39e07SChaoyong He 
1511acb6bebfSChaoyong He 		eth_dev->process_private = pf_dev;
15129d723baaSChaoyong He 		hw = eth_dev->data->dev_private;
1513ee8ca64eSChaoyong He 		nfp_net_ethdev_ops_mount(hw, eth_dev);
1514d5f39e07SChaoyong He 
1515d5f39e07SChaoyong He 		rte_eth_dev_probing_finish(eth_dev);
1516d5f39e07SChaoyong He 	}
1517d5f39e07SChaoyong He 
1518d5f39e07SChaoyong He 	return ret;
1519d5f39e07SChaoyong He }
1520d5f39e07SChaoyong He 
1521646ea79cSHeinrich Kuhn /*
1522646ea79cSHeinrich Kuhn  * When attaching to the NFP4000/6000 PF on a secondary process there
1523646ea79cSHeinrich Kuhn  * is no need to initialise the PF again. Only minimal work is required
152440688372SChaoyong He  * here.
1525646ea79cSHeinrich Kuhn  */
1526a6189a67SJin Liu static int
1527a6189a67SJin Liu nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
1528646ea79cSHeinrich Kuhn {
1529968ec1c3SChaoyong He 	int ret = 0;
1530a6189a67SJin Liu 	struct nfp_cpp *cpp;
15313b00109dSPeng Zhang 	uint8_t function_id;
1532016141b1SChaoyong He 	struct nfp_pf_dev *pf_dev;
1533d5f39e07SChaoyong He 	enum nfp_app_fw_id app_fw_id;
1534016141b1SChaoyong He 	char name[RTE_ETH_NAME_MAX_LEN];
1535a6189a67SJin Liu 	struct nfp_rtsym_table *sym_tbl;
15360314a8ffSChaoyong He 	const struct nfp_dev_info *dev_info;
15373b00109dSPeng Zhang 	char app_name[RTE_ETH_NAME_MAX_LEN];
1538646ea79cSHeinrich Kuhn 
1539a6189a67SJin Liu 	if (pci_dev == NULL)
1540646ea79cSHeinrich Kuhn 		return -ENODEV;
1541646ea79cSHeinrich Kuhn 
154284aaba5aSChaoyong He 	if (pci_dev->mem_resource[0].addr == NULL) {
154384aaba5aSChaoyong He 		PMD_INIT_LOG(ERR, "The address of BAR0 is NULL.");
154484aaba5aSChaoyong He 		return -ENODEV;
154584aaba5aSChaoyong He 	}
154684aaba5aSChaoyong He 
15470314a8ffSChaoyong He 	dev_info = nfp_dev_info_get(pci_dev->id.device_id);
15480314a8ffSChaoyong He 	if (dev_info == NULL) {
15490314a8ffSChaoyong He 		PMD_INIT_LOG(ERR, "Not supported device ID");
15500314a8ffSChaoyong He 		return -ENODEV;
15510314a8ffSChaoyong He 	}
15520314a8ffSChaoyong He 
1553016141b1SChaoyong He 	/* Allocate memory for the PF "device" */
1554016141b1SChaoyong He 	snprintf(name, sizeof(name), "nfp_pf%d", 0);
1555016141b1SChaoyong He 	pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0);
1556016141b1SChaoyong He 	if (pf_dev == NULL) {
1557016141b1SChaoyong He 		PMD_INIT_LOG(ERR, "Can't allocate memory for the PF device");
1558016141b1SChaoyong He 		return -ENOMEM;
1559016141b1SChaoyong He 	}
1560016141b1SChaoyong He 
1561646ea79cSHeinrich Kuhn 	/*
1562646ea79cSHeinrich Kuhn 	 * When device bound to UIO, the device could be used, by mistake,
1563646ea79cSHeinrich Kuhn 	 * by two DPDK apps, and the UIO driver does not avoid it. This
1564646ea79cSHeinrich Kuhn 	 * could lead to a serious problem when configuring the NFP CPP
1565646ea79cSHeinrich Kuhn 	 * interface. Here we avoid this telling to the CPP init code to
1566646ea79cSHeinrich Kuhn 	 * use a lock file if UIO is being used.
1567646ea79cSHeinrich Kuhn 	 */
1568646ea79cSHeinrich Kuhn 	if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO)
15691fbe51cdSChaoyong He 		cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, false);
1570646ea79cSHeinrich Kuhn 	else
15711fbe51cdSChaoyong He 		cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, dev_info, true);
1572646ea79cSHeinrich Kuhn 
1573a6189a67SJin Liu 	if (cpp == NULL) {
1574646ea79cSHeinrich Kuhn 		PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
1575016141b1SChaoyong He 		ret = -EIO;
1576016141b1SChaoyong He 		goto pf_cleanup;
1577646ea79cSHeinrich Kuhn 	}
1578646ea79cSHeinrich Kuhn 
1579646ea79cSHeinrich Kuhn 	/*
1580646ea79cSHeinrich Kuhn 	 * We don't have access to the PF created in the primary process
158140688372SChaoyong He 	 * here so we have to read the number of ports from firmware.
1582646ea79cSHeinrich Kuhn 	 */
1583646ea79cSHeinrich Kuhn 	sym_tbl = nfp_rtsym_table_read(cpp);
1584a6189a67SJin Liu 	if (sym_tbl == NULL) {
1585f4d24fe9SChaoyong He 		PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table");
1586016141b1SChaoyong He 		ret = -EIO;
1587016141b1SChaoyong He 		goto pf_cleanup;
1588646ea79cSHeinrich Kuhn 	}
1589646ea79cSHeinrich Kuhn 
1590d5f39e07SChaoyong He 	/* Read the app ID of the firmware loaded */
15913b00109dSPeng Zhang 	function_id = pci_dev->addr.function & 0x7;
15923b00109dSPeng Zhang 	snprintf(app_name, sizeof(app_name), "_pf%u_net_app_id", function_id);
15933b00109dSPeng Zhang 	app_fw_id = nfp_rtsym_read_le(sym_tbl, app_name, &ret);
1594e7978635SChaoyong He 	if (ret != 0) {
15953b00109dSPeng Zhang 		PMD_INIT_LOG(ERR, "Couldn't read %s from fw", app_name);
1596016141b1SChaoyong He 		ret = -EIO;
1597968ec1c3SChaoyong He 		goto sym_tbl_cleanup;
1598968ec1c3SChaoyong He 	}
1599646ea79cSHeinrich Kuhn 
1600016141b1SChaoyong He 	/* Populate the newly created PF device */
1601016141b1SChaoyong He 	pf_dev->app_fw_id = app_fw_id;
1602016141b1SChaoyong He 	pf_dev->cpp = cpp;
1603016141b1SChaoyong He 	pf_dev->sym_tbl = sym_tbl;
1604016141b1SChaoyong He 	pf_dev->pci_dev = pci_dev;
1605016141b1SChaoyong He 
1606016141b1SChaoyong He 	/* Call app specific init code now */
1607d5f39e07SChaoyong He 	switch (app_fw_id) {
1608d5f39e07SChaoyong He 	case NFP_APP_FW_CORE_NIC:
1609d5f39e07SChaoyong He 		PMD_INIT_LOG(INFO, "Initializing coreNIC");
1610016141b1SChaoyong He 		ret = nfp_secondary_init_app_fw_nic(pf_dev);
1611d5f39e07SChaoyong He 		if (ret != 0) {
1612d5f39e07SChaoyong He 			PMD_INIT_LOG(ERR, "Could not initialize coreNIC!");
1613d5f39e07SChaoyong He 			goto sym_tbl_cleanup;
1614646ea79cSHeinrich Kuhn 		}
1615d5f39e07SChaoyong He 		break;
1616b1880421SChaoyong He 	case NFP_APP_FW_FLOWER_NIC:
1617b1880421SChaoyong He 		PMD_INIT_LOG(INFO, "Initializing Flower");
1618016141b1SChaoyong He 		ret = nfp_secondary_init_app_fw_flower(pf_dev);
1619b1880421SChaoyong He 		if (ret != 0) {
1620b1880421SChaoyong He 			PMD_INIT_LOG(ERR, "Could not initialize Flower!");
1621b1880421SChaoyong He 			goto sym_tbl_cleanup;
1622b1880421SChaoyong He 		}
1623b1880421SChaoyong He 		break;
1624d5f39e07SChaoyong He 	default:
1625d5f39e07SChaoyong He 		PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
1626d5f39e07SChaoyong He 		ret = -EINVAL;
1627d5f39e07SChaoyong He 		goto sym_tbl_cleanup;
1628646ea79cSHeinrich Kuhn 	}
1629646ea79cSHeinrich Kuhn 
1630016141b1SChaoyong He 	return 0;
1631016141b1SChaoyong He 
1632968ec1c3SChaoyong He sym_tbl_cleanup:
1633968ec1c3SChaoyong He 	free(sym_tbl);
1634016141b1SChaoyong He pf_cleanup:
1635016141b1SChaoyong He 	rte_free(pf_dev);
1636968ec1c3SChaoyong He 
1637968ec1c3SChaoyong He 	return ret;
1638646ea79cSHeinrich Kuhn }
1639646ea79cSHeinrich Kuhn 
1640a6189a67SJin Liu static int
1641a6189a67SJin Liu nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
1642646ea79cSHeinrich Kuhn 		struct rte_pci_device *dev)
1643646ea79cSHeinrich Kuhn {
1644646ea79cSHeinrich Kuhn 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
1645646ea79cSHeinrich Kuhn 		return nfp_pf_init(dev);
1646646ea79cSHeinrich Kuhn 	else
1647646ea79cSHeinrich Kuhn 		return nfp_pf_secondary_init(dev);
1648646ea79cSHeinrich Kuhn }
1649646ea79cSHeinrich Kuhn 
1650646ea79cSHeinrich Kuhn static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
1651646ea79cSHeinrich Kuhn 	{
1652646ea79cSHeinrich Kuhn 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
16535c464d6aSJin Liu 				PCI_DEVICE_ID_NFP3800_PF_NIC)
16545c464d6aSJin Liu 	},
16555c464d6aSJin Liu 	{
16565c464d6aSJin Liu 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
1657646ea79cSHeinrich Kuhn 				PCI_DEVICE_ID_NFP4000_PF_NIC)
1658646ea79cSHeinrich Kuhn 	},
1659646ea79cSHeinrich Kuhn 	{
1660646ea79cSHeinrich Kuhn 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
1661646ea79cSHeinrich Kuhn 				PCI_DEVICE_ID_NFP6000_PF_NIC)
1662646ea79cSHeinrich Kuhn 	},
1663646ea79cSHeinrich Kuhn 	{
16645aedd4c3SJames Hershaw 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
16655aedd4c3SJames Hershaw 				PCI_DEVICE_ID_NFP3800_PF_NIC)
16665aedd4c3SJames Hershaw 	},
16675aedd4c3SJames Hershaw 	{
16685aedd4c3SJames Hershaw 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
16695aedd4c3SJames Hershaw 				PCI_DEVICE_ID_NFP4000_PF_NIC)
16705aedd4c3SJames Hershaw 	},
16715aedd4c3SJames Hershaw 	{
16725aedd4c3SJames Hershaw 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CORIGINE,
16735aedd4c3SJames Hershaw 				PCI_DEVICE_ID_NFP6000_PF_NIC)
16745aedd4c3SJames Hershaw 	},
16755aedd4c3SJames Hershaw 	{
1676646ea79cSHeinrich Kuhn 		.vendor_id = 0,
1677646ea79cSHeinrich Kuhn 	},
1678646ea79cSHeinrich Kuhn };
1679646ea79cSHeinrich Kuhn 
1680a6189a67SJin Liu static int
1681a6189a67SJin Liu nfp_pci_uninit(struct rte_eth_dev *eth_dev)
1682646ea79cSHeinrich Kuhn {
1683646ea79cSHeinrich Kuhn 	uint16_t port_id;
168449952141SChaoyong He 	struct rte_pci_device *pci_dev;
1685646ea79cSHeinrich Kuhn 
1686646ea79cSHeinrich Kuhn 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
1687646ea79cSHeinrich Kuhn 
1688646ea79cSHeinrich Kuhn 	/* Free up all physical ports under PF */
1689646ea79cSHeinrich Kuhn 	RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device)
1690646ea79cSHeinrich Kuhn 		rte_eth_dev_close(port_id);
1691646ea79cSHeinrich Kuhn 	/*
1692646ea79cSHeinrich Kuhn 	 * Ports can be closed and freed but hotplugging is not
169340688372SChaoyong He 	 * currently supported.
1694646ea79cSHeinrich Kuhn 	 */
1695646ea79cSHeinrich Kuhn 	return -ENOTSUP;
1696646ea79cSHeinrich Kuhn }
1697646ea79cSHeinrich Kuhn 
1698a6189a67SJin Liu static int
1699a6189a67SJin Liu eth_nfp_pci_remove(struct rte_pci_device *pci_dev)
1700646ea79cSHeinrich Kuhn {
1701646ea79cSHeinrich Kuhn 	return rte_eth_dev_pci_generic_remove(pci_dev, nfp_pci_uninit);
1702646ea79cSHeinrich Kuhn }
1703646ea79cSHeinrich Kuhn 
1704646ea79cSHeinrich Kuhn static struct rte_pci_driver rte_nfp_net_pf_pmd = {
1705646ea79cSHeinrich Kuhn 	.id_table = pci_id_nfp_pf_net_map,
1706646ea79cSHeinrich Kuhn 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
1707646ea79cSHeinrich Kuhn 	.probe = nfp_pf_pci_probe,
1708646ea79cSHeinrich Kuhn 	.remove = eth_nfp_pci_remove,
1709646ea79cSHeinrich Kuhn };
1710646ea79cSHeinrich Kuhn 
1711d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI(NFP_PF_DRIVER_NAME, rte_nfp_net_pf_pmd);
1712d505ee1dSChaoyong He RTE_PMD_REGISTER_PCI_TABLE(NFP_PF_DRIVER_NAME, pci_id_nfp_pf_net_map);
1713d505ee1dSChaoyong He RTE_PMD_REGISTER_KMOD_DEP(NFP_PF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio");
1714