196de2506SJakub Kicinski // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
296de2506SJakub Kicinski /* Copyright (C) 2015-2018 Netronome Systems, Inc. */
32633beb9SJakub Kicinski 
42633beb9SJakub Kicinski /*
52633beb9SJakub Kicinski  * nfp_main.c
62633beb9SJakub Kicinski  * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
72633beb9SJakub Kicinski  *          Alejandro Lucero <alejandro.lucero@netronome.com>
82633beb9SJakub Kicinski  *          Jason McMullan <jason.mcmullan@netronome.com>
92633beb9SJakub Kicinski  *          Rolf Neugebauer <rolf.neugebauer@netronome.com>
102633beb9SJakub Kicinski  */
112633beb9SJakub Kicinski 
122633beb9SJakub Kicinski #include <linux/kernel.h>
132633beb9SJakub Kicinski #include <linux/module.h>
14346cfe84SJakub Kicinski #include <linux/mutex.h>
152633beb9SJakub Kicinski #include <linux/pci.h>
162633beb9SJakub Kicinski #include <linux/firmware.h>
172633beb9SJakub Kicinski #include <linux/vermagic.h>
18d79e19f5SCarl Heymann #include <linux/vmalloc.h>
191851f93fSSimon Horman #include <net/devlink.h>
202633beb9SJakub Kicinski 
2163461a02SJakub Kicinski #include "nfpcore/nfp.h"
2263461a02SJakub Kicinski #include "nfpcore/nfp_cpp.h"
230bc3827fSJakub Kicinski #include "nfpcore/nfp_nffw.h"
24ce22f5a2SJakub Kicinski #include "nfpcore/nfp_nsp.h"
2563461a02SJakub Kicinski 
2663461a02SJakub Kicinski #include "nfpcore/nfp6000_pcie.h"
2763461a02SJakub Kicinski 
280c693323SJakub Kicinski #include "nfp_abi.h"
29758238f2SSimon Horman #include "nfp_app.h"
302633beb9SJakub Kicinski #include "nfp_main.h"
312633beb9SJakub Kicinski #include "nfp_net.h"
322633beb9SJakub Kicinski 
332633beb9SJakub Kicinski static const char nfp_driver_name[] = "nfp";
342633beb9SJakub Kicinski const char nfp_driver_version[] = VERMAGIC_STRING;
352633beb9SJakub Kicinski 
3663461a02SJakub Kicinski static const struct pci_device_id nfp_pci_device_ids[] = {
373b473528SSimon Horman 	{ PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000,
3863461a02SJakub Kicinski 	  PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
3963461a02SJakub Kicinski 	  PCI_ANY_ID, 0,
4063461a02SJakub Kicinski 	},
410377505cSJakub Kicinski 	{ PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP5000,
420377505cSJakub Kicinski 	  PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
430377505cSJakub Kicinski 	  PCI_ANY_ID, 0,
440377505cSJakub Kicinski 	},
453b473528SSimon Horman 	{ PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP4000,
4663461a02SJakub Kicinski 	  PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
4763461a02SJakub Kicinski 	  PCI_ANY_ID, 0,
4863461a02SJakub Kicinski 	},
4963461a02SJakub Kicinski 	{ 0, } /* Required last entry. */
5063461a02SJakub Kicinski };
5163461a02SJakub Kicinski MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids);
5263461a02SJakub Kicinski 
538f6196f6SJakub Kicinski int nfp_pf_rtsym_read_optional(struct nfp_pf *pf, const char *format,
548f6196f6SJakub Kicinski 			       unsigned int default_val)
558f6196f6SJakub Kicinski {
568f6196f6SJakub Kicinski 	char name[256];
578f6196f6SJakub Kicinski 	int err = 0;
588f6196f6SJakub Kicinski 	u64 val;
598f6196f6SJakub Kicinski 
608f6196f6SJakub Kicinski 	snprintf(name, sizeof(name), format, nfp_cppcore_pcie_unit(pf->cpp));
618f6196f6SJakub Kicinski 
628f6196f6SJakub Kicinski 	val = nfp_rtsym_read_le(pf->rtbl, name, &err);
638f6196f6SJakub Kicinski 	if (err) {
648f6196f6SJakub Kicinski 		if (err == -ENOENT)
658f6196f6SJakub Kicinski 			return default_val;
668f6196f6SJakub Kicinski 		nfp_err(pf->cpp, "Unable to read symbol %s\n", name);
678f6196f6SJakub Kicinski 		return err;
688f6196f6SJakub Kicinski 	}
698f6196f6SJakub Kicinski 
708f6196f6SJakub Kicinski 	return val;
718f6196f6SJakub Kicinski }
728f6196f6SJakub Kicinski 
738f6196f6SJakub Kicinski u8 __iomem *
748f6196f6SJakub Kicinski nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
758f6196f6SJakub Kicinski 		 unsigned int min_size, struct nfp_cpp_area **area)
768f6196f6SJakub Kicinski {
778f6196f6SJakub Kicinski 	char pf_symbol[256];
788f6196f6SJakub Kicinski 
798f6196f6SJakub Kicinski 	snprintf(pf_symbol, sizeof(pf_symbol), sym_fmt,
808f6196f6SJakub Kicinski 		 nfp_cppcore_pcie_unit(pf->cpp));
818f6196f6SJakub Kicinski 
828f6196f6SJakub Kicinski 	return nfp_rtsym_map(pf->rtbl, pf_symbol, name, min_size, area);
838f6196f6SJakub Kicinski }
848f6196f6SJakub Kicinski 
850c693323SJakub Kicinski /* Callers should hold the devlink instance lock */
860c693323SJakub Kicinski int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
870c693323SJakub Kicinski 		 void *out_data, u64 out_length)
880c693323SJakub Kicinski {
890c693323SJakub Kicinski 	unsigned long err_at;
900c693323SJakub Kicinski 	u64 max_data_sz;
910c693323SJakub Kicinski 	u32 val = 0;
920c693323SJakub Kicinski 	int n, err;
930c693323SJakub Kicinski 
940c693323SJakub Kicinski 	if (!pf->mbox)
950c693323SJakub Kicinski 		return -EOPNOTSUPP;
960c693323SJakub Kicinski 
974152e58cSJakub Kicinski 	max_data_sz = nfp_rtsym_size(pf->mbox) - NFP_MBOX_SYM_MIN_SIZE;
980c693323SJakub Kicinski 
990c693323SJakub Kicinski 	/* Check if cmd field is clear */
1001240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
1010c693323SJakub Kicinski 	if (err || val) {
1020c693323SJakub Kicinski 		nfp_warn(pf->cpp, "failed to issue command (%u): %u, err: %d\n",
1030c693323SJakub Kicinski 			 cmd, val, err);
1040c693323SJakub Kicinski 		return err ?: -EBUSY;
1050c693323SJakub Kicinski 	}
1060c693323SJakub Kicinski 
1070c693323SJakub Kicinski 	in_length = min(in_length, max_data_sz);
1081240989cSJakub Kicinski 	n = nfp_rtsym_write(pf->cpp, pf->mbox, NFP_MBOX_DATA, in_data,
1091240989cSJakub Kicinski 			    in_length);
1100c693323SJakub Kicinski 	if (n != in_length)
1110c693323SJakub Kicinski 		return -EIO;
1120c693323SJakub Kicinski 	/* Write data_len and wipe reserved */
1131240989cSJakub Kicinski 	err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, in_length);
1140c693323SJakub Kicinski 	if (err)
1150c693323SJakub Kicinski 		return err;
1160c693323SJakub Kicinski 
1170c693323SJakub Kicinski 	/* Read back for ordering */
1181240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val);
1190c693323SJakub Kicinski 	if (err)
1200c693323SJakub Kicinski 		return err;
1210c693323SJakub Kicinski 
1220c693323SJakub Kicinski 	/* Write cmd and wipe return value */
1231240989cSJakub Kicinski 	err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_CMD, cmd);
1240c693323SJakub Kicinski 	if (err)
1250c693323SJakub Kicinski 		return err;
1260c693323SJakub Kicinski 
1270c693323SJakub Kicinski 	err_at = jiffies + 5 * HZ;
1280c693323SJakub Kicinski 	while (true) {
1290c693323SJakub Kicinski 		/* Wait for command to go to 0 (NFP_MBOX_NO_CMD) */
1301240989cSJakub Kicinski 		err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
1310c693323SJakub Kicinski 		if (err)
1320c693323SJakub Kicinski 			return err;
1330c693323SJakub Kicinski 		if (!val)
1340c693323SJakub Kicinski 			break;
1350c693323SJakub Kicinski 
1360c693323SJakub Kicinski 		if (time_is_before_eq_jiffies(err_at))
1370c693323SJakub Kicinski 			return -ETIMEDOUT;
1380c693323SJakub Kicinski 
1390c693323SJakub Kicinski 		msleep(5);
1400c693323SJakub Kicinski 	}
1410c693323SJakub Kicinski 
1420c693323SJakub Kicinski 	/* Copy output if any (could be error info, do it before reading ret) */
1431240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val);
1440c693323SJakub Kicinski 	if (err)
1450c693323SJakub Kicinski 		return err;
1460c693323SJakub Kicinski 
1470c693323SJakub Kicinski 	out_length = min_t(u32, val, min(out_length, max_data_sz));
1481240989cSJakub Kicinski 	n = nfp_rtsym_read(pf->cpp, pf->mbox, NFP_MBOX_DATA,
1490c693323SJakub Kicinski 			   out_data, out_length);
1500c693323SJakub Kicinski 	if (n != out_length)
1510c693323SJakub Kicinski 		return -EIO;
1520c693323SJakub Kicinski 
1530c693323SJakub Kicinski 	/* Check if there is an error */
1541240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_RET, &val);
1550c693323SJakub Kicinski 	if (err)
1560c693323SJakub Kicinski 		return err;
1570c693323SJakub Kicinski 	if (val)
1580c693323SJakub Kicinski 		return -val;
1590c693323SJakub Kicinski 
1600c693323SJakub Kicinski 	return out_length;
1610c693323SJakub Kicinski }
1620c693323SJakub Kicinski 
1634cbe94f2SJakub Kicinski static bool nfp_board_ready(struct nfp_pf *pf)
1644cbe94f2SJakub Kicinski {
1654cbe94f2SJakub Kicinski 	const char *cp;
1664cbe94f2SJakub Kicinski 	long state;
1674cbe94f2SJakub Kicinski 	int err;
1684cbe94f2SJakub Kicinski 
1694cbe94f2SJakub Kicinski 	cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
1704cbe94f2SJakub Kicinski 	if (!cp)
1714cbe94f2SJakub Kicinski 		return false;
1724cbe94f2SJakub Kicinski 
1734cbe94f2SJakub Kicinski 	err = kstrtol(cp, 0, &state);
1744cbe94f2SJakub Kicinski 	if (err < 0)
1754cbe94f2SJakub Kicinski 		return false;
1764cbe94f2SJakub Kicinski 
1774cbe94f2SJakub Kicinski 	return state == 15;
1784cbe94f2SJakub Kicinski }
1794cbe94f2SJakub Kicinski 
1804cbe94f2SJakub Kicinski static int nfp_pf_board_state_wait(struct nfp_pf *pf)
1814cbe94f2SJakub Kicinski {
1824cbe94f2SJakub Kicinski 	const unsigned long wait_until = jiffies + 10 * HZ;
1834cbe94f2SJakub Kicinski 
1844cbe94f2SJakub Kicinski 	while (!nfp_board_ready(pf)) {
1854cbe94f2SJakub Kicinski 		if (time_is_before_eq_jiffies(wait_until)) {
1864cbe94f2SJakub Kicinski 			nfp_err(pf->cpp, "NFP board initialization timeout\n");
1874cbe94f2SJakub Kicinski 			return -EINVAL;
1884cbe94f2SJakub Kicinski 		}
1894cbe94f2SJakub Kicinski 
1904cbe94f2SJakub Kicinski 		nfp_info(pf->cpp, "waiting for board initialization\n");
1914cbe94f2SJakub Kicinski 		if (msleep_interruptible(500))
1924cbe94f2SJakub Kicinski 			return -ERESTARTSYS;
1934cbe94f2SJakub Kicinski 
1944cbe94f2SJakub Kicinski 		/* Refresh cached information */
1954cbe94f2SJakub Kicinski 		kfree(pf->hwinfo);
1964cbe94f2SJakub Kicinski 		pf->hwinfo = nfp_hwinfo_read(pf->cpp);
1974cbe94f2SJakub Kicinski 	}
1984cbe94f2SJakub Kicinski 
1994cbe94f2SJakub Kicinski 	return 0;
2004cbe94f2SJakub Kicinski }
2014cbe94f2SJakub Kicinski 
202651e1f2fSJakub Kicinski static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
2030bc3827fSJakub Kicinski {
2040bc3827fSJakub Kicinski 	int err;
2050bc3827fSJakub Kicinski 
206af4fa7eaSJakub Kicinski 	pf->limit_vfs = nfp_rtsym_read_le(pf->rtbl, "nfd_vf_cfg_max_vfs", &err);
2075b0ced17SJakub Kicinski 	if (err) {
2085b0ced17SJakub Kicinski 		/* For backwards compatibility if symbol not found allow all */
2090bc3827fSJakub Kicinski 		pf->limit_vfs = ~0;
210651e1f2fSJakub Kicinski 		if (err == -ENOENT)
211651e1f2fSJakub Kicinski 			return 0;
212651e1f2fSJakub Kicinski 
2130bc3827fSJakub Kicinski 		nfp_warn(pf->cpp, "Warning: VF limit read failed: %d\n", err);
214651e1f2fSJakub Kicinski 		return err;
2150bc3827fSJakub Kicinski 	}
2160bc3827fSJakub Kicinski 
2175b0ced17SJakub Kicinski 	err = pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
2185b0ced17SJakub Kicinski 	if (err)
2195b0ced17SJakub Kicinski 		nfp_warn(pf->cpp, "Failed to set VF count in sysfs: %d\n", err);
2205b0ced17SJakub Kicinski 	return 0;
2215b0ced17SJakub Kicinski }
2225b0ced17SJakub Kicinski 
22363461a02SJakub Kicinski static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs)
22463461a02SJakub Kicinski {
22563461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV
22663461a02SJakub Kicinski 	struct nfp_pf *pf = pci_get_drvdata(pdev);
22763461a02SJakub Kicinski 	int err;
22863461a02SJakub Kicinski 
2290bc3827fSJakub Kicinski 	if (num_vfs > pf->limit_vfs) {
2300bc3827fSJakub Kicinski 		nfp_info(pf->cpp, "Firmware limits number of VFs to %u\n",
2310bc3827fSJakub Kicinski 			 pf->limit_vfs);
232d6e1ab9eSJakub Kicinski 		return -EINVAL;
233758238f2SSimon Horman 	}
234758238f2SSimon Horman 
235e3f28473SJakub Kicinski 	err = pci_enable_sriov(pdev, num_vfs);
236758238f2SSimon Horman 	if (err) {
237e3f28473SJakub Kicinski 		dev_warn(&pdev->dev, "Failed to enable PCI SR-IOV: %d\n", err);
238d6e1ab9eSJakub Kicinski 		return err;
2390bc3827fSJakub Kicinski 	}
2400bc3827fSJakub Kicinski 
241d6e1ab9eSJakub Kicinski 	mutex_lock(&pf->lock);
242d6e1ab9eSJakub Kicinski 
243e3f28473SJakub Kicinski 	err = nfp_app_sriov_enable(pf->app, num_vfs);
24463461a02SJakub Kicinski 	if (err) {
245e3f28473SJakub Kicinski 		dev_warn(&pdev->dev,
246e3f28473SJakub Kicinski 			 "App specific PCI SR-IOV configuration failed: %d\n",
247e3f28473SJakub Kicinski 			 err);
248e3f28473SJakub Kicinski 		goto err_sriov_disable;
24963461a02SJakub Kicinski 	}
25063461a02SJakub Kicinski 
25163461a02SJakub Kicinski 	pf->num_vfs = num_vfs;
25263461a02SJakub Kicinski 
25363461a02SJakub Kicinski 	dev_dbg(&pdev->dev, "Created %d VFs.\n", pf->num_vfs);
25463461a02SJakub Kicinski 
255758238f2SSimon Horman 	mutex_unlock(&pf->lock);
25663461a02SJakub Kicinski 	return num_vfs;
257758238f2SSimon Horman 
258e3f28473SJakub Kicinski err_sriov_disable:
259758238f2SSimon Horman 	mutex_unlock(&pf->lock);
260d6e1ab9eSJakub Kicinski 	pci_disable_sriov(pdev);
261758238f2SSimon Horman 	return err;
26263461a02SJakub Kicinski #endif
26363461a02SJakub Kicinski 	return 0;
26463461a02SJakub Kicinski }
26563461a02SJakub Kicinski 
266e3f28473SJakub Kicinski static int nfp_pcie_sriov_disable(struct pci_dev *pdev)
26763461a02SJakub Kicinski {
26863461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV
26963461a02SJakub Kicinski 	struct nfp_pf *pf = pci_get_drvdata(pdev);
27063461a02SJakub Kicinski 
271e3f28473SJakub Kicinski 	mutex_lock(&pf->lock);
272e3f28473SJakub Kicinski 
27363461a02SJakub Kicinski 	/* If the VFs are assigned we cannot shut down SR-IOV without
27463461a02SJakub Kicinski 	 * causing issues, so just leave the hardware available but
27563461a02SJakub Kicinski 	 * disabled
27663461a02SJakub Kicinski 	 */
27763461a02SJakub Kicinski 	if (pci_vfs_assigned(pdev)) {
27863461a02SJakub Kicinski 		dev_warn(&pdev->dev, "Disabling while VFs assigned - VFs will not be deallocated\n");
279e3f28473SJakub Kicinski 		mutex_unlock(&pf->lock);
28063461a02SJakub Kicinski 		return -EPERM;
28163461a02SJakub Kicinski 	}
28263461a02SJakub Kicinski 
283758238f2SSimon Horman 	nfp_app_sriov_disable(pf->app);
284758238f2SSimon Horman 
28563461a02SJakub Kicinski 	pf->num_vfs = 0;
28663461a02SJakub Kicinski 
287d6e1ab9eSJakub Kicinski 	mutex_unlock(&pf->lock);
288d6e1ab9eSJakub Kicinski 
28963461a02SJakub Kicinski 	pci_disable_sriov(pdev);
29063461a02SJakub Kicinski 	dev_dbg(&pdev->dev, "Removed VFs.\n");
29163461a02SJakub Kicinski #endif
29263461a02SJakub Kicinski 	return 0;
29363461a02SJakub Kicinski }
29463461a02SJakub Kicinski 
29563461a02SJakub Kicinski static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs)
29663461a02SJakub Kicinski {
29763461a02SJakub Kicinski 	if (num_vfs == 0)
29863461a02SJakub Kicinski 		return nfp_pcie_sriov_disable(pdev);
29963461a02SJakub Kicinski 	else
30063461a02SJakub Kicinski 		return nfp_pcie_sriov_enable(pdev, num_vfs);
30163461a02SJakub Kicinski }
30263461a02SJakub Kicinski 
3035c5696f3SJakub Kicinski int nfp_flash_update_common(struct nfp_pf *pf, const char *path,
3045c5696f3SJakub Kicinski 			    struct netlink_ext_ack *extack)
3055c5696f3SJakub Kicinski {
3065c5696f3SJakub Kicinski 	struct device *dev = &pf->pdev->dev;
3075c5696f3SJakub Kicinski 	const struct firmware *fw;
3085c5696f3SJakub Kicinski 	struct nfp_nsp *nsp;
3095c5696f3SJakub Kicinski 	int err;
3105c5696f3SJakub Kicinski 
3115c5696f3SJakub Kicinski 	nsp = nfp_nsp_open(pf->cpp);
3125c5696f3SJakub Kicinski 	if (IS_ERR(nsp)) {
3135c5696f3SJakub Kicinski 		err = PTR_ERR(nsp);
3145c5696f3SJakub Kicinski 		if (extack)
3155c5696f3SJakub Kicinski 			NL_SET_ERR_MSG_MOD(extack, "can't access NSP");
3165c5696f3SJakub Kicinski 		else
3175c5696f3SJakub Kicinski 			dev_err(dev, "Failed to access the NSP: %d\n", err);
3185c5696f3SJakub Kicinski 		return err;
3195c5696f3SJakub Kicinski 	}
3205c5696f3SJakub Kicinski 
3215c5696f3SJakub Kicinski 	err = request_firmware_direct(&fw, path, dev);
3225c5696f3SJakub Kicinski 	if (err) {
3235c5696f3SJakub Kicinski 		NL_SET_ERR_MSG_MOD(extack,
3245c5696f3SJakub Kicinski 				   "unable to read flash file from disk");
3255c5696f3SJakub Kicinski 		goto exit_close_nsp;
3265c5696f3SJakub Kicinski 	}
3275c5696f3SJakub Kicinski 
3285c5696f3SJakub Kicinski 	dev_info(dev, "Please be patient while writing flash image: %s\n",
3295c5696f3SJakub Kicinski 		 path);
3305c5696f3SJakub Kicinski 
3315c5696f3SJakub Kicinski 	err = nfp_nsp_write_flash(nsp, fw);
3325c5696f3SJakub Kicinski 	if (err < 0)
3335c5696f3SJakub Kicinski 		goto exit_release_fw;
3345c5696f3SJakub Kicinski 	dev_info(dev, "Finished writing flash image\n");
3355c5696f3SJakub Kicinski 	err = 0;
3365c5696f3SJakub Kicinski 
3375c5696f3SJakub Kicinski exit_release_fw:
3385c5696f3SJakub Kicinski 	release_firmware(fw);
3395c5696f3SJakub Kicinski exit_close_nsp:
3405c5696f3SJakub Kicinski 	nfp_nsp_close(nsp);
3415c5696f3SJakub Kicinski 	return err;
3425c5696f3SJakub Kicinski }
3435c5696f3SJakub Kicinski 
3441680a370SJakub Kicinski static const struct firmware *
3451680a370SJakub Kicinski nfp_net_fw_request(struct pci_dev *pdev, struct nfp_pf *pf, const char *name)
3461680a370SJakub Kicinski {
3471680a370SJakub Kicinski 	const struct firmware *fw = NULL;
3481680a370SJakub Kicinski 	int err;
3491680a370SJakub Kicinski 
3501680a370SJakub Kicinski 	err = request_firmware_direct(&fw, name, &pdev->dev);
3511680a370SJakub Kicinski 	nfp_info(pf->cpp, "  %s: %s\n",
3521680a370SJakub Kicinski 		 name, err ? "not found" : "found, loading...");
3531680a370SJakub Kicinski 	if (err)
3541680a370SJakub Kicinski 		return NULL;
3551680a370SJakub Kicinski 
3561680a370SJakub Kicinski 	return fw;
3571680a370SJakub Kicinski }
3581680a370SJakub Kicinski 
35963461a02SJakub Kicinski /**
36063461a02SJakub Kicinski  * nfp_net_fw_find() - Find the correct firmware image for netdev mode
36163461a02SJakub Kicinski  * @pdev:	PCI Device structure
36263461a02SJakub Kicinski  * @pf:		NFP PF Device structure
36363461a02SJakub Kicinski  *
36463461a02SJakub Kicinski  * Return: firmware if found and requested successfully.
36563461a02SJakub Kicinski  */
36663461a02SJakub Kicinski static const struct firmware *
36763461a02SJakub Kicinski nfp_net_fw_find(struct pci_dev *pdev, struct nfp_pf *pf)
36863461a02SJakub Kicinski {
36963461a02SJakub Kicinski 	struct nfp_eth_table_port *port;
3701680a370SJakub Kicinski 	const struct firmware *fw;
37163461a02SJakub Kicinski 	const char *fw_model;
37263461a02SJakub Kicinski 	char fw_name[256];
3739511f298SJakub Kicinski 	const u8 *serial;
3749511f298SJakub Kicinski 	u16 interface;
3751680a370SJakub Kicinski 	int spc, i, j;
3761680a370SJakub Kicinski 
3771680a370SJakub Kicinski 	nfp_info(pf->cpp, "Looking for firmware file in order of priority:\n");
37863461a02SJakub Kicinski 
3799511f298SJakub Kicinski 	/* First try to find a firmware image specific for this device */
3809511f298SJakub Kicinski 	interface = nfp_cpp_interface(pf->cpp);
3819511f298SJakub Kicinski 	nfp_cpp_serial(pf->cpp, &serial);
3829511f298SJakub Kicinski 	sprintf(fw_name, "netronome/serial-%pMF-%02hhx-%02hhx.nffw",
3839511f298SJakub Kicinski 		serial, interface >> 8, interface & 0xff);
3841680a370SJakub Kicinski 	fw = nfp_net_fw_request(pdev, pf, fw_name);
3851680a370SJakub Kicinski 	if (fw)
3861680a370SJakub Kicinski 		return fw;
3879511f298SJakub Kicinski 
3889511f298SJakub Kicinski 	/* Then try the PCI name */
3899511f298SJakub Kicinski 	sprintf(fw_name, "netronome/pci-%s.nffw", pci_name(pdev));
3901680a370SJakub Kicinski 	fw = nfp_net_fw_request(pdev, pf, fw_name);
3911680a370SJakub Kicinski 	if (fw)
3921680a370SJakub Kicinski 		return fw;
3939511f298SJakub Kicinski 
3949511f298SJakub Kicinski 	/* Finally try the card type and media */
39563461a02SJakub Kicinski 	if (!pf->eth_tbl) {
39663461a02SJakub Kicinski 		dev_err(&pdev->dev, "Error: can't identify media config\n");
39763461a02SJakub Kicinski 		return NULL;
39863461a02SJakub Kicinski 	}
39963461a02SJakub Kicinski 
4009baa4885SJakub Kicinski 	fw_model = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
40163461a02SJakub Kicinski 	if (!fw_model) {
40263461a02SJakub Kicinski 		dev_err(&pdev->dev, "Error: can't read part number\n");
40363461a02SJakub Kicinski 		return NULL;
40463461a02SJakub Kicinski 	}
40563461a02SJakub Kicinski 
40663461a02SJakub Kicinski 	spc = ARRAY_SIZE(fw_name);
40763461a02SJakub Kicinski 	spc -= snprintf(fw_name, spc, "netronome/nic_%s", fw_model);
40863461a02SJakub Kicinski 
40963461a02SJakub Kicinski 	for (i = 0; spc > 0 && i < pf->eth_tbl->count; i += j) {
41063461a02SJakub Kicinski 		port = &pf->eth_tbl->ports[i];
41163461a02SJakub Kicinski 		j = 1;
41263461a02SJakub Kicinski 		while (i + j < pf->eth_tbl->count &&
41363461a02SJakub Kicinski 		       port->speed == port[j].speed)
41463461a02SJakub Kicinski 			j++;
41563461a02SJakub Kicinski 
41663461a02SJakub Kicinski 		spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc,
41763461a02SJakub Kicinski 				"_%dx%d", j, port->speed / 1000);
41863461a02SJakub Kicinski 	}
41963461a02SJakub Kicinski 
42063461a02SJakub Kicinski 	if (spc <= 0)
42163461a02SJakub Kicinski 		return NULL;
42263461a02SJakub Kicinski 
42363461a02SJakub Kicinski 	spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, ".nffw");
42463461a02SJakub Kicinski 	if (spc <= 0)
42563461a02SJakub Kicinski 		return NULL;
42663461a02SJakub Kicinski 
4271680a370SJakub Kicinski 	return nfp_net_fw_request(pdev, pf, fw_name);
42863461a02SJakub Kicinski }
42963461a02SJakub Kicinski 
43063461a02SJakub Kicinski /**
43163461a02SJakub Kicinski  * nfp_net_fw_load() - Load the firmware image
43263461a02SJakub Kicinski  * @pdev:       PCI Device structure
43363461a02SJakub Kicinski  * @pf:		NFP PF Device structure
43463461a02SJakub Kicinski  * @nsp:	NFP SP handle
43563461a02SJakub Kicinski  *
43663461a02SJakub Kicinski  * Return: -ERRNO, 0 for no firmware loaded, 1 for firmware loaded
43763461a02SJakub Kicinski  */
43863461a02SJakub Kicinski static int
43963461a02SJakub Kicinski nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp)
44063461a02SJakub Kicinski {
44163461a02SJakub Kicinski 	const struct firmware *fw;
44263461a02SJakub Kicinski 	u16 interface;
44363461a02SJakub Kicinski 	int err;
44463461a02SJakub Kicinski 
44563461a02SJakub Kicinski 	interface = nfp_cpp_interface(pf->cpp);
44663461a02SJakub Kicinski 	if (NFP_CPP_INTERFACE_UNIT_of(interface) != 0) {
44763461a02SJakub Kicinski 		/* Only Unit 0 should reset or load firmware */
44863461a02SJakub Kicinski 		dev_info(&pdev->dev, "Firmware will be loaded by partner\n");
44963461a02SJakub Kicinski 		return 0;
45063461a02SJakub Kicinski 	}
45163461a02SJakub Kicinski 
45263461a02SJakub Kicinski 	fw = nfp_net_fw_find(pdev, pf);
4532db10000SJakub Kicinski 	if (!fw) {
4542db10000SJakub Kicinski 		if (nfp_nsp_has_stored_fw_load(nsp))
4552db10000SJakub Kicinski 			nfp_nsp_load_stored_fw(nsp);
45663461a02SJakub Kicinski 		return 0;
4572db10000SJakub Kicinski 	}
45863461a02SJakub Kicinski 
45963461a02SJakub Kicinski 	dev_info(&pdev->dev, "Soft-reset, loading FW image\n");
46063461a02SJakub Kicinski 	err = nfp_nsp_device_soft_reset(nsp);
46163461a02SJakub Kicinski 	if (err < 0) {
46263461a02SJakub Kicinski 		dev_err(&pdev->dev, "Failed to soft reset the NFP: %d\n",
46363461a02SJakub Kicinski 			err);
46463461a02SJakub Kicinski 		goto exit_release_fw;
46563461a02SJakub Kicinski 	}
46663461a02SJakub Kicinski 
46763461a02SJakub Kicinski 	err = nfp_nsp_load_fw(nsp, fw);
46863461a02SJakub Kicinski 	if (err < 0) {
46963461a02SJakub Kicinski 		dev_err(&pdev->dev, "FW loading failed: %d\n", err);
47063461a02SJakub Kicinski 		goto exit_release_fw;
47163461a02SJakub Kicinski 	}
47263461a02SJakub Kicinski 
47363461a02SJakub Kicinski 	dev_info(&pdev->dev, "Finished loading FW image\n");
47463461a02SJakub Kicinski 
47563461a02SJakub Kicinski exit_release_fw:
47663461a02SJakub Kicinski 	release_firmware(fw);
47763461a02SJakub Kicinski 
47863461a02SJakub Kicinski 	return err < 0 ? err : 1;
47963461a02SJakub Kicinski }
48063461a02SJakub Kicinski 
4817717c319SJakub Kicinski static void
4827717c319SJakub Kicinski nfp_nsp_init_ports(struct pci_dev *pdev, struct nfp_pf *pf,
4837717c319SJakub Kicinski 		   struct nfp_nsp *nsp)
4847717c319SJakub Kicinski {
4857717c319SJakub Kicinski 	bool needs_reinit = false;
4867717c319SJakub Kicinski 	int i;
4877717c319SJakub Kicinski 
4887717c319SJakub Kicinski 	pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
4897717c319SJakub Kicinski 	if (!pf->eth_tbl)
4907717c319SJakub Kicinski 		return;
4917717c319SJakub Kicinski 
4927717c319SJakub Kicinski 	if (!nfp_nsp_has_mac_reinit(nsp))
4937717c319SJakub Kicinski 		return;
4947717c319SJakub Kicinski 
4957717c319SJakub Kicinski 	for (i = 0; i < pf->eth_tbl->count; i++)
4967717c319SJakub Kicinski 		needs_reinit |= pf->eth_tbl->ports[i].override_changed;
4977717c319SJakub Kicinski 	if (!needs_reinit)
4987717c319SJakub Kicinski 		return;
4997717c319SJakub Kicinski 
5007717c319SJakub Kicinski 	kfree(pf->eth_tbl);
5017717c319SJakub Kicinski 	if (nfp_nsp_mac_reinit(nsp))
5027717c319SJakub Kicinski 		dev_warn(&pdev->dev, "MAC reinit failed\n");
5037717c319SJakub Kicinski 
5047717c319SJakub Kicinski 	pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
5057717c319SJakub Kicinski }
5067717c319SJakub Kicinski 
507a9c83f7bSJakub Kicinski static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
508a9c83f7bSJakub Kicinski {
509a9c83f7bSJakub Kicinski 	struct nfp_nsp *nsp;
510a9c83f7bSJakub Kicinski 	int err;
511a9c83f7bSJakub Kicinski 
5127dbd5b75SJakub Kicinski 	err = nfp_resource_wait(pf->cpp, NFP_RESOURCE_NSP, 30);
5137dbd5b75SJakub Kicinski 	if (err)
5147dbd5b75SJakub Kicinski 		return err;
5157dbd5b75SJakub Kicinski 
516a9c83f7bSJakub Kicinski 	nsp = nfp_nsp_open(pf->cpp);
517a9c83f7bSJakub Kicinski 	if (IS_ERR(nsp)) {
518a9c83f7bSJakub Kicinski 		err = PTR_ERR(nsp);
519a9c83f7bSJakub Kicinski 		dev_err(&pdev->dev, "Failed to access the NSP: %d\n", err);
520a9c83f7bSJakub Kicinski 		return err;
521a9c83f7bSJakub Kicinski 	}
522a9c83f7bSJakub Kicinski 
523a9c83f7bSJakub Kicinski 	err = nfp_nsp_wait(nsp);
524a9c83f7bSJakub Kicinski 	if (err < 0)
525a9c83f7bSJakub Kicinski 		goto exit_close_nsp;
526a9c83f7bSJakub Kicinski 
5277717c319SJakub Kicinski 	nfp_nsp_init_ports(pdev, pf, nsp);
528a9c83f7bSJakub Kicinski 
529eefbde7eSDavid Brunecz 	pf->nspi = __nfp_nsp_identify(nsp);
530eefbde7eSDavid Brunecz 	if (pf->nspi)
531eefbde7eSDavid Brunecz 		dev_info(&pdev->dev, "BSP: %s\n", pf->nspi->version);
532010e2f9cSDavid Brunecz 
533a9c83f7bSJakub Kicinski 	err = nfp_fw_load(pdev, pf, nsp);
534a9c83f7bSJakub Kicinski 	if (err < 0) {
53547eaa23bSJakub Kicinski 		kfree(pf->nspi);
536a9c83f7bSJakub Kicinski 		kfree(pf->eth_tbl);
537a9c83f7bSJakub Kicinski 		dev_err(&pdev->dev, "Failed to load FW\n");
538a9c83f7bSJakub Kicinski 		goto exit_close_nsp;
539a9c83f7bSJakub Kicinski 	}
540a9c83f7bSJakub Kicinski 
541a9c83f7bSJakub Kicinski 	pf->fw_loaded = !!err;
542a9c83f7bSJakub Kicinski 	err = 0;
543a9c83f7bSJakub Kicinski 
544a9c83f7bSJakub Kicinski exit_close_nsp:
545a9c83f7bSJakub Kicinski 	nfp_nsp_close(nsp);
546a9c83f7bSJakub Kicinski 
547a9c83f7bSJakub Kicinski 	return err;
548a9c83f7bSJakub Kicinski }
549a9c83f7bSJakub Kicinski 
55063461a02SJakub Kicinski static void nfp_fw_unload(struct nfp_pf *pf)
55163461a02SJakub Kicinski {
55263461a02SJakub Kicinski 	struct nfp_nsp *nsp;
55363461a02SJakub Kicinski 	int err;
55463461a02SJakub Kicinski 
55563461a02SJakub Kicinski 	nsp = nfp_nsp_open(pf->cpp);
55663461a02SJakub Kicinski 	if (IS_ERR(nsp)) {
55763461a02SJakub Kicinski 		nfp_err(pf->cpp, "Reset failed, can't open NSP\n");
55863461a02SJakub Kicinski 		return;
55963461a02SJakub Kicinski 	}
56063461a02SJakub Kicinski 
56163461a02SJakub Kicinski 	err = nfp_nsp_device_soft_reset(nsp);
56263461a02SJakub Kicinski 	if (err < 0)
56363461a02SJakub Kicinski 		dev_warn(&pf->pdev->dev, "Couldn't unload firmware: %d\n", err);
56463461a02SJakub Kicinski 	else
56563461a02SJakub Kicinski 		dev_info(&pf->pdev->dev, "Firmware safely unloaded\n");
56663461a02SJakub Kicinski 
56763461a02SJakub Kicinski 	nfp_nsp_close(nsp);
56863461a02SJakub Kicinski }
56963461a02SJakub Kicinski 
5700c693323SJakub Kicinski static int nfp_pf_find_rtsyms(struct nfp_pf *pf)
5710c693323SJakub Kicinski {
5720c693323SJakub Kicinski 	char pf_symbol[256];
5730c693323SJakub Kicinski 	unsigned int pf_id;
5740c693323SJakub Kicinski 
5750c693323SJakub Kicinski 	pf_id = nfp_cppcore_pcie_unit(pf->cpp);
5760c693323SJakub Kicinski 
5770c693323SJakub Kicinski 	/* Optional per-PCI PF mailbox */
5780c693323SJakub Kicinski 	snprintf(pf_symbol, sizeof(pf_symbol), NFP_MBOX_SYM_NAME, pf_id);
5790c693323SJakub Kicinski 	pf->mbox = nfp_rtsym_lookup(pf->rtbl, pf_symbol);
5804152e58cSJakub Kicinski 	if (pf->mbox && nfp_rtsym_size(pf->mbox) < NFP_MBOX_SYM_MIN_SIZE) {
5810c693323SJakub Kicinski 		nfp_err(pf->cpp, "PF mailbox symbol too small: %llu < %d\n",
5824152e58cSJakub Kicinski 			nfp_rtsym_size(pf->mbox), NFP_MBOX_SYM_MIN_SIZE);
5830c693323SJakub Kicinski 		return -EINVAL;
5840c693323SJakub Kicinski 	}
5850c693323SJakub Kicinski 
5860c693323SJakub Kicinski 	return 0;
5870c693323SJakub Kicinski }
5880c693323SJakub Kicinski 
58963461a02SJakub Kicinski static int nfp_pci_probe(struct pci_dev *pdev,
59063461a02SJakub Kicinski 			 const struct pci_device_id *pci_id)
59163461a02SJakub Kicinski {
5921851f93fSSimon Horman 	struct devlink *devlink;
59363461a02SJakub Kicinski 	struct nfp_pf *pf;
59463461a02SJakub Kicinski 	int err;
59563461a02SJakub Kicinski 
59663461a02SJakub Kicinski 	err = pci_enable_device(pdev);
59763461a02SJakub Kicinski 	if (err < 0)
59863461a02SJakub Kicinski 		return err;
59963461a02SJakub Kicinski 
60063461a02SJakub Kicinski 	pci_set_master(pdev);
60163461a02SJakub Kicinski 
60263461a02SJakub Kicinski 	err = dma_set_mask_and_coherent(&pdev->dev,
60363461a02SJakub Kicinski 					DMA_BIT_MASK(NFP_NET_MAX_DMA_BITS));
60463461a02SJakub Kicinski 	if (err)
60563461a02SJakub Kicinski 		goto err_pci_disable;
60663461a02SJakub Kicinski 
60763461a02SJakub Kicinski 	err = pci_request_regions(pdev, nfp_driver_name);
60863461a02SJakub Kicinski 	if (err < 0) {
60963461a02SJakub Kicinski 		dev_err(&pdev->dev, "Unable to reserve pci resources.\n");
61063461a02SJakub Kicinski 		goto err_pci_disable;
61163461a02SJakub Kicinski 	}
61263461a02SJakub Kicinski 
6131851f93fSSimon Horman 	devlink = devlink_alloc(&nfp_devlink_ops, sizeof(*pf));
6141851f93fSSimon Horman 	if (!devlink) {
61563461a02SJakub Kicinski 		err = -ENOMEM;
61663461a02SJakub Kicinski 		goto err_rel_regions;
61763461a02SJakub Kicinski 	}
6181851f93fSSimon Horman 	pf = devlink_priv(devlink);
619d4e7f092SJakub Kicinski 	INIT_LIST_HEAD(&pf->vnics);
6203eb3b74aSJakub Kicinski 	INIT_LIST_HEAD(&pf->ports);
621346cfe84SJakub Kicinski 	mutex_init(&pf->lock);
62263461a02SJakub Kicinski 	pci_set_drvdata(pdev, pf);
62363461a02SJakub Kicinski 	pf->pdev = pdev;
62463461a02SJakub Kicinski 
6256d48ceb2SJakub Kicinski 	pf->wq = alloc_workqueue("nfp-%s", 0, 2, pci_name(pdev));
6266d48ceb2SJakub Kicinski 	if (!pf->wq) {
6276d48ceb2SJakub Kicinski 		err = -ENOMEM;
6286d48ceb2SJakub Kicinski 		goto err_pci_priv_unset;
6296d48ceb2SJakub Kicinski 	}
6306d48ceb2SJakub Kicinski 
63163461a02SJakub Kicinski 	pf->cpp = nfp_cpp_from_nfp6000_pcie(pdev);
63263461a02SJakub Kicinski 	if (IS_ERR_OR_NULL(pf->cpp)) {
63363461a02SJakub Kicinski 		err = PTR_ERR(pf->cpp);
63463461a02SJakub Kicinski 		if (err >= 0)
63563461a02SJakub Kicinski 			err = -ENOMEM;
63663461a02SJakub Kicinski 		goto err_disable_msix;
63763461a02SJakub Kicinski 	}
63863461a02SJakub Kicinski 
6393e3e9fd8SJakub Kicinski 	err = nfp_resource_table_init(pf->cpp);
6403e3e9fd8SJakub Kicinski 	if (err)
6413e3e9fd8SJakub Kicinski 		goto err_cpp_free;
6423e3e9fd8SJakub Kicinski 
6439baa4885SJakub Kicinski 	pf->hwinfo = nfp_hwinfo_read(pf->cpp);
6449baa4885SJakub Kicinski 
64564db09edSJakub Kicinski 	dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n",
6469baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"),
6479baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"),
6489baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"),
6499baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"),
6509baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "cpld.version"));
65164db09edSJakub Kicinski 
6524cbe94f2SJakub Kicinski 	err = nfp_pf_board_state_wait(pf);
6534cbe94f2SJakub Kicinski 	if (err)
6544cbe94f2SJakub Kicinski 		goto err_hwinfo_free;
6554cbe94f2SJakub Kicinski 
6561851f93fSSimon Horman 	err = nfp_nsp_init(pdev, pf);
6571851f93fSSimon Horman 	if (err)
658bcc93a23SJakub Kicinski 		goto err_hwinfo_free;
6591851f93fSSimon Horman 
6600be40e66SJakub Kicinski 	pf->mip = nfp_mip_open(pf->cpp);
6610be40e66SJakub Kicinski 	pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip);
662af4fa7eaSJakub Kicinski 
6630c693323SJakub Kicinski 	err = nfp_pf_find_rtsyms(pf);
6640c693323SJakub Kicinski 	if (err)
6650c693323SJakub Kicinski 		goto err_fw_unload;
6660c693323SJakub Kicinski 
667d79e19f5SCarl Heymann 	pf->dump_flag = NFP_DUMP_NSP_DIAG;
668d79e19f5SCarl Heymann 	pf->dumpspec = nfp_net_dump_load_dumpspec(pf->cpp, pf->rtbl);
669d79e19f5SCarl Heymann 
670651e1f2fSJakub Kicinski 	err = nfp_pcie_sriov_read_nfd_limit(pf);
67163461a02SJakub Kicinski 	if (err)
67263461a02SJakub Kicinski 		goto err_fw_unload;
67363461a02SJakub Kicinski 
6740dc78621SJakub Kicinski 	pf->num_vfs = pci_num_vf(pdev);
6750dc78621SJakub Kicinski 	if (pf->num_vfs > pf->limit_vfs) {
6760dc78621SJakub Kicinski 		dev_err(&pdev->dev,
6770dc78621SJakub Kicinski 			"Error: %d VFs already enabled, but loaded FW can only support %d\n",
6780dc78621SJakub Kicinski 			pf->num_vfs, pf->limit_vfs);
679e58decc9SWei Yongjun 		err = -EINVAL;
6800dc78621SJakub Kicinski 		goto err_fw_unload;
6810dc78621SJakub Kicinski 	}
6820dc78621SJakub Kicinski 
683651e1f2fSJakub Kicinski 	err = nfp_net_pci_probe(pf);
684651e1f2fSJakub Kicinski 	if (err)
68583235822SJakub Kicinski 		goto err_fw_unload;
686651e1f2fSJakub Kicinski 
687eefbde7eSDavid Brunecz 	err = nfp_hwmon_register(pf);
688eefbde7eSDavid Brunecz 	if (err) {
689eefbde7eSDavid Brunecz 		dev_err(&pdev->dev, "Failed to register hwmon info\n");
690eefbde7eSDavid Brunecz 		goto err_net_remove;
691eefbde7eSDavid Brunecz 	}
692eefbde7eSDavid Brunecz 
69363461a02SJakub Kicinski 	return 0;
69463461a02SJakub Kicinski 
695eefbde7eSDavid Brunecz err_net_remove:
696eefbde7eSDavid Brunecz 	nfp_net_pci_remove(pf);
69763461a02SJakub Kicinski err_fw_unload:
698af4fa7eaSJakub Kicinski 	kfree(pf->rtbl);
6990be40e66SJakub Kicinski 	nfp_mip_close(pf->mip);
70063461a02SJakub Kicinski 	if (pf->fw_loaded)
70163461a02SJakub Kicinski 		nfp_fw_unload(pf);
70263461a02SJakub Kicinski 	kfree(pf->eth_tbl);
703eefbde7eSDavid Brunecz 	kfree(pf->nspi);
704d79e19f5SCarl Heymann 	vfree(pf->dumpspec);
7059baa4885SJakub Kicinski err_hwinfo_free:
7069baa4885SJakub Kicinski 	kfree(pf->hwinfo);
7073e3e9fd8SJakub Kicinski err_cpp_free:
70863461a02SJakub Kicinski 	nfp_cpp_free(pf->cpp);
70963461a02SJakub Kicinski err_disable_msix:
7106d48ceb2SJakub Kicinski 	destroy_workqueue(pf->wq);
7116d48ceb2SJakub Kicinski err_pci_priv_unset:
71263461a02SJakub Kicinski 	pci_set_drvdata(pdev, NULL);
713346cfe84SJakub Kicinski 	mutex_destroy(&pf->lock);
7141851f93fSSimon Horman 	devlink_free(devlink);
71563461a02SJakub Kicinski err_rel_regions:
71663461a02SJakub Kicinski 	pci_release_regions(pdev);
71763461a02SJakub Kicinski err_pci_disable:
71863461a02SJakub Kicinski 	pci_disable_device(pdev);
71963461a02SJakub Kicinski 
72063461a02SJakub Kicinski 	return err;
72163461a02SJakub Kicinski }
72263461a02SJakub Kicinski 
72363461a02SJakub Kicinski static void nfp_pci_remove(struct pci_dev *pdev)
72463461a02SJakub Kicinski {
72563461a02SJakub Kicinski 	struct nfp_pf *pf = pci_get_drvdata(pdev);
7261851f93fSSimon Horman 
727eefbde7eSDavid Brunecz 	nfp_hwmon_unregister(pf);
728eefbde7eSDavid Brunecz 
72963461a02SJakub Kicinski 	nfp_pcie_sriov_disable(pdev);
73063461a02SJakub Kicinski 
731bcc93a23SJakub Kicinski 	nfp_net_pci_remove(pf);
7321851f93fSSimon Horman 
733d79e19f5SCarl Heymann 	vfree(pf->dumpspec);
734af4fa7eaSJakub Kicinski 	kfree(pf->rtbl);
7350be40e66SJakub Kicinski 	nfp_mip_close(pf->mip);
73663461a02SJakub Kicinski 	if (pf->fw_loaded)
73763461a02SJakub Kicinski 		nfp_fw_unload(pf);
73863461a02SJakub Kicinski 
7396d48ceb2SJakub Kicinski 	destroy_workqueue(pf->wq);
74063461a02SJakub Kicinski 	pci_set_drvdata(pdev, NULL);
7419baa4885SJakub Kicinski 	kfree(pf->hwinfo);
74263461a02SJakub Kicinski 	nfp_cpp_free(pf->cpp);
74363461a02SJakub Kicinski 
74463461a02SJakub Kicinski 	kfree(pf->eth_tbl);
745eefbde7eSDavid Brunecz 	kfree(pf->nspi);
746346cfe84SJakub Kicinski 	mutex_destroy(&pf->lock);
747bcc93a23SJakub Kicinski 	devlink_free(priv_to_devlink(pf));
74863461a02SJakub Kicinski 	pci_release_regions(pdev);
74963461a02SJakub Kicinski 	pci_disable_device(pdev);
75063461a02SJakub Kicinski }
75163461a02SJakub Kicinski 
75263461a02SJakub Kicinski static struct pci_driver nfp_pci_driver = {
75363461a02SJakub Kicinski 	.name			= nfp_driver_name,
75463461a02SJakub Kicinski 	.id_table		= nfp_pci_device_ids,
75563461a02SJakub Kicinski 	.probe			= nfp_pci_probe,
75663461a02SJakub Kicinski 	.remove			= nfp_pci_remove,
75763461a02SJakub Kicinski 	.sriov_configure	= nfp_pcie_sriov_configure,
75863461a02SJakub Kicinski };
75963461a02SJakub Kicinski 
7602633beb9SJakub Kicinski static int __init nfp_main_init(void)
7612633beb9SJakub Kicinski {
7622633beb9SJakub Kicinski 	int err;
7632633beb9SJakub Kicinski 
7642633beb9SJakub Kicinski 	pr_info("%s: NFP PCIe Driver, Copyright (C) 2014-2017 Netronome Systems\n",
7652633beb9SJakub Kicinski 		nfp_driver_name);
7662633beb9SJakub Kicinski 
7672633beb9SJakub Kicinski 	nfp_net_debugfs_create();
7682633beb9SJakub Kicinski 
76963461a02SJakub Kicinski 	err = pci_register_driver(&nfp_pci_driver);
77063461a02SJakub Kicinski 	if (err < 0)
77163461a02SJakub Kicinski 		goto err_destroy_debugfs;
77263461a02SJakub Kicinski 
7732633beb9SJakub Kicinski 	err = pci_register_driver(&nfp_netvf_pci_driver);
7742633beb9SJakub Kicinski 	if (err)
77563461a02SJakub Kicinski 		goto err_unreg_pf;
7762633beb9SJakub Kicinski 
7772633beb9SJakub Kicinski 	return err;
7782633beb9SJakub Kicinski 
77963461a02SJakub Kicinski err_unreg_pf:
78063461a02SJakub Kicinski 	pci_unregister_driver(&nfp_pci_driver);
7812633beb9SJakub Kicinski err_destroy_debugfs:
7822633beb9SJakub Kicinski 	nfp_net_debugfs_destroy();
7832633beb9SJakub Kicinski 	return err;
7842633beb9SJakub Kicinski }
7852633beb9SJakub Kicinski 
7862633beb9SJakub Kicinski static void __exit nfp_main_exit(void)
7872633beb9SJakub Kicinski {
7882633beb9SJakub Kicinski 	pci_unregister_driver(&nfp_netvf_pci_driver);
78963461a02SJakub Kicinski 	pci_unregister_driver(&nfp_pci_driver);
7902633beb9SJakub Kicinski 	nfp_net_debugfs_destroy();
7912633beb9SJakub Kicinski }
7922633beb9SJakub Kicinski 
7932633beb9SJakub Kicinski module_init(nfp_main_init);
7942633beb9SJakub Kicinski module_exit(nfp_main_exit);
7952633beb9SJakub Kicinski 
79663461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_1x40.nffw");
79763461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_4x10.nffw");
79863461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0096-0001_2x10.nffw");
79963461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_2x40.nffw");
80063461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_4x10_1x40.nffw");
80163461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_8x10.nffw");
80263461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x10.nffw");
80363461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x25.nffw");
80470271dadSDirk van der Merwe MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_1x10_1x25.nffw");
80563461a02SJakub Kicinski 
8062633beb9SJakub Kicinski MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
8072633beb9SJakub Kicinski MODULE_LICENSE("GPL");
8082633beb9SJakub Kicinski MODULE_DESCRIPTION("The Netronome Flow Processor (NFP) driver.");
8091a5e8e35SJakub Kicinski MODULE_VERSION(UTS_RELEASE);
810