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>
17d79e19f5SCarl Heymann #include <linux/vmalloc.h>
181851f93fSSimon Horman #include <net/devlink.h>
192633beb9SJakub Kicinski 
2063461a02SJakub Kicinski #include "nfpcore/nfp.h"
2163461a02SJakub Kicinski #include "nfpcore/nfp_cpp.h"
220bc3827fSJakub Kicinski #include "nfpcore/nfp_nffw.h"
23ce22f5a2SJakub Kicinski #include "nfpcore/nfp_nsp.h"
2463461a02SJakub Kicinski 
2563461a02SJakub Kicinski #include "nfpcore/nfp6000_pcie.h"
2663461a02SJakub Kicinski 
270c693323SJakub Kicinski #include "nfp_abi.h"
28758238f2SSimon Horman #include "nfp_app.h"
292633beb9SJakub Kicinski #include "nfp_main.h"
302633beb9SJakub Kicinski #include "nfp_net.h"
312633beb9SJakub Kicinski 
322633beb9SJakub Kicinski static const char nfp_driver_name[] = "nfp";
332633beb9SJakub Kicinski 
3463461a02SJakub Kicinski static const struct pci_device_id nfp_pci_device_ids[] = {
353b473528SSimon Horman 	{ PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000,
3663461a02SJakub Kicinski 	  PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
3763461a02SJakub Kicinski 	  PCI_ANY_ID, 0,
3863461a02SJakub Kicinski 	},
390377505cSJakub Kicinski 	{ PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP5000,
400377505cSJakub Kicinski 	  PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
410377505cSJakub Kicinski 	  PCI_ANY_ID, 0,
420377505cSJakub Kicinski 	},
433b473528SSimon Horman 	{ PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP4000,
4463461a02SJakub Kicinski 	  PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
4563461a02SJakub Kicinski 	  PCI_ANY_ID, 0,
4663461a02SJakub Kicinski 	},
4763461a02SJakub Kicinski 	{ 0, } /* Required last entry. */
4863461a02SJakub Kicinski };
4963461a02SJakub Kicinski MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids);
5063461a02SJakub Kicinski 
518f6196f6SJakub Kicinski int nfp_pf_rtsym_read_optional(struct nfp_pf *pf, const char *format,
528f6196f6SJakub Kicinski 			       unsigned int default_val)
538f6196f6SJakub Kicinski {
548f6196f6SJakub Kicinski 	char name[256];
558f6196f6SJakub Kicinski 	int err = 0;
568f6196f6SJakub Kicinski 	u64 val;
578f6196f6SJakub Kicinski 
588f6196f6SJakub Kicinski 	snprintf(name, sizeof(name), format, nfp_cppcore_pcie_unit(pf->cpp));
598f6196f6SJakub Kicinski 
608f6196f6SJakub Kicinski 	val = nfp_rtsym_read_le(pf->rtbl, name, &err);
618f6196f6SJakub Kicinski 	if (err) {
628f6196f6SJakub Kicinski 		if (err == -ENOENT)
638f6196f6SJakub Kicinski 			return default_val;
648f6196f6SJakub Kicinski 		nfp_err(pf->cpp, "Unable to read symbol %s\n", name);
658f6196f6SJakub Kicinski 		return err;
668f6196f6SJakub Kicinski 	}
678f6196f6SJakub Kicinski 
688f6196f6SJakub Kicinski 	return val;
698f6196f6SJakub Kicinski }
708f6196f6SJakub Kicinski 
718f6196f6SJakub Kicinski u8 __iomem *
728f6196f6SJakub Kicinski nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
738f6196f6SJakub Kicinski 		 unsigned int min_size, struct nfp_cpp_area **area)
748f6196f6SJakub Kicinski {
758f6196f6SJakub Kicinski 	char pf_symbol[256];
768f6196f6SJakub Kicinski 
778f6196f6SJakub Kicinski 	snprintf(pf_symbol, sizeof(pf_symbol), sym_fmt,
788f6196f6SJakub Kicinski 		 nfp_cppcore_pcie_unit(pf->cpp));
798f6196f6SJakub Kicinski 
808f6196f6SJakub Kicinski 	return nfp_rtsym_map(pf->rtbl, pf_symbol, name, min_size, area);
818f6196f6SJakub Kicinski }
828f6196f6SJakub Kicinski 
830c693323SJakub Kicinski /* Callers should hold the devlink instance lock */
840c693323SJakub Kicinski int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
850c693323SJakub Kicinski 		 void *out_data, u64 out_length)
860c693323SJakub Kicinski {
870c693323SJakub Kicinski 	unsigned long err_at;
880c693323SJakub Kicinski 	u64 max_data_sz;
890c693323SJakub Kicinski 	u32 val = 0;
900c693323SJakub Kicinski 	int n, err;
910c693323SJakub Kicinski 
920c693323SJakub Kicinski 	if (!pf->mbox)
930c693323SJakub Kicinski 		return -EOPNOTSUPP;
940c693323SJakub Kicinski 
954152e58cSJakub Kicinski 	max_data_sz = nfp_rtsym_size(pf->mbox) - NFP_MBOX_SYM_MIN_SIZE;
960c693323SJakub Kicinski 
970c693323SJakub Kicinski 	/* Check if cmd field is clear */
981240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
990c693323SJakub Kicinski 	if (err || val) {
1000c693323SJakub Kicinski 		nfp_warn(pf->cpp, "failed to issue command (%u): %u, err: %d\n",
1010c693323SJakub Kicinski 			 cmd, val, err);
1020c693323SJakub Kicinski 		return err ?: -EBUSY;
1030c693323SJakub Kicinski 	}
1040c693323SJakub Kicinski 
1050c693323SJakub Kicinski 	in_length = min(in_length, max_data_sz);
1061240989cSJakub Kicinski 	n = nfp_rtsym_write(pf->cpp, pf->mbox, NFP_MBOX_DATA, in_data,
1071240989cSJakub Kicinski 			    in_length);
1080c693323SJakub Kicinski 	if (n != in_length)
1090c693323SJakub Kicinski 		return -EIO;
1100c693323SJakub Kicinski 	/* Write data_len and wipe reserved */
1111240989cSJakub Kicinski 	err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, in_length);
1120c693323SJakub Kicinski 	if (err)
1130c693323SJakub Kicinski 		return err;
1140c693323SJakub Kicinski 
1150c693323SJakub Kicinski 	/* Read back for ordering */
1161240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val);
1170c693323SJakub Kicinski 	if (err)
1180c693323SJakub Kicinski 		return err;
1190c693323SJakub Kicinski 
1200c693323SJakub Kicinski 	/* Write cmd and wipe return value */
1211240989cSJakub Kicinski 	err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_CMD, cmd);
1220c693323SJakub Kicinski 	if (err)
1230c693323SJakub Kicinski 		return err;
1240c693323SJakub Kicinski 
1250c693323SJakub Kicinski 	err_at = jiffies + 5 * HZ;
1260c693323SJakub Kicinski 	while (true) {
1270c693323SJakub Kicinski 		/* Wait for command to go to 0 (NFP_MBOX_NO_CMD) */
1281240989cSJakub Kicinski 		err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val);
1290c693323SJakub Kicinski 		if (err)
1300c693323SJakub Kicinski 			return err;
1310c693323SJakub Kicinski 		if (!val)
1320c693323SJakub Kicinski 			break;
1330c693323SJakub Kicinski 
1340c693323SJakub Kicinski 		if (time_is_before_eq_jiffies(err_at))
1350c693323SJakub Kicinski 			return -ETIMEDOUT;
1360c693323SJakub Kicinski 
1370c693323SJakub Kicinski 		msleep(5);
1380c693323SJakub Kicinski 	}
1390c693323SJakub Kicinski 
1400c693323SJakub Kicinski 	/* Copy output if any (could be error info, do it before reading ret) */
1411240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val);
1420c693323SJakub Kicinski 	if (err)
1430c693323SJakub Kicinski 		return err;
1440c693323SJakub Kicinski 
1450c693323SJakub Kicinski 	out_length = min_t(u32, val, min(out_length, max_data_sz));
1461240989cSJakub Kicinski 	n = nfp_rtsym_read(pf->cpp, pf->mbox, NFP_MBOX_DATA,
1470c693323SJakub Kicinski 			   out_data, out_length);
1480c693323SJakub Kicinski 	if (n != out_length)
1490c693323SJakub Kicinski 		return -EIO;
1500c693323SJakub Kicinski 
1510c693323SJakub Kicinski 	/* Check if there is an error */
1521240989cSJakub Kicinski 	err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_RET, &val);
1530c693323SJakub Kicinski 	if (err)
1540c693323SJakub Kicinski 		return err;
1550c693323SJakub Kicinski 	if (val)
1560c693323SJakub Kicinski 		return -val;
1570c693323SJakub Kicinski 
1580c693323SJakub Kicinski 	return out_length;
1590c693323SJakub Kicinski }
1600c693323SJakub Kicinski 
1614cbe94f2SJakub Kicinski static bool nfp_board_ready(struct nfp_pf *pf)
1624cbe94f2SJakub Kicinski {
1634cbe94f2SJakub Kicinski 	const char *cp;
1644cbe94f2SJakub Kicinski 	long state;
1654cbe94f2SJakub Kicinski 	int err;
1664cbe94f2SJakub Kicinski 
1674cbe94f2SJakub Kicinski 	cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
1684cbe94f2SJakub Kicinski 	if (!cp)
1694cbe94f2SJakub Kicinski 		return false;
1704cbe94f2SJakub Kicinski 
1714cbe94f2SJakub Kicinski 	err = kstrtol(cp, 0, &state);
1724cbe94f2SJakub Kicinski 	if (err < 0)
1734cbe94f2SJakub Kicinski 		return false;
1744cbe94f2SJakub Kicinski 
1754cbe94f2SJakub Kicinski 	return state == 15;
1764cbe94f2SJakub Kicinski }
1774cbe94f2SJakub Kicinski 
1784cbe94f2SJakub Kicinski static int nfp_pf_board_state_wait(struct nfp_pf *pf)
1794cbe94f2SJakub Kicinski {
1804cbe94f2SJakub Kicinski 	const unsigned long wait_until = jiffies + 10 * HZ;
1814cbe94f2SJakub Kicinski 
1824cbe94f2SJakub Kicinski 	while (!nfp_board_ready(pf)) {
1834cbe94f2SJakub Kicinski 		if (time_is_before_eq_jiffies(wait_until)) {
1844cbe94f2SJakub Kicinski 			nfp_err(pf->cpp, "NFP board initialization timeout\n");
1854cbe94f2SJakub Kicinski 			return -EINVAL;
1864cbe94f2SJakub Kicinski 		}
1874cbe94f2SJakub Kicinski 
1884cbe94f2SJakub Kicinski 		nfp_info(pf->cpp, "waiting for board initialization\n");
1894cbe94f2SJakub Kicinski 		if (msleep_interruptible(500))
1904cbe94f2SJakub Kicinski 			return -ERESTARTSYS;
1914cbe94f2SJakub Kicinski 
1924cbe94f2SJakub Kicinski 		/* Refresh cached information */
1934cbe94f2SJakub Kicinski 		kfree(pf->hwinfo);
1944cbe94f2SJakub Kicinski 		pf->hwinfo = nfp_hwinfo_read(pf->cpp);
1954cbe94f2SJakub Kicinski 	}
1964cbe94f2SJakub Kicinski 
1974cbe94f2SJakub Kicinski 	return 0;
1984cbe94f2SJakub Kicinski }
1994cbe94f2SJakub Kicinski 
200651e1f2fSJakub Kicinski static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
2010bc3827fSJakub Kicinski {
2020bc3827fSJakub Kicinski 	int err;
2030bc3827fSJakub Kicinski 
204af4fa7eaSJakub Kicinski 	pf->limit_vfs = nfp_rtsym_read_le(pf->rtbl, "nfd_vf_cfg_max_vfs", &err);
2055b0ced17SJakub Kicinski 	if (err) {
2065b0ced17SJakub Kicinski 		/* For backwards compatibility if symbol not found allow all */
2070bc3827fSJakub Kicinski 		pf->limit_vfs = ~0;
208651e1f2fSJakub Kicinski 		if (err == -ENOENT)
209651e1f2fSJakub Kicinski 			return 0;
210651e1f2fSJakub Kicinski 
2110bc3827fSJakub Kicinski 		nfp_warn(pf->cpp, "Warning: VF limit read failed: %d\n", err);
212651e1f2fSJakub Kicinski 		return err;
2130bc3827fSJakub Kicinski 	}
2140bc3827fSJakub Kicinski 
2155b0ced17SJakub Kicinski 	err = pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
2165b0ced17SJakub Kicinski 	if (err)
2175b0ced17SJakub Kicinski 		nfp_warn(pf->cpp, "Failed to set VF count in sysfs: %d\n", err);
2185b0ced17SJakub Kicinski 	return 0;
2195b0ced17SJakub Kicinski }
2205b0ced17SJakub Kicinski 
22163461a02SJakub Kicinski static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs)
22263461a02SJakub Kicinski {
22363461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV
22463461a02SJakub Kicinski 	struct nfp_pf *pf = pci_get_drvdata(pdev);
22563461a02SJakub Kicinski 	int err;
22663461a02SJakub Kicinski 
2270bc3827fSJakub Kicinski 	if (num_vfs > pf->limit_vfs) {
2280bc3827fSJakub Kicinski 		nfp_info(pf->cpp, "Firmware limits number of VFs to %u\n",
2290bc3827fSJakub Kicinski 			 pf->limit_vfs);
230d6e1ab9eSJakub Kicinski 		return -EINVAL;
231758238f2SSimon Horman 	}
232758238f2SSimon Horman 
233e3f28473SJakub Kicinski 	err = pci_enable_sriov(pdev, num_vfs);
234758238f2SSimon Horman 	if (err) {
235e3f28473SJakub Kicinski 		dev_warn(&pdev->dev, "Failed to enable PCI SR-IOV: %d\n", err);
236d6e1ab9eSJakub Kicinski 		return err;
2370bc3827fSJakub Kicinski 	}
2380bc3827fSJakub Kicinski 
239d6e1ab9eSJakub Kicinski 	mutex_lock(&pf->lock);
240d6e1ab9eSJakub Kicinski 
241e3f28473SJakub Kicinski 	err = nfp_app_sriov_enable(pf->app, num_vfs);
24263461a02SJakub Kicinski 	if (err) {
243e3f28473SJakub Kicinski 		dev_warn(&pdev->dev,
244e3f28473SJakub Kicinski 			 "App specific PCI SR-IOV configuration failed: %d\n",
245e3f28473SJakub Kicinski 			 err);
246e3f28473SJakub Kicinski 		goto err_sriov_disable;
24763461a02SJakub Kicinski 	}
24863461a02SJakub Kicinski 
24963461a02SJakub Kicinski 	pf->num_vfs = num_vfs;
25063461a02SJakub Kicinski 
25163461a02SJakub Kicinski 	dev_dbg(&pdev->dev, "Created %d VFs.\n", pf->num_vfs);
25263461a02SJakub Kicinski 
253758238f2SSimon Horman 	mutex_unlock(&pf->lock);
25463461a02SJakub Kicinski 	return num_vfs;
255758238f2SSimon Horman 
256e3f28473SJakub Kicinski err_sriov_disable:
257758238f2SSimon Horman 	mutex_unlock(&pf->lock);
258d6e1ab9eSJakub Kicinski 	pci_disable_sriov(pdev);
259758238f2SSimon Horman 	return err;
26063461a02SJakub Kicinski #endif
26163461a02SJakub Kicinski 	return 0;
26263461a02SJakub Kicinski }
26363461a02SJakub Kicinski 
264e3f28473SJakub Kicinski static int nfp_pcie_sriov_disable(struct pci_dev *pdev)
26563461a02SJakub Kicinski {
26663461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV
26763461a02SJakub Kicinski 	struct nfp_pf *pf = pci_get_drvdata(pdev);
26863461a02SJakub Kicinski 
269e3f28473SJakub Kicinski 	mutex_lock(&pf->lock);
270e3f28473SJakub Kicinski 
27163461a02SJakub Kicinski 	/* If the VFs are assigned we cannot shut down SR-IOV without
27263461a02SJakub Kicinski 	 * causing issues, so just leave the hardware available but
27363461a02SJakub Kicinski 	 * disabled
27463461a02SJakub Kicinski 	 */
27563461a02SJakub Kicinski 	if (pci_vfs_assigned(pdev)) {
27663461a02SJakub Kicinski 		dev_warn(&pdev->dev, "Disabling while VFs assigned - VFs will not be deallocated\n");
277e3f28473SJakub Kicinski 		mutex_unlock(&pf->lock);
27863461a02SJakub Kicinski 		return -EPERM;
27963461a02SJakub Kicinski 	}
28063461a02SJakub Kicinski 
281758238f2SSimon Horman 	nfp_app_sriov_disable(pf->app);
282758238f2SSimon Horman 
28363461a02SJakub Kicinski 	pf->num_vfs = 0;
28463461a02SJakub Kicinski 
285d6e1ab9eSJakub Kicinski 	mutex_unlock(&pf->lock);
286d6e1ab9eSJakub Kicinski 
28763461a02SJakub Kicinski 	pci_disable_sriov(pdev);
28863461a02SJakub Kicinski 	dev_dbg(&pdev->dev, "Removed VFs.\n");
28963461a02SJakub Kicinski #endif
29063461a02SJakub Kicinski 	return 0;
29163461a02SJakub Kicinski }
29263461a02SJakub Kicinski 
29363461a02SJakub Kicinski static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs)
29463461a02SJakub Kicinski {
295790d23e7SDirk van der Merwe 	if (!pci_get_drvdata(pdev))
296790d23e7SDirk van der Merwe 		return -ENOENT;
297790d23e7SDirk van der Merwe 
29863461a02SJakub Kicinski 	if (num_vfs == 0)
29963461a02SJakub Kicinski 		return nfp_pcie_sriov_disable(pdev);
30063461a02SJakub Kicinski 	else
30163461a02SJakub Kicinski 		return nfp_pcie_sriov_enable(pdev, num_vfs);
30263461a02SJakub Kicinski }
30363461a02SJakub Kicinski 
304*b44cfd4fSJacob Keller int nfp_flash_update_common(struct nfp_pf *pf, const struct firmware *fw,
3055c5696f3SJakub Kicinski 			    struct netlink_ext_ack *extack)
3065c5696f3SJakub Kicinski {
3075c5696f3SJakub Kicinski 	struct device *dev = &pf->pdev->dev;
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 = nfp_nsp_write_flash(nsp, fw);
3225c5696f3SJakub Kicinski 	if (err < 0)
323*b44cfd4fSJacob Keller 		goto exit_close_nsp;
3245c5696f3SJakub Kicinski 	dev_info(dev, "Finished writing flash image\n");
3255c5696f3SJakub Kicinski 	err = 0;
3265c5696f3SJakub Kicinski 
3275c5696f3SJakub Kicinski exit_close_nsp:
3285c5696f3SJakub Kicinski 	nfp_nsp_close(nsp);
3295c5696f3SJakub Kicinski 	return err;
3305c5696f3SJakub Kicinski }
3315c5696f3SJakub Kicinski 
3321680a370SJakub Kicinski static const struct firmware *
3331680a370SJakub Kicinski nfp_net_fw_request(struct pci_dev *pdev, struct nfp_pf *pf, const char *name)
3341680a370SJakub Kicinski {
3351680a370SJakub Kicinski 	const struct firmware *fw = NULL;
3361680a370SJakub Kicinski 	int err;
3371680a370SJakub Kicinski 
3381680a370SJakub Kicinski 	err = request_firmware_direct(&fw, name, &pdev->dev);
3391680a370SJakub Kicinski 	nfp_info(pf->cpp, "  %s: %s\n",
340f8921d73SDirk van der Merwe 		 name, err ? "not found" : "found");
3411680a370SJakub Kicinski 	if (err)
3421680a370SJakub Kicinski 		return NULL;
3431680a370SJakub Kicinski 
3441680a370SJakub Kicinski 	return fw;
3451680a370SJakub Kicinski }
3461680a370SJakub Kicinski 
34763461a02SJakub Kicinski /**
34863461a02SJakub Kicinski  * nfp_net_fw_find() - Find the correct firmware image for netdev mode
34963461a02SJakub Kicinski  * @pdev:	PCI Device structure
35063461a02SJakub Kicinski  * @pf:		NFP PF Device structure
35163461a02SJakub Kicinski  *
35263461a02SJakub Kicinski  * Return: firmware if found and requested successfully.
35363461a02SJakub Kicinski  */
35463461a02SJakub Kicinski static const struct firmware *
35563461a02SJakub Kicinski nfp_net_fw_find(struct pci_dev *pdev, struct nfp_pf *pf)
35663461a02SJakub Kicinski {
35763461a02SJakub Kicinski 	struct nfp_eth_table_port *port;
3581680a370SJakub Kicinski 	const struct firmware *fw;
35963461a02SJakub Kicinski 	const char *fw_model;
36063461a02SJakub Kicinski 	char fw_name[256];
3619511f298SJakub Kicinski 	const u8 *serial;
3629511f298SJakub Kicinski 	u16 interface;
3631680a370SJakub Kicinski 	int spc, i, j;
3641680a370SJakub Kicinski 
3651680a370SJakub Kicinski 	nfp_info(pf->cpp, "Looking for firmware file in order of priority:\n");
36663461a02SJakub Kicinski 
3679511f298SJakub Kicinski 	/* First try to find a firmware image specific for this device */
3689511f298SJakub Kicinski 	interface = nfp_cpp_interface(pf->cpp);
3699511f298SJakub Kicinski 	nfp_cpp_serial(pf->cpp, &serial);
3709511f298SJakub Kicinski 	sprintf(fw_name, "netronome/serial-%pMF-%02hhx-%02hhx.nffw",
3719511f298SJakub Kicinski 		serial, interface >> 8, interface & 0xff);
3721680a370SJakub Kicinski 	fw = nfp_net_fw_request(pdev, pf, fw_name);
3731680a370SJakub Kicinski 	if (fw)
3741680a370SJakub Kicinski 		return fw;
3759511f298SJakub Kicinski 
3769511f298SJakub Kicinski 	/* Then try the PCI name */
3779511f298SJakub Kicinski 	sprintf(fw_name, "netronome/pci-%s.nffw", pci_name(pdev));
3781680a370SJakub Kicinski 	fw = nfp_net_fw_request(pdev, pf, fw_name);
3791680a370SJakub Kicinski 	if (fw)
3801680a370SJakub Kicinski 		return fw;
3819511f298SJakub Kicinski 
3829511f298SJakub Kicinski 	/* Finally try the card type and media */
38363461a02SJakub Kicinski 	if (!pf->eth_tbl) {
38463461a02SJakub Kicinski 		dev_err(&pdev->dev, "Error: can't identify media config\n");
38563461a02SJakub Kicinski 		return NULL;
38663461a02SJakub Kicinski 	}
38763461a02SJakub Kicinski 
3889baa4885SJakub Kicinski 	fw_model = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
38963461a02SJakub Kicinski 	if (!fw_model) {
39063461a02SJakub Kicinski 		dev_err(&pdev->dev, "Error: can't read part number\n");
39163461a02SJakub Kicinski 		return NULL;
39263461a02SJakub Kicinski 	}
39363461a02SJakub Kicinski 
39463461a02SJakub Kicinski 	spc = ARRAY_SIZE(fw_name);
39563461a02SJakub Kicinski 	spc -= snprintf(fw_name, spc, "netronome/nic_%s", fw_model);
39663461a02SJakub Kicinski 
39763461a02SJakub Kicinski 	for (i = 0; spc > 0 && i < pf->eth_tbl->count; i += j) {
39863461a02SJakub Kicinski 		port = &pf->eth_tbl->ports[i];
39963461a02SJakub Kicinski 		j = 1;
40063461a02SJakub Kicinski 		while (i + j < pf->eth_tbl->count &&
40163461a02SJakub Kicinski 		       port->speed == port[j].speed)
40263461a02SJakub Kicinski 			j++;
40363461a02SJakub Kicinski 
40463461a02SJakub Kicinski 		spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc,
40563461a02SJakub Kicinski 				"_%dx%d", j, port->speed / 1000);
40663461a02SJakub Kicinski 	}
40763461a02SJakub Kicinski 
40863461a02SJakub Kicinski 	if (spc <= 0)
40963461a02SJakub Kicinski 		return NULL;
41063461a02SJakub Kicinski 
41163461a02SJakub Kicinski 	spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, ".nffw");
41263461a02SJakub Kicinski 	if (spc <= 0)
41363461a02SJakub Kicinski 		return NULL;
41463461a02SJakub Kicinski 
4151680a370SJakub Kicinski 	return nfp_net_fw_request(pdev, pf, fw_name);
41663461a02SJakub Kicinski }
41763461a02SJakub Kicinski 
418f8921d73SDirk van der Merwe static int
419f8921d73SDirk van der Merwe nfp_get_fw_policy_value(struct pci_dev *pdev, struct nfp_nsp *nsp,
420f8921d73SDirk van der Merwe 			const char *key, const char *default_val, int max_val,
421f8921d73SDirk van der Merwe 			int *value)
422f8921d73SDirk van der Merwe {
423f8921d73SDirk van der Merwe 	char hwinfo[64];
424f8921d73SDirk van der Merwe 	long hi_val;
425f8921d73SDirk van der Merwe 	int err;
426f8921d73SDirk van der Merwe 
427f8921d73SDirk van der Merwe 	snprintf(hwinfo, sizeof(hwinfo), key);
428f8921d73SDirk van der Merwe 	err = nfp_nsp_hwinfo_lookup_optional(nsp, hwinfo, sizeof(hwinfo),
429f8921d73SDirk van der Merwe 					     default_val);
430f8921d73SDirk van der Merwe 	if (err)
431f8921d73SDirk van der Merwe 		return err;
432f8921d73SDirk van der Merwe 
433f8921d73SDirk van der Merwe 	err = kstrtol(hwinfo, 0, &hi_val);
434f8921d73SDirk van der Merwe 	if (err || hi_val < 0 || hi_val > max_val) {
435f8921d73SDirk van der Merwe 		dev_warn(&pdev->dev,
436f8921d73SDirk van der Merwe 			 "Invalid value '%s' from '%s', ignoring\n",
437f8921d73SDirk van der Merwe 			 hwinfo, key);
438f8921d73SDirk van der Merwe 		err = kstrtol(default_val, 0, &hi_val);
439f8921d73SDirk van der Merwe 	}
440f8921d73SDirk van der Merwe 
441f8921d73SDirk van der Merwe 	*value = hi_val;
442f8921d73SDirk van der Merwe 	return err;
443f8921d73SDirk van der Merwe }
444f8921d73SDirk van der Merwe 
44563461a02SJakub Kicinski /**
4468fb822ceSDirk van der Merwe  * nfp_fw_load() - Load the firmware image
44763461a02SJakub Kicinski  * @pdev:       PCI Device structure
44863461a02SJakub Kicinski  * @pf:		NFP PF Device structure
44963461a02SJakub Kicinski  * @nsp:	NFP SP handle
45063461a02SJakub Kicinski  *
45163461a02SJakub Kicinski  * Return: -ERRNO, 0 for no firmware loaded, 1 for firmware loaded
45263461a02SJakub Kicinski  */
45363461a02SJakub Kicinski static int
45463461a02SJakub Kicinski nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp)
45563461a02SJakub Kicinski {
456f8921d73SDirk van der Merwe 	bool do_reset, fw_loaded = false;
457f8921d73SDirk van der Merwe 	const struct firmware *fw = NULL;
458f8921d73SDirk van der Merwe 	int err, reset, policy, ifcs = 0;
459f8921d73SDirk van der Merwe 	char *token, *ptr;
460f8921d73SDirk van der Merwe 	char hwinfo[64];
46163461a02SJakub Kicinski 	u16 interface;
462f8921d73SDirk van der Merwe 
463f8921d73SDirk van der Merwe 	snprintf(hwinfo, sizeof(hwinfo), "abi_drv_load_ifc");
464f8921d73SDirk van der Merwe 	err = nfp_nsp_hwinfo_lookup_optional(nsp, hwinfo, sizeof(hwinfo),
465f8921d73SDirk van der Merwe 					     NFP_NSP_DRV_LOAD_IFC_DEFAULT);
466f8921d73SDirk van der Merwe 	if (err)
467f8921d73SDirk van der Merwe 		return err;
46863461a02SJakub Kicinski 
46963461a02SJakub Kicinski 	interface = nfp_cpp_interface(pf->cpp);
470f8921d73SDirk van der Merwe 	ptr = hwinfo;
471f8921d73SDirk van der Merwe 	while ((token = strsep(&ptr, ","))) {
472f8921d73SDirk van der Merwe 		unsigned long interface_hi;
473f8921d73SDirk van der Merwe 
474f8921d73SDirk van der Merwe 		err = kstrtoul(token, 0, &interface_hi);
475f8921d73SDirk van der Merwe 		if (err) {
476f8921d73SDirk van der Merwe 			dev_err(&pdev->dev,
477f8921d73SDirk van der Merwe 				"Failed to parse interface '%s': %d\n",
478f8921d73SDirk van der Merwe 				token, err);
479f8921d73SDirk van der Merwe 			return err;
480f8921d73SDirk van der Merwe 		}
481f8921d73SDirk van der Merwe 
482f8921d73SDirk van der Merwe 		ifcs++;
483f8921d73SDirk van der Merwe 		if (interface == interface_hi)
484f8921d73SDirk van der Merwe 			break;
485f8921d73SDirk van der Merwe 	}
486f8921d73SDirk van der Merwe 
487f8921d73SDirk van der Merwe 	if (!token) {
48863461a02SJakub Kicinski 		dev_info(&pdev->dev, "Firmware will be loaded by partner\n");
48963461a02SJakub Kicinski 		return 0;
49063461a02SJakub Kicinski 	}
49163461a02SJakub Kicinski 
492f8921d73SDirk van der Merwe 	err = nfp_get_fw_policy_value(pdev, nsp, "abi_drv_reset",
493f8921d73SDirk van der Merwe 				      NFP_NSP_DRV_RESET_DEFAULT,
494f8921d73SDirk van der Merwe 				      NFP_NSP_DRV_RESET_NEVER, &reset);
495f8921d73SDirk van der Merwe 	if (err)
496f8921d73SDirk van der Merwe 		return err;
49763461a02SJakub Kicinski 
498f8921d73SDirk van der Merwe 	err = nfp_get_fw_policy_value(pdev, nsp, "app_fw_from_flash",
499f8921d73SDirk van der Merwe 				      NFP_NSP_APP_FW_LOAD_DEFAULT,
500f8921d73SDirk van der Merwe 				      NFP_NSP_APP_FW_LOAD_PREF, &policy);
501f8921d73SDirk van der Merwe 	if (err)
502f8921d73SDirk van der Merwe 		return err;
503f8921d73SDirk van der Merwe 
504f8921d73SDirk van der Merwe 	fw = nfp_net_fw_find(pdev, pf);
505f8921d73SDirk van der Merwe 	do_reset = reset == NFP_NSP_DRV_RESET_ALWAYS ||
506f8921d73SDirk van der Merwe 		   (fw && reset == NFP_NSP_DRV_RESET_DISK);
507f8921d73SDirk van der Merwe 
508f8921d73SDirk van der Merwe 	if (do_reset) {
509f8921d73SDirk van der Merwe 		dev_info(&pdev->dev, "Soft-resetting the NFP\n");
51063461a02SJakub Kicinski 		err = nfp_nsp_device_soft_reset(nsp);
51163461a02SJakub Kicinski 		if (err < 0) {
512f8921d73SDirk van der Merwe 			dev_err(&pdev->dev,
513f8921d73SDirk van der Merwe 				"Failed to soft reset the NFP: %d\n", err);
51463461a02SJakub Kicinski 			goto exit_release_fw;
51563461a02SJakub Kicinski 		}
516f8921d73SDirk van der Merwe 	}
517f8921d73SDirk van der Merwe 
518f8921d73SDirk van der Merwe 	if (fw && policy != NFP_NSP_APP_FW_LOAD_FLASH) {
519f8921d73SDirk van der Merwe 		if (nfp_nsp_has_fw_loaded(nsp) && nfp_nsp_fw_loaded(nsp))
520f8921d73SDirk van der Merwe 			goto exit_release_fw;
52163461a02SJakub Kicinski 
52263461a02SJakub Kicinski 		err = nfp_nsp_load_fw(nsp, fw);
52363461a02SJakub Kicinski 		if (err < 0) {
524f8921d73SDirk van der Merwe 			dev_err(&pdev->dev, "FW loading failed: %d\n",
525f8921d73SDirk van der Merwe 				err);
52663461a02SJakub Kicinski 			goto exit_release_fw;
52763461a02SJakub Kicinski 		}
52863461a02SJakub Kicinski 		dev_info(&pdev->dev, "Finished loading FW image\n");
529f8921d73SDirk van der Merwe 		fw_loaded = true;
530f8921d73SDirk van der Merwe 	} else if (policy != NFP_NSP_APP_FW_LOAD_DISK &&
531f8921d73SDirk van der Merwe 		   nfp_nsp_has_stored_fw_load(nsp)) {
532f8921d73SDirk van der Merwe 
533f8921d73SDirk van der Merwe 		/* Don't propagate this error to stick with legacy driver
534f8921d73SDirk van der Merwe 		 * behavior, failure will be detected later during init.
535f8921d73SDirk van der Merwe 		 */
536f8921d73SDirk van der Merwe 		if (!nfp_nsp_load_stored_fw(nsp))
537f8921d73SDirk van der Merwe 			dev_info(&pdev->dev, "Finished loading stored FW image\n");
538f8921d73SDirk van der Merwe 
539f8921d73SDirk van der Merwe 		/* Don't flag the fw_loaded in this case since other devices
540f8921d73SDirk van der Merwe 		 * may reuse the firmware when configured this way
541f8921d73SDirk van der Merwe 		 */
542f8921d73SDirk van der Merwe 	} else {
543f8921d73SDirk van der Merwe 		dev_warn(&pdev->dev, "Didn't load firmware, please update flash or reconfigure card\n");
544f8921d73SDirk van der Merwe 	}
54563461a02SJakub Kicinski 
54663461a02SJakub Kicinski exit_release_fw:
54763461a02SJakub Kicinski 	release_firmware(fw);
54863461a02SJakub Kicinski 
549f8921d73SDirk van der Merwe 	/* We don't want to unload firmware when other devices may still be
550f8921d73SDirk van der Merwe 	 * dependent on it, which could be the case if there are multiple
551f8921d73SDirk van der Merwe 	 * devices that could load firmware.
552f8921d73SDirk van der Merwe 	 */
553f8921d73SDirk van der Merwe 	if (fw_loaded && ifcs == 1)
554f8921d73SDirk van der Merwe 		pf->unload_fw_on_remove = true;
555f8921d73SDirk van der Merwe 
556f8921d73SDirk van der Merwe 	return err < 0 ? err : fw_loaded;
55763461a02SJakub Kicinski }
55863461a02SJakub Kicinski 
5597717c319SJakub Kicinski static void
5607717c319SJakub Kicinski nfp_nsp_init_ports(struct pci_dev *pdev, struct nfp_pf *pf,
5617717c319SJakub Kicinski 		   struct nfp_nsp *nsp)
5627717c319SJakub Kicinski {
5637717c319SJakub Kicinski 	bool needs_reinit = false;
5647717c319SJakub Kicinski 	int i;
5657717c319SJakub Kicinski 
5667717c319SJakub Kicinski 	pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
5677717c319SJakub Kicinski 	if (!pf->eth_tbl)
5687717c319SJakub Kicinski 		return;
5697717c319SJakub Kicinski 
5707717c319SJakub Kicinski 	if (!nfp_nsp_has_mac_reinit(nsp))
5717717c319SJakub Kicinski 		return;
5727717c319SJakub Kicinski 
5737717c319SJakub Kicinski 	for (i = 0; i < pf->eth_tbl->count; i++)
5747717c319SJakub Kicinski 		needs_reinit |= pf->eth_tbl->ports[i].override_changed;
5757717c319SJakub Kicinski 	if (!needs_reinit)
5767717c319SJakub Kicinski 		return;
5777717c319SJakub Kicinski 
5787717c319SJakub Kicinski 	kfree(pf->eth_tbl);
5797717c319SJakub Kicinski 	if (nfp_nsp_mac_reinit(nsp))
5807717c319SJakub Kicinski 		dev_warn(&pdev->dev, "MAC reinit failed\n");
5817717c319SJakub Kicinski 
5827717c319SJakub Kicinski 	pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp);
5837717c319SJakub Kicinski }
5847717c319SJakub Kicinski 
585a9c83f7bSJakub Kicinski static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf)
586a9c83f7bSJakub Kicinski {
587a9c83f7bSJakub Kicinski 	struct nfp_nsp *nsp;
588a9c83f7bSJakub Kicinski 	int err;
589a9c83f7bSJakub Kicinski 
5907dbd5b75SJakub Kicinski 	err = nfp_resource_wait(pf->cpp, NFP_RESOURCE_NSP, 30);
5917dbd5b75SJakub Kicinski 	if (err)
5927dbd5b75SJakub Kicinski 		return err;
5937dbd5b75SJakub Kicinski 
594a9c83f7bSJakub Kicinski 	nsp = nfp_nsp_open(pf->cpp);
595a9c83f7bSJakub Kicinski 	if (IS_ERR(nsp)) {
596a9c83f7bSJakub Kicinski 		err = PTR_ERR(nsp);
597a9c83f7bSJakub Kicinski 		dev_err(&pdev->dev, "Failed to access the NSP: %d\n", err);
598a9c83f7bSJakub Kicinski 		return err;
599a9c83f7bSJakub Kicinski 	}
600a9c83f7bSJakub Kicinski 
601a9c83f7bSJakub Kicinski 	err = nfp_nsp_wait(nsp);
602a9c83f7bSJakub Kicinski 	if (err < 0)
603a9c83f7bSJakub Kicinski 		goto exit_close_nsp;
604a9c83f7bSJakub Kicinski 
6057717c319SJakub Kicinski 	nfp_nsp_init_ports(pdev, pf, nsp);
606a9c83f7bSJakub Kicinski 
607eefbde7eSDavid Brunecz 	pf->nspi = __nfp_nsp_identify(nsp);
608eefbde7eSDavid Brunecz 	if (pf->nspi)
609eefbde7eSDavid Brunecz 		dev_info(&pdev->dev, "BSP: %s\n", pf->nspi->version);
610010e2f9cSDavid Brunecz 
611a9c83f7bSJakub Kicinski 	err = nfp_fw_load(pdev, pf, nsp);
612a9c83f7bSJakub Kicinski 	if (err < 0) {
61347eaa23bSJakub Kicinski 		kfree(pf->nspi);
614a9c83f7bSJakub Kicinski 		kfree(pf->eth_tbl);
615a9c83f7bSJakub Kicinski 		dev_err(&pdev->dev, "Failed to load FW\n");
616a9c83f7bSJakub Kicinski 		goto exit_close_nsp;
617a9c83f7bSJakub Kicinski 	}
618a9c83f7bSJakub Kicinski 
619a9c83f7bSJakub Kicinski 	pf->fw_loaded = !!err;
620a9c83f7bSJakub Kicinski 	err = 0;
621a9c83f7bSJakub Kicinski 
622a9c83f7bSJakub Kicinski exit_close_nsp:
623a9c83f7bSJakub Kicinski 	nfp_nsp_close(nsp);
624a9c83f7bSJakub Kicinski 
625a9c83f7bSJakub Kicinski 	return err;
626a9c83f7bSJakub Kicinski }
627a9c83f7bSJakub Kicinski 
62863461a02SJakub Kicinski static void nfp_fw_unload(struct nfp_pf *pf)
62963461a02SJakub Kicinski {
63063461a02SJakub Kicinski 	struct nfp_nsp *nsp;
63163461a02SJakub Kicinski 	int err;
63263461a02SJakub Kicinski 
63363461a02SJakub Kicinski 	nsp = nfp_nsp_open(pf->cpp);
63463461a02SJakub Kicinski 	if (IS_ERR(nsp)) {
63563461a02SJakub Kicinski 		nfp_err(pf->cpp, "Reset failed, can't open NSP\n");
63663461a02SJakub Kicinski 		return;
63763461a02SJakub Kicinski 	}
63863461a02SJakub Kicinski 
63963461a02SJakub Kicinski 	err = nfp_nsp_device_soft_reset(nsp);
64063461a02SJakub Kicinski 	if (err < 0)
64163461a02SJakub Kicinski 		dev_warn(&pf->pdev->dev, "Couldn't unload firmware: %d\n", err);
64263461a02SJakub Kicinski 	else
64363461a02SJakub Kicinski 		dev_info(&pf->pdev->dev, "Firmware safely unloaded\n");
64463461a02SJakub Kicinski 
64563461a02SJakub Kicinski 	nfp_nsp_close(nsp);
64663461a02SJakub Kicinski }
64763461a02SJakub Kicinski 
6480c693323SJakub Kicinski static int nfp_pf_find_rtsyms(struct nfp_pf *pf)
6490c693323SJakub Kicinski {
6500c693323SJakub Kicinski 	char pf_symbol[256];
6510c693323SJakub Kicinski 	unsigned int pf_id;
6520c693323SJakub Kicinski 
6530c693323SJakub Kicinski 	pf_id = nfp_cppcore_pcie_unit(pf->cpp);
6540c693323SJakub Kicinski 
6550c693323SJakub Kicinski 	/* Optional per-PCI PF mailbox */
6560c693323SJakub Kicinski 	snprintf(pf_symbol, sizeof(pf_symbol), NFP_MBOX_SYM_NAME, pf_id);
6570c693323SJakub Kicinski 	pf->mbox = nfp_rtsym_lookup(pf->rtbl, pf_symbol);
6584152e58cSJakub Kicinski 	if (pf->mbox && nfp_rtsym_size(pf->mbox) < NFP_MBOX_SYM_MIN_SIZE) {
6590c693323SJakub Kicinski 		nfp_err(pf->cpp, "PF mailbox symbol too small: %llu < %d\n",
6604152e58cSJakub Kicinski 			nfp_rtsym_size(pf->mbox), NFP_MBOX_SYM_MIN_SIZE);
6610c693323SJakub Kicinski 		return -EINVAL;
6620c693323SJakub Kicinski 	}
6630c693323SJakub Kicinski 
6640c693323SJakub Kicinski 	return 0;
6650c693323SJakub Kicinski }
6660c693323SJakub Kicinski 
66763461a02SJakub Kicinski static int nfp_pci_probe(struct pci_dev *pdev,
66863461a02SJakub Kicinski 			 const struct pci_device_id *pci_id)
66963461a02SJakub Kicinski {
6701851f93fSSimon Horman 	struct devlink *devlink;
67163461a02SJakub Kicinski 	struct nfp_pf *pf;
67263461a02SJakub Kicinski 	int err;
67363461a02SJakub Kicinski 
674f767fc66SJakub Kicinski 	if (pdev->vendor == PCI_VENDOR_ID_NETRONOME &&
675f767fc66SJakub Kicinski 	    pdev->device == PCI_DEVICE_ID_NETRONOME_NFP6000_VF)
676f767fc66SJakub Kicinski 		dev_warn(&pdev->dev, "Binding NFP VF device to the NFP PF driver, the VF driver is called 'nfp_netvf'\n");
677f767fc66SJakub Kicinski 
67863461a02SJakub Kicinski 	err = pci_enable_device(pdev);
67963461a02SJakub Kicinski 	if (err < 0)
68063461a02SJakub Kicinski 		return err;
68163461a02SJakub Kicinski 
68263461a02SJakub Kicinski 	pci_set_master(pdev);
68363461a02SJakub Kicinski 
68463461a02SJakub Kicinski 	err = dma_set_mask_and_coherent(&pdev->dev,
68563461a02SJakub Kicinski 					DMA_BIT_MASK(NFP_NET_MAX_DMA_BITS));
68663461a02SJakub Kicinski 	if (err)
68763461a02SJakub Kicinski 		goto err_pci_disable;
68863461a02SJakub Kicinski 
68963461a02SJakub Kicinski 	err = pci_request_regions(pdev, nfp_driver_name);
69063461a02SJakub Kicinski 	if (err < 0) {
69163461a02SJakub Kicinski 		dev_err(&pdev->dev, "Unable to reserve pci resources.\n");
69263461a02SJakub Kicinski 		goto err_pci_disable;
69363461a02SJakub Kicinski 	}
69463461a02SJakub Kicinski 
6951851f93fSSimon Horman 	devlink = devlink_alloc(&nfp_devlink_ops, sizeof(*pf));
6961851f93fSSimon Horman 	if (!devlink) {
69763461a02SJakub Kicinski 		err = -ENOMEM;
69863461a02SJakub Kicinski 		goto err_rel_regions;
69963461a02SJakub Kicinski 	}
7001851f93fSSimon Horman 	pf = devlink_priv(devlink);
701d4e7f092SJakub Kicinski 	INIT_LIST_HEAD(&pf->vnics);
7023eb3b74aSJakub Kicinski 	INIT_LIST_HEAD(&pf->ports);
703346cfe84SJakub Kicinski 	mutex_init(&pf->lock);
70463461a02SJakub Kicinski 	pci_set_drvdata(pdev, pf);
70563461a02SJakub Kicinski 	pf->pdev = pdev;
70663461a02SJakub Kicinski 
7076d48ceb2SJakub Kicinski 	pf->wq = alloc_workqueue("nfp-%s", 0, 2, pci_name(pdev));
7086d48ceb2SJakub Kicinski 	if (!pf->wq) {
7096d48ceb2SJakub Kicinski 		err = -ENOMEM;
7106d48ceb2SJakub Kicinski 		goto err_pci_priv_unset;
7116d48ceb2SJakub Kicinski 	}
7126d48ceb2SJakub Kicinski 
71363461a02SJakub Kicinski 	pf->cpp = nfp_cpp_from_nfp6000_pcie(pdev);
71495530a59SYueHaibing 	if (IS_ERR(pf->cpp)) {
71563461a02SJakub Kicinski 		err = PTR_ERR(pf->cpp);
71663461a02SJakub Kicinski 		goto err_disable_msix;
71763461a02SJakub Kicinski 	}
71863461a02SJakub Kicinski 
7193e3e9fd8SJakub Kicinski 	err = nfp_resource_table_init(pf->cpp);
7203e3e9fd8SJakub Kicinski 	if (err)
7213e3e9fd8SJakub Kicinski 		goto err_cpp_free;
7223e3e9fd8SJakub Kicinski 
7239baa4885SJakub Kicinski 	pf->hwinfo = nfp_hwinfo_read(pf->cpp);
7249baa4885SJakub Kicinski 
72564db09edSJakub Kicinski 	dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n",
7269baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"),
7279baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"),
7289baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"),
7299baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"),
7309baa4885SJakub Kicinski 		 nfp_hwinfo_lookup(pf->hwinfo, "cpld.version"));
73164db09edSJakub Kicinski 
7324cbe94f2SJakub Kicinski 	err = nfp_pf_board_state_wait(pf);
7334cbe94f2SJakub Kicinski 	if (err)
7344cbe94f2SJakub Kicinski 		goto err_hwinfo_free;
7354cbe94f2SJakub Kicinski 
7361851f93fSSimon Horman 	err = nfp_nsp_init(pdev, pf);
7371851f93fSSimon Horman 	if (err)
738bcc93a23SJakub Kicinski 		goto err_hwinfo_free;
7391851f93fSSimon Horman 
7400be40e66SJakub Kicinski 	pf->mip = nfp_mip_open(pf->cpp);
7410be40e66SJakub Kicinski 	pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip);
742af4fa7eaSJakub Kicinski 
7430c693323SJakub Kicinski 	err = nfp_pf_find_rtsyms(pf);
7440c693323SJakub Kicinski 	if (err)
7450c693323SJakub Kicinski 		goto err_fw_unload;
7460c693323SJakub Kicinski 
747d79e19f5SCarl Heymann 	pf->dump_flag = NFP_DUMP_NSP_DIAG;
748d79e19f5SCarl Heymann 	pf->dumpspec = nfp_net_dump_load_dumpspec(pf->cpp, pf->rtbl);
749d79e19f5SCarl Heymann 
750651e1f2fSJakub Kicinski 	err = nfp_pcie_sriov_read_nfd_limit(pf);
75163461a02SJakub Kicinski 	if (err)
75263461a02SJakub Kicinski 		goto err_fw_unload;
75363461a02SJakub Kicinski 
7540dc78621SJakub Kicinski 	pf->num_vfs = pci_num_vf(pdev);
7550dc78621SJakub Kicinski 	if (pf->num_vfs > pf->limit_vfs) {
7560dc78621SJakub Kicinski 		dev_err(&pdev->dev,
7570dc78621SJakub Kicinski 			"Error: %d VFs already enabled, but loaded FW can only support %d\n",
7580dc78621SJakub Kicinski 			pf->num_vfs, pf->limit_vfs);
759e58decc9SWei Yongjun 		err = -EINVAL;
7600dc78621SJakub Kicinski 		goto err_fw_unload;
7610dc78621SJakub Kicinski 	}
7620dc78621SJakub Kicinski 
763651e1f2fSJakub Kicinski 	err = nfp_net_pci_probe(pf);
764651e1f2fSJakub Kicinski 	if (err)
76583235822SJakub Kicinski 		goto err_fw_unload;
766651e1f2fSJakub Kicinski 
767eefbde7eSDavid Brunecz 	err = nfp_hwmon_register(pf);
768eefbde7eSDavid Brunecz 	if (err) {
769eefbde7eSDavid Brunecz 		dev_err(&pdev->dev, "Failed to register hwmon info\n");
770eefbde7eSDavid Brunecz 		goto err_net_remove;
771eefbde7eSDavid Brunecz 	}
772eefbde7eSDavid Brunecz 
77363461a02SJakub Kicinski 	return 0;
77463461a02SJakub Kicinski 
775eefbde7eSDavid Brunecz err_net_remove:
776eefbde7eSDavid Brunecz 	nfp_net_pci_remove(pf);
77763461a02SJakub Kicinski err_fw_unload:
778af4fa7eaSJakub Kicinski 	kfree(pf->rtbl);
7790be40e66SJakub Kicinski 	nfp_mip_close(pf->mip);
780f8921d73SDirk van der Merwe 	if (pf->unload_fw_on_remove)
78163461a02SJakub Kicinski 		nfp_fw_unload(pf);
78263461a02SJakub Kicinski 	kfree(pf->eth_tbl);
783eefbde7eSDavid Brunecz 	kfree(pf->nspi);
784d79e19f5SCarl Heymann 	vfree(pf->dumpspec);
7859baa4885SJakub Kicinski err_hwinfo_free:
7869baa4885SJakub Kicinski 	kfree(pf->hwinfo);
7873e3e9fd8SJakub Kicinski err_cpp_free:
78863461a02SJakub Kicinski 	nfp_cpp_free(pf->cpp);
78963461a02SJakub Kicinski err_disable_msix:
7906d48ceb2SJakub Kicinski 	destroy_workqueue(pf->wq);
7916d48ceb2SJakub Kicinski err_pci_priv_unset:
79263461a02SJakub Kicinski 	pci_set_drvdata(pdev, NULL);
793346cfe84SJakub Kicinski 	mutex_destroy(&pf->lock);
7941851f93fSSimon Horman 	devlink_free(devlink);
79563461a02SJakub Kicinski err_rel_regions:
79663461a02SJakub Kicinski 	pci_release_regions(pdev);
79763461a02SJakub Kicinski err_pci_disable:
79863461a02SJakub Kicinski 	pci_disable_device(pdev);
79963461a02SJakub Kicinski 
80063461a02SJakub Kicinski 	return err;
80163461a02SJakub Kicinski }
80263461a02SJakub Kicinski 
803790d23e7SDirk van der Merwe static void __nfp_pci_shutdown(struct pci_dev *pdev, bool unload_fw)
80463461a02SJakub Kicinski {
805790d23e7SDirk van der Merwe 	struct nfp_pf *pf;
806790d23e7SDirk van der Merwe 
807790d23e7SDirk van der Merwe 	pf = pci_get_drvdata(pdev);
808790d23e7SDirk van der Merwe 	if (!pf)
809790d23e7SDirk van der Merwe 		return;
8101851f93fSSimon Horman 
811eefbde7eSDavid Brunecz 	nfp_hwmon_unregister(pf);
812eefbde7eSDavid Brunecz 
81363461a02SJakub Kicinski 	nfp_pcie_sriov_disable(pdev);
81463461a02SJakub Kicinski 
815bcc93a23SJakub Kicinski 	nfp_net_pci_remove(pf);
8161851f93fSSimon Horman 
817d79e19f5SCarl Heymann 	vfree(pf->dumpspec);
818af4fa7eaSJakub Kicinski 	kfree(pf->rtbl);
8190be40e66SJakub Kicinski 	nfp_mip_close(pf->mip);
820f8921d73SDirk van der Merwe 	if (unload_fw && pf->unload_fw_on_remove)
82163461a02SJakub Kicinski 		nfp_fw_unload(pf);
82263461a02SJakub Kicinski 
8236d48ceb2SJakub Kicinski 	destroy_workqueue(pf->wq);
82463461a02SJakub Kicinski 	pci_set_drvdata(pdev, NULL);
8259baa4885SJakub Kicinski 	kfree(pf->hwinfo);
82663461a02SJakub Kicinski 	nfp_cpp_free(pf->cpp);
82763461a02SJakub Kicinski 
82863461a02SJakub Kicinski 	kfree(pf->eth_tbl);
829eefbde7eSDavid Brunecz 	kfree(pf->nspi);
830346cfe84SJakub Kicinski 	mutex_destroy(&pf->lock);
831bcc93a23SJakub Kicinski 	devlink_free(priv_to_devlink(pf));
83263461a02SJakub Kicinski 	pci_release_regions(pdev);
83363461a02SJakub Kicinski 	pci_disable_device(pdev);
83463461a02SJakub Kicinski }
83563461a02SJakub Kicinski 
836790d23e7SDirk van der Merwe static void nfp_pci_remove(struct pci_dev *pdev)
837790d23e7SDirk van der Merwe {
838790d23e7SDirk van der Merwe 	__nfp_pci_shutdown(pdev, true);
839790d23e7SDirk van der Merwe }
840790d23e7SDirk van der Merwe 
841790d23e7SDirk van der Merwe static void nfp_pci_shutdown(struct pci_dev *pdev)
842790d23e7SDirk van der Merwe {
843790d23e7SDirk van der Merwe 	__nfp_pci_shutdown(pdev, false);
844790d23e7SDirk van der Merwe }
845790d23e7SDirk van der Merwe 
84663461a02SJakub Kicinski static struct pci_driver nfp_pci_driver = {
84763461a02SJakub Kicinski 	.name			= nfp_driver_name,
84863461a02SJakub Kicinski 	.id_table		= nfp_pci_device_ids,
84963461a02SJakub Kicinski 	.probe			= nfp_pci_probe,
85063461a02SJakub Kicinski 	.remove			= nfp_pci_remove,
851790d23e7SDirk van der Merwe 	.shutdown		= nfp_pci_shutdown,
85263461a02SJakub Kicinski 	.sriov_configure	= nfp_pcie_sriov_configure,
85363461a02SJakub Kicinski };
85463461a02SJakub Kicinski 
8552633beb9SJakub Kicinski static int __init nfp_main_init(void)
8562633beb9SJakub Kicinski {
8572633beb9SJakub Kicinski 	int err;
8582633beb9SJakub Kicinski 
8592633beb9SJakub Kicinski 	pr_info("%s: NFP PCIe Driver, Copyright (C) 2014-2017 Netronome Systems\n",
8602633beb9SJakub Kicinski 		nfp_driver_name);
8612633beb9SJakub Kicinski 
8622633beb9SJakub Kicinski 	nfp_net_debugfs_create();
8632633beb9SJakub Kicinski 
86463461a02SJakub Kicinski 	err = pci_register_driver(&nfp_pci_driver);
86563461a02SJakub Kicinski 	if (err < 0)
86663461a02SJakub Kicinski 		goto err_destroy_debugfs;
86763461a02SJakub Kicinski 
8682633beb9SJakub Kicinski 	err = pci_register_driver(&nfp_netvf_pci_driver);
8692633beb9SJakub Kicinski 	if (err)
87063461a02SJakub Kicinski 		goto err_unreg_pf;
8712633beb9SJakub Kicinski 
8722633beb9SJakub Kicinski 	return err;
8732633beb9SJakub Kicinski 
87463461a02SJakub Kicinski err_unreg_pf:
87563461a02SJakub Kicinski 	pci_unregister_driver(&nfp_pci_driver);
8762633beb9SJakub Kicinski err_destroy_debugfs:
8772633beb9SJakub Kicinski 	nfp_net_debugfs_destroy();
8782633beb9SJakub Kicinski 	return err;
8792633beb9SJakub Kicinski }
8802633beb9SJakub Kicinski 
8812633beb9SJakub Kicinski static void __exit nfp_main_exit(void)
8822633beb9SJakub Kicinski {
8832633beb9SJakub Kicinski 	pci_unregister_driver(&nfp_netvf_pci_driver);
88463461a02SJakub Kicinski 	pci_unregister_driver(&nfp_pci_driver);
8852633beb9SJakub Kicinski 	nfp_net_debugfs_destroy();
8862633beb9SJakub Kicinski }
8872633beb9SJakub Kicinski 
8882633beb9SJakub Kicinski module_init(nfp_main_init);
8892633beb9SJakub Kicinski module_exit(nfp_main_exit);
8902633beb9SJakub Kicinski 
891d00ee466SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0058-0011_2x40.nffw");
892d00ee466SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0058-0012_2x40.nffw");
89363461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_1x40.nffw");
89463461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_4x10.nffw");
89563461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0096-0001_2x10.nffw");
89663461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_2x40.nffw");
89763461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_4x10_1x40.nffw");
89863461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_8x10.nffw");
89963461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x10.nffw");
90063461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x25.nffw");
90170271dadSDirk van der Merwe MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_1x10_1x25.nffw");
90263461a02SJakub Kicinski 
9032633beb9SJakub Kicinski MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
9042633beb9SJakub Kicinski MODULE_LICENSE("GPL");
9052633beb9SJakub Kicinski MODULE_DESCRIPTION("The Netronome Flow Processor (NFP) driver.");
906