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