brintos

brintos / linux-shallow public Read only

0
0
Text · 19.0 KiB · cbe4972 Raw
836 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2/* Copyright (C) 2015-2018 Netronome Systems, Inc. */3 4/*5 * nfp_net_main.c6 * Netronome network device driver: Main entry point7 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>8 *          Alejandro Lucero <alejandro.lucero@netronome.com>9 *          Jason McMullan <jason.mcmullan@netronome.com>10 *          Rolf Neugebauer <rolf.neugebauer@netronome.com>11 */12 13#include <linux/etherdevice.h>14#include <linux/kernel.h>15#include <linux/init.h>16#include <linux/lockdep.h>17#include <linux/pci.h>18#include <linux/pci_regs.h>19#include <linux/random.h>20#include <linux/rtnetlink.h>21 22#include "nfpcore/nfp.h"23#include "nfpcore/nfp_cpp.h"24#include "nfpcore/nfp_dev.h"25#include "nfpcore/nfp_nffw.h"26#include "nfpcore/nfp_nsp.h"27#include "nfpcore/nfp6000_pcie.h"28#include "nfp_app.h"29#include "nfp_net_ctrl.h"30#include "nfp_net_sriov.h"31#include "nfp_net.h"32#include "nfp_main.h"33#include "nfp_port.h"34 35#define NFP_PF_CSR_SLICE_SIZE	(32 * 1024)36 37/**38 * nfp_net_get_mac_addr() - Get the MAC address.39 * @pf:       NFP PF handle40 * @netdev:   net_device to set MAC address on41 * @port:     NFP port structure42 *43 * First try to get the MAC address from NSP ETH table. If that44 * fails generate a random address.45 */46void47nfp_net_get_mac_addr(struct nfp_pf *pf, struct net_device *netdev,48		     struct nfp_port *port)49{50	struct nfp_eth_table_port *eth_port;51 52	eth_port = __nfp_port_get_eth_port(port);53	if (!eth_port) {54		eth_hw_addr_random(netdev);55		return;56	}57 58	eth_hw_addr_set(netdev, eth_port->mac_addr);59	ether_addr_copy(netdev->perm_addr, eth_port->mac_addr);60}61 62static struct nfp_eth_table_port *63nfp_net_find_port(struct nfp_eth_table *eth_tbl, unsigned int index)64{65	int i;66 67	for (i = 0; eth_tbl && i < eth_tbl->count; i++)68		if (eth_tbl->ports[i].index == index)69			return &eth_tbl->ports[i];70 71	return NULL;72}73 74static int nfp_net_pf_get_num_ports(struct nfp_pf *pf)75{76	return nfp_pf_rtsym_read_optional(pf, "nfd_cfg_pf%u_num_ports", 1);77}78 79static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn)80{81	if (nfp_net_is_data_vnic(nn))82		nfp_app_vnic_free(pf->app, nn);83	nfp_port_free(nn->port);84	list_del(&nn->vnic_list);85	pf->num_vnics--;86	nfp_net_free(nn);87}88 89static void nfp_net_pf_free_vnics(struct nfp_pf *pf)90{91	struct nfp_net *nn, *next;92 93	list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list)94		if (nfp_net_is_data_vnic(nn))95			nfp_net_pf_free_vnic(pf, nn);96}97 98static struct nfp_net *99nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,100		      void __iomem *ctrl_bar, void __iomem *qc_bar,101		      int stride, unsigned int id)102{103	u32 tx_base, rx_base, n_tx_rings, n_rx_rings;104	struct nfp_net *nn;105	int err;106 107	tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);108	rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);109	n_tx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_TXRINGS);110	n_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);111 112	/* Allocate and initialise the vNIC */113	nn = nfp_net_alloc(pf->pdev, pf->dev_info, ctrl_bar, needs_netdev,114			   n_tx_rings, n_rx_rings);115	if (IS_ERR(nn))116		return nn;117 118	nn->app = pf->app;119	nn->tx_bar = qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;120	nn->rx_bar = qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ;121	nn->dp.is_vf = 0;122	nn->stride_rx = stride;123	nn->stride_tx = stride;124 125	if (needs_netdev) {126		err = nfp_app_vnic_alloc(pf->app, nn, id);127		if (err) {128			nfp_net_free(nn);129			return ERR_PTR(err);130		}131	}132 133	pf->num_vnics++;134	list_add_tail(&nn->vnic_list, &pf->vnics);135 136	return nn;137}138 139static int140nfp_net_pf_init_vnic(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)141{142	int err;143 144	nn->id = id;145 146	if (nn->port) {147		err = nfp_devlink_port_register(pf->app, nn->port);148		if (err)149			return err;150	}151 152	err = nfp_net_init(nn);153	if (err)154		goto err_devlink_port_clean;155 156	nfp_net_debugfs_vnic_add(nn, pf->ddir);157 158	nfp_net_info(nn);159 160	if (nfp_net_is_data_vnic(nn)) {161		err = nfp_app_vnic_init(pf->app, nn);162		if (err)163			goto err_debugfs_vnic_clean;164	}165 166	return 0;167 168err_debugfs_vnic_clean:169	nfp_net_debugfs_dir_clean(&nn->debugfs_dir);170	nfp_net_clean(nn);171err_devlink_port_clean:172	if (nn->port)173		nfp_devlink_port_unregister(nn->port);174	return err;175}176 177static int178nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,179		       void __iomem *qc_bar, int stride)180{181	struct nfp_net *nn;182	unsigned int i;183	int err;184 185	for (i = 0; i < pf->max_data_vnics; i++) {186		nn = nfp_net_pf_alloc_vnic(pf, true, ctrl_bar, qc_bar,187					   stride, i);188		if (IS_ERR(nn)) {189			err = PTR_ERR(nn);190			goto err_free_prev;191		}192 193		if (nn->port)194			nn->port->link_cb = nfp_net_refresh_port_table;195 196		ctrl_bar += NFP_PF_CSR_SLICE_SIZE;197 198		/* Kill the vNIC if app init marked it as invalid */199		if (nn->port && nn->port->type == NFP_PORT_INVALID)200			nfp_net_pf_free_vnic(pf, nn);201	}202 203	if (list_empty(&pf->vnics))204		return -ENODEV;205 206	return 0;207 208err_free_prev:209	nfp_net_pf_free_vnics(pf);210	return err;211}212 213static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)214{215	if (nfp_net_is_data_vnic(nn))216		nfp_app_vnic_clean(pf->app, nn);217	nfp_net_debugfs_dir_clean(&nn->debugfs_dir);218	nfp_net_clean(nn);219	if (nn->port)220		nfp_devlink_port_unregister(nn->port);221}222 223static int nfp_net_pf_alloc_irqs(struct nfp_pf *pf)224{225	unsigned int wanted_irqs, num_irqs, vnics_left, irqs_left;226	struct nfp_net *nn;227 228	/* Get MSI-X vectors */229	wanted_irqs = 0;230	list_for_each_entry(nn, &pf->vnics, vnic_list)231		wanted_irqs += NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs;232	pf->irq_entries = kcalloc(wanted_irqs, sizeof(*pf->irq_entries),233				  GFP_KERNEL);234	if (!pf->irq_entries)235		return -ENOMEM;236 237	num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries,238				      NFP_NET_MIN_VNIC_IRQS * pf->num_vnics,239				      wanted_irqs);240	if (!num_irqs) {241		nfp_warn(pf->cpp, "Unable to allocate MSI-X vectors\n");242		kfree(pf->irq_entries);243		return -ENOMEM;244	}245 246	/* Distribute IRQs to vNICs */247	irqs_left = num_irqs;248	vnics_left = pf->num_vnics;249	list_for_each_entry(nn, &pf->vnics, vnic_list) {250		unsigned int n;251 252		n = min(NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs,253			DIV_ROUND_UP(irqs_left, vnics_left));254		nfp_net_irqs_assign(nn, &pf->irq_entries[num_irqs - irqs_left],255				    n);256		irqs_left -= n;257		vnics_left--;258	}259 260	return 0;261}262 263static void nfp_net_pf_free_irqs(struct nfp_pf *pf)264{265	nfp_net_irqs_disable(pf->pdev);266	kfree(pf->irq_entries);267}268 269static int nfp_net_pf_init_vnics(struct nfp_pf *pf)270{271	struct nfp_net *nn;272	unsigned int id;273	int err;274 275	/* Finish vNIC init and register */276	id = 0;277	list_for_each_entry(nn, &pf->vnics, vnic_list) {278		if (!nfp_net_is_data_vnic(nn))279			continue;280		err = nfp_net_pf_init_vnic(pf, nn, id);281		if (err)282			goto err_prev_deinit;283 284		id++;285	}286 287	return 0;288 289err_prev_deinit:290	list_for_each_entry_continue_reverse(nn, &pf->vnics, vnic_list)291		if (nfp_net_is_data_vnic(nn))292			nfp_net_pf_clean_vnic(pf, nn);293	return err;294}295 296static int297nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)298{299	struct devlink *devlink = priv_to_devlink(pf);300	u8 __iomem *ctrl_bar;301	int err;302 303	pf->app = nfp_app_alloc(pf, nfp_net_pf_get_app_id(pf));304	if (IS_ERR(pf->app))305		return PTR_ERR(pf->app);306 307	devl_lock(devlink);308	err = nfp_app_init(pf->app);309	devl_unlock(devlink);310	if (err)311		goto err_free;312 313	if (!nfp_app_needs_ctrl_vnic(pf->app))314		return 0;315 316	ctrl_bar = nfp_pf_map_rtsym(pf, "net.ctrl", "_pf%u_net_ctrl_bar",317				    NFP_PF_CSR_SLICE_SIZE, &pf->ctrl_vnic_bar);318	if (IS_ERR(ctrl_bar)) {319		nfp_err(pf->cpp, "Failed to find ctrl vNIC memory symbol\n");320		err = PTR_ERR(ctrl_bar);321		goto err_app_clean;322	}323 324	pf->ctrl_vnic =	nfp_net_pf_alloc_vnic(pf, false, ctrl_bar, qc_bar,325					      stride, 0);326	if (IS_ERR(pf->ctrl_vnic)) {327		err = PTR_ERR(pf->ctrl_vnic);328		goto err_unmap;329	}330 331	return 0;332 333err_unmap:334	nfp_cpp_area_release_free(pf->ctrl_vnic_bar);335err_app_clean:336	devl_lock(devlink);337	nfp_app_clean(pf->app);338	devl_unlock(devlink);339err_free:340	nfp_app_free(pf->app);341	pf->app = NULL;342	return err;343}344 345static void nfp_net_pf_app_clean(struct nfp_pf *pf)346{347	struct devlink *devlink = priv_to_devlink(pf);348 349	if (pf->ctrl_vnic) {350		nfp_net_pf_free_vnic(pf, pf->ctrl_vnic);351		nfp_cpp_area_release_free(pf->ctrl_vnic_bar);352	}353 354	devl_lock(devlink);355	nfp_app_clean(pf->app);356	devl_unlock(devlink);357 358	nfp_app_free(pf->app);359	pf->app = NULL;360}361 362static int nfp_net_pf_app_start_ctrl(struct nfp_pf *pf)363{364	int err;365 366	if (!pf->ctrl_vnic)367		return 0;368	err = nfp_net_pf_init_vnic(pf, pf->ctrl_vnic, 0);369	if (err)370		return err;371 372	err = nfp_ctrl_open(pf->ctrl_vnic);373	if (err)374		goto err_clean_ctrl;375 376	return 0;377 378err_clean_ctrl:379	nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic);380	return err;381}382 383static void nfp_net_pf_app_stop_ctrl(struct nfp_pf *pf)384{385	if (!pf->ctrl_vnic)386		return;387	nfp_ctrl_close(pf->ctrl_vnic);388	nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic);389}390 391static int nfp_net_pf_app_start(struct nfp_pf *pf)392{393	int err;394 395	err = nfp_net_pf_app_start_ctrl(pf);396	if (err)397		return err;398 399	err = nfp_app_start(pf->app, pf->ctrl_vnic);400	if (err)401		goto err_ctrl_stop;402 403	if (pf->num_vfs) {404		err = nfp_app_sriov_enable(pf->app, pf->num_vfs);405		if (err)406			goto err_app_stop;407	}408 409	return 0;410 411err_app_stop:412	nfp_app_stop(pf->app);413err_ctrl_stop:414	nfp_net_pf_app_stop_ctrl(pf);415	return err;416}417 418static void nfp_net_pf_app_stop(struct nfp_pf *pf)419{420	if (pf->num_vfs)421		nfp_app_sriov_disable(pf->app);422	nfp_app_stop(pf->app);423	nfp_net_pf_app_stop_ctrl(pf);424}425 426static void nfp_net_pci_unmap_mem(struct nfp_pf *pf)427{428	if (pf->vfcfg_tbl2_area)429		nfp_cpp_area_release_free(pf->vfcfg_tbl2_area);430	if (pf->vf_cfg_bar)431		nfp_cpp_area_release_free(pf->vf_cfg_bar);432	if (pf->mac_stats_bar)433		nfp_cpp_area_release_free(pf->mac_stats_bar);434	nfp_cpp_area_release_free(pf->qc_area);435	nfp_cpp_area_release_free(pf->data_vnic_bar);436}437 438static int nfp_net_pci_map_mem(struct nfp_pf *pf)439{440	u32 min_size, cpp_id;441	u8 __iomem *mem;442	int err;443 444	min_size = pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE;445	mem = nfp_pf_map_rtsym(pf, "net.bar0", "_pf%d_net_bar0",446			       min_size, &pf->data_vnic_bar);447	if (IS_ERR(mem)) {448		nfp_err(pf->cpp, "Failed to find data vNIC memory symbol\n");449		return PTR_ERR(mem);450	}451 452	if (pf->eth_tbl) {453		min_size =  NFP_MAC_STATS_SIZE * (pf->eth_tbl->max_index + 1);454		pf->mac_stats_mem = nfp_rtsym_map(pf->rtbl, "_mac_stats",455						  "net.macstats", min_size,456						  &pf->mac_stats_bar);457		if (IS_ERR(pf->mac_stats_mem)) {458			if (PTR_ERR(pf->mac_stats_mem) != -ENOENT) {459				err = PTR_ERR(pf->mac_stats_mem);460				goto err_unmap_ctrl;461			}462			pf->mac_stats_mem = NULL;463		}464	}465 466	pf->vf_cfg_mem = nfp_pf_map_rtsym(pf, "net.vfcfg", "_pf%d_net_vf_bar",467					  NFP_NET_CFG_BAR_SZ * pf->limit_vfs,468					  &pf->vf_cfg_bar);469	if (IS_ERR(pf->vf_cfg_mem)) {470		if (PTR_ERR(pf->vf_cfg_mem) != -ENOENT) {471			err = PTR_ERR(pf->vf_cfg_mem);472			goto err_unmap_mac_stats;473		}474		pf->vf_cfg_mem = NULL;475	}476 477	min_size = NFP_NET_VF_CFG_SZ * pf->limit_vfs + NFP_NET_VF_CFG_MB_SZ;478	pf->vfcfg_tbl2 = nfp_pf_map_rtsym(pf, "net.vfcfg_tbl2",479					  "_pf%d_net_vf_cfg2",480					  min_size, &pf->vfcfg_tbl2_area);481	if (IS_ERR(pf->vfcfg_tbl2)) {482		if (PTR_ERR(pf->vfcfg_tbl2) != -ENOENT) {483			err = PTR_ERR(pf->vfcfg_tbl2);484			goto err_unmap_vf_cfg;485		}486		pf->vfcfg_tbl2 = NULL;487	}488 489	cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0);490	mem = nfp_cpp_map_area(pf->cpp, "net.qc", cpp_id,491			       nfp_qcp_queue_offset(pf->dev_info, 0),492			       pf->dev_info->qc_area_sz, &pf->qc_area);493	if (IS_ERR(mem)) {494		nfp_err(pf->cpp, "Failed to map Queue Controller area.\n");495		err = PTR_ERR(mem);496		goto err_unmap_vfcfg_tbl2;497	}498 499	return 0;500 501err_unmap_vfcfg_tbl2:502	if (pf->vfcfg_tbl2_area)503		nfp_cpp_area_release_free(pf->vfcfg_tbl2_area);504err_unmap_vf_cfg:505	if (pf->vf_cfg_bar)506		nfp_cpp_area_release_free(pf->vf_cfg_bar);507err_unmap_mac_stats:508	if (pf->mac_stats_bar)509		nfp_cpp_area_release_free(pf->mac_stats_bar);510err_unmap_ctrl:511	nfp_cpp_area_release_free(pf->data_vnic_bar);512	return err;513}514 515static const unsigned int lr_to_speed[] = {516	[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED]	= 0,517	[NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]	= SPEED_UNKNOWN,518	[NFP_NET_CFG_STS_LINK_RATE_1G]		= SPEED_1000,519	[NFP_NET_CFG_STS_LINK_RATE_10G]		= SPEED_10000,520	[NFP_NET_CFG_STS_LINK_RATE_25G]		= SPEED_25000,521	[NFP_NET_CFG_STS_LINK_RATE_40G]		= SPEED_40000,522	[NFP_NET_CFG_STS_LINK_RATE_50G]		= SPEED_50000,523	[NFP_NET_CFG_STS_LINK_RATE_100G]	= SPEED_100000,524};525 526unsigned int nfp_net_lr2speed(unsigned int linkrate)527{528	if (linkrate < ARRAY_SIZE(lr_to_speed))529		return lr_to_speed[linkrate];530 531	return SPEED_UNKNOWN;532}533 534unsigned int nfp_net_speed2lr(unsigned int speed)535{536	int i;537 538	for (i = 0; i < ARRAY_SIZE(lr_to_speed); i++) {539		if (speed == lr_to_speed[i])540			return i;541	}542 543	return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;544}545 546static void nfp_net_notify_port_speed(struct nfp_port *port)547{548	struct net_device *netdev = port->netdev;549	struct nfp_net *nn;550	u16 sts;551 552	if (!nfp_netdev_is_nfp_net(netdev))553		return;554 555	nn = netdev_priv(netdev);556	sts = nn_readw(nn, NFP_NET_CFG_STS);557 558	if (!(sts & NFP_NET_CFG_STS_LINK)) {559		nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);560		return;561	}562 563	nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, nfp_net_speed2lr(port->eth_port->speed));564}565 566static int567nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,568			struct nfp_eth_table *eth_table)569{570	struct nfp_eth_table_port *eth_port;571 572	ASSERT_RTNL();573 574	eth_port = nfp_net_find_port(eth_table, port->eth_id);575	if (!eth_port) {576		set_bit(NFP_PORT_CHANGED, &port->flags);577		nfp_warn(cpp, "Warning: port #%d not present after reconfig\n",578			 port->eth_id);579		return -EIO;580	}581	if (eth_port->override_changed) {582		nfp_warn(cpp, "Port #%d config changed, unregistering. Driver reload required before port will be operational again.\n", port->eth_id);583		port->type = NFP_PORT_INVALID;584	}585 586	memcpy(port->eth_port, eth_port, sizeof(*eth_port));587	nfp_net_notify_port_speed(port);588 589	return 0;590}591 592int nfp_net_refresh_port_table_sync(struct nfp_pf *pf)593{594	struct devlink *devlink = priv_to_devlink(pf);595	struct nfp_eth_table *eth_table;596	struct nfp_net *nn, *next;597	struct nfp_port *port;598	int err;599 600	devl_assert_locked(devlink);601 602	/* Check for nfp_net_pci_remove() racing against us */603	if (list_empty(&pf->vnics))604		return 0;605 606	/* Update state of all ports */607	rtnl_lock();608	list_for_each_entry(port, &pf->ports, port_list)609		clear_bit(NFP_PORT_CHANGED, &port->flags);610 611	eth_table = nfp_eth_read_ports(pf->cpp);612	if (!eth_table) {613		list_for_each_entry(port, &pf->ports, port_list)614			if (__nfp_port_get_eth_port(port))615				set_bit(NFP_PORT_CHANGED, &port->flags);616		rtnl_unlock();617		nfp_err(pf->cpp, "Error refreshing port config!\n");618		return -EIO;619	}620 621	list_for_each_entry(port, &pf->ports, port_list)622		if (__nfp_port_get_eth_port(port))623			nfp_net_eth_port_update(pf->cpp, port, eth_table);624	rtnl_unlock();625 626	kfree(eth_table);627 628	/* Resync repr state. This may cause reprs to be removed. */629	err = nfp_reprs_resync_phys_ports(pf->app);630	if (err)631		return err;632 633	/* Shoot off the ports which became invalid */634	list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {635		if (!nn->port || nn->port->type != NFP_PORT_INVALID)636			continue;637 638		nfp_net_pf_clean_vnic(pf, nn);639		nfp_net_pf_free_vnic(pf, nn);640	}641 642	return 0;643}644 645static void nfp_net_refresh_vnics(struct work_struct *work)646{647	struct nfp_pf *pf = container_of(work, struct nfp_pf,648					 port_refresh_work);649	struct devlink *devlink = priv_to_devlink(pf);650 651	devl_lock(devlink);652	nfp_net_refresh_port_table_sync(pf);653	devl_unlock(devlink);654}655 656void nfp_net_refresh_port_table(struct nfp_port *port)657{658	struct nfp_pf *pf = port->app->pf;659 660	set_bit(NFP_PORT_CHANGED, &port->flags);661 662	queue_work(pf->wq, &pf->port_refresh_work);663}664 665int nfp_net_refresh_eth_port(struct nfp_port *port)666{667	struct nfp_cpp *cpp = port->app->cpp;668	struct nfp_eth_table *eth_table;669	int ret;670 671	clear_bit(NFP_PORT_CHANGED, &port->flags);672 673	eth_table = nfp_eth_read_ports(cpp);674	if (!eth_table) {675		set_bit(NFP_PORT_CHANGED, &port->flags);676		nfp_err(cpp, "Error refreshing port state table!\n");677		return -EIO;678	}679 680	ret = nfp_net_eth_port_update(cpp, port, eth_table);681 682	kfree(eth_table);683 684	return ret;685}686 687/*688 * PCI device functions689 */690int nfp_net_pci_probe(struct nfp_pf *pf)691{692	struct devlink *devlink = priv_to_devlink(pf);693	struct nfp_net_fw_version fw_ver;694	u8 __iomem *ctrl_bar, *qc_bar;695	int stride;696	int err;697 698	INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);699 700	if (!pf->rtbl) {701		nfp_err(pf->cpp, "No %s, giving up.\n",702			pf->fw_loaded ? "symbol table" : "firmware found");703		return -EINVAL;704	}705 706	pf->max_data_vnics = nfp_net_pf_get_num_ports(pf);707	if ((int)pf->max_data_vnics < 0)708		return pf->max_data_vnics;709 710	err = nfp_net_pci_map_mem(pf);711	if (err)712		return err;713 714	ctrl_bar = nfp_cpp_area_iomem(pf->data_vnic_bar);715	qc_bar = nfp_cpp_area_iomem(pf->qc_area);716	if (!ctrl_bar || !qc_bar) {717		err = -EIO;718		goto err_unmap;719	}720 721	nfp_net_get_fw_version(&fw_ver, ctrl_bar);722	if (fw_ver.extend & NFP_NET_CFG_VERSION_RESERVED_MASK ||723	    fw_ver.class != NFP_NET_CFG_VERSION_CLASS_GENERIC) {724		nfp_err(pf->cpp, "Unknown Firmware ABI %d.%d.%d.%d\n",725			fw_ver.extend, fw_ver.class,726			fw_ver.major, fw_ver.minor);727		err = -EINVAL;728		goto err_unmap;729	}730 731	/* Determine stride */732	if (nfp_net_fw_ver_eq(&fw_ver, 0, 0, 0, 1)) {733		stride = 2;734		nfp_warn(pf->cpp, "OBSOLETE Firmware detected - VF isolation not available\n");735	} else {736		switch (fw_ver.major) {737		case 1 ... 5:738			stride = 4;739			break;740		default:741			nfp_err(pf->cpp, "Unsupported Firmware ABI %d.%d.%d.%d\n",742				fw_ver.extend, fw_ver.class,743				fw_ver.major, fw_ver.minor);744			err = -EINVAL;745			goto err_unmap;746		}747	}748 749	err = nfp_net_pf_app_init(pf, qc_bar, stride);750	if (err)751		goto err_unmap;752 753	err = nfp_shared_buf_register(pf);754	if (err)755		goto err_devlink_unreg;756 757	devl_lock(devlink);758	err = nfp_devlink_params_register(pf);759	if (err)760		goto err_shared_buf_unreg;761 762	pf->ddir = nfp_net_debugfs_device_add(pf->pdev);763 764	/* Allocate the vnics and do basic init */765	err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);766	if (err)767		goto err_clean_ddir;768 769	err = nfp_net_pf_alloc_irqs(pf);770	if (err)771		goto err_free_vnics;772 773	err = nfp_net_pf_app_start(pf);774	if (err)775		goto err_free_irqs;776 777	err = nfp_net_pf_init_vnics(pf);778	if (err)779		goto err_stop_app;780 781	devl_unlock(devlink);782	devlink_register(devlink);783 784	return 0;785 786err_stop_app:787	nfp_net_pf_app_stop(pf);788err_free_irqs:789	nfp_net_pf_free_irqs(pf);790err_free_vnics:791	nfp_net_pf_free_vnics(pf);792err_clean_ddir:793	nfp_net_debugfs_dir_clean(&pf->ddir);794	nfp_devlink_params_unregister(pf);795err_shared_buf_unreg:796	devl_unlock(devlink);797	nfp_shared_buf_unregister(pf);798err_devlink_unreg:799	cancel_work_sync(&pf->port_refresh_work);800	nfp_net_pf_app_clean(pf);801err_unmap:802	nfp_net_pci_unmap_mem(pf);803	return err;804}805 806void nfp_net_pci_remove(struct nfp_pf *pf)807{808	struct devlink *devlink = priv_to_devlink(pf);809	struct nfp_net *nn, *next;810 811	devlink_unregister(priv_to_devlink(pf));812	devl_lock(devlink);813	list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {814		if (!nfp_net_is_data_vnic(nn))815			continue;816		nfp_net_pf_clean_vnic(pf, nn);817		nfp_net_pf_free_vnic(pf, nn);818	}819 820	nfp_net_pf_app_stop(pf);821	/* stop app first, to avoid double free of ctrl vNIC's ddir */822	nfp_net_debugfs_dir_clean(&pf->ddir);823 824	nfp_devlink_params_unregister(pf);825 826	devl_unlock(devlink);827 828	nfp_shared_buf_unregister(pf);829 830	nfp_net_pf_free_irqs(pf);831	nfp_net_pf_app_clean(pf);832	nfp_net_pci_unmap_mem(pf);833 834	cancel_work_sync(&pf->port_refresh_work);835}836