12633beb9SJakub Kicinski /* 22633beb9SJakub Kicinski * Copyright (C) 2015-2017 Netronome Systems, Inc. 32633beb9SJakub Kicinski * 42633beb9SJakub Kicinski * This software is dual licensed under the GNU General License Version 2, 52633beb9SJakub Kicinski * June 1991 as shown in the file COPYING in the top-level directory of this 62633beb9SJakub Kicinski * source tree or the BSD 2-Clause License provided below. You have the 72633beb9SJakub Kicinski * option to license this software under the complete terms of either license. 82633beb9SJakub Kicinski * 92633beb9SJakub Kicinski * The BSD 2-Clause License: 102633beb9SJakub Kicinski * 112633beb9SJakub Kicinski * Redistribution and use in source and binary forms, with or 122633beb9SJakub Kicinski * without modification, are permitted provided that the following 132633beb9SJakub Kicinski * conditions are met: 142633beb9SJakub Kicinski * 152633beb9SJakub Kicinski * 1. Redistributions of source code must retain the above 162633beb9SJakub Kicinski * copyright notice, this list of conditions and the following 172633beb9SJakub Kicinski * disclaimer. 182633beb9SJakub Kicinski * 192633beb9SJakub Kicinski * 2. Redistributions in binary form must reproduce the above 202633beb9SJakub Kicinski * copyright notice, this list of conditions and the following 212633beb9SJakub Kicinski * disclaimer in the documentation and/or other materials 222633beb9SJakub Kicinski * provided with the distribution. 232633beb9SJakub Kicinski * 242633beb9SJakub Kicinski * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 252633beb9SJakub Kicinski * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 262633beb9SJakub Kicinski * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 272633beb9SJakub Kicinski * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 282633beb9SJakub Kicinski * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 292633beb9SJakub Kicinski * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 302633beb9SJakub Kicinski * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 312633beb9SJakub Kicinski * SOFTWARE. 322633beb9SJakub Kicinski */ 332633beb9SJakub Kicinski 342633beb9SJakub Kicinski /* 352633beb9SJakub Kicinski * nfp_main.c 362633beb9SJakub Kicinski * Authors: Jakub Kicinski <jakub.kicinski@netronome.com> 372633beb9SJakub Kicinski * Alejandro Lucero <alejandro.lucero@netronome.com> 382633beb9SJakub Kicinski * Jason McMullan <jason.mcmullan@netronome.com> 392633beb9SJakub Kicinski * Rolf Neugebauer <rolf.neugebauer@netronome.com> 402633beb9SJakub Kicinski */ 412633beb9SJakub Kicinski 422633beb9SJakub Kicinski #include <linux/kernel.h> 432633beb9SJakub Kicinski #include <linux/module.h> 44346cfe84SJakub Kicinski #include <linux/mutex.h> 452633beb9SJakub Kicinski #include <linux/pci.h> 462633beb9SJakub Kicinski #include <linux/firmware.h> 472633beb9SJakub Kicinski #include <linux/vermagic.h> 481851f93fSSimon Horman #include <net/devlink.h> 492633beb9SJakub Kicinski 5063461a02SJakub Kicinski #include "nfpcore/nfp.h" 5163461a02SJakub Kicinski #include "nfpcore/nfp_cpp.h" 520bc3827fSJakub Kicinski #include "nfpcore/nfp_nffw.h" 53ce22f5a2SJakub Kicinski #include "nfpcore/nfp_nsp.h" 5463461a02SJakub Kicinski 5563461a02SJakub Kicinski #include "nfpcore/nfp6000_pcie.h" 5663461a02SJakub Kicinski 572633beb9SJakub Kicinski #include "nfp_main.h" 582633beb9SJakub Kicinski #include "nfp_net.h" 592633beb9SJakub Kicinski 602633beb9SJakub Kicinski static const char nfp_driver_name[] = "nfp"; 612633beb9SJakub Kicinski const char nfp_driver_version[] = VERMAGIC_STRING; 622633beb9SJakub Kicinski 6363461a02SJakub Kicinski static const struct pci_device_id nfp_pci_device_ids[] = { 643b473528SSimon Horman { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000, 6563461a02SJakub Kicinski PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID, 6663461a02SJakub Kicinski PCI_ANY_ID, 0, 6763461a02SJakub Kicinski }, 683b473528SSimon Horman { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP4000, 6963461a02SJakub Kicinski PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID, 7063461a02SJakub Kicinski PCI_ANY_ID, 0, 7163461a02SJakub Kicinski }, 7263461a02SJakub Kicinski { 0, } /* Required last entry. */ 7363461a02SJakub Kicinski }; 7463461a02SJakub Kicinski MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids); 7563461a02SJakub Kicinski 76651e1f2fSJakub Kicinski static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf) 770bc3827fSJakub Kicinski { 780bc3827fSJakub Kicinski int err; 790bc3827fSJakub Kicinski 80af4fa7eaSJakub Kicinski pf->limit_vfs = nfp_rtsym_read_le(pf->rtbl, "nfd_vf_cfg_max_vfs", &err); 810bc3827fSJakub Kicinski if (!err) 82651e1f2fSJakub Kicinski return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs); 830bc3827fSJakub Kicinski 840bc3827fSJakub Kicinski pf->limit_vfs = ~0; 85651e1f2fSJakub Kicinski pci_sriov_set_totalvfs(pf->pdev, 0); /* 0 is unset */ 860bc3827fSJakub Kicinski /* Allow any setting for backwards compatibility if symbol not found */ 87651e1f2fSJakub Kicinski if (err == -ENOENT) 88651e1f2fSJakub Kicinski return 0; 89651e1f2fSJakub Kicinski 900bc3827fSJakub Kicinski nfp_warn(pf->cpp, "Warning: VF limit read failed: %d\n", err); 91651e1f2fSJakub Kicinski return err; 920bc3827fSJakub Kicinski } 930bc3827fSJakub Kicinski 9463461a02SJakub Kicinski static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs) 9563461a02SJakub Kicinski { 9663461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV 9763461a02SJakub Kicinski struct nfp_pf *pf = pci_get_drvdata(pdev); 9863461a02SJakub Kicinski int err; 9963461a02SJakub Kicinski 1000bc3827fSJakub Kicinski if (num_vfs > pf->limit_vfs) { 1010bc3827fSJakub Kicinski nfp_info(pf->cpp, "Firmware limits number of VFs to %u\n", 1020bc3827fSJakub Kicinski pf->limit_vfs); 1030bc3827fSJakub Kicinski return -EINVAL; 1040bc3827fSJakub Kicinski } 1050bc3827fSJakub Kicinski 10663461a02SJakub Kicinski err = pci_enable_sriov(pdev, num_vfs); 10763461a02SJakub Kicinski if (err) { 10863461a02SJakub Kicinski dev_warn(&pdev->dev, "Failed to enable PCI sriov: %d\n", err); 10963461a02SJakub Kicinski return err; 11063461a02SJakub Kicinski } 11163461a02SJakub Kicinski 11263461a02SJakub Kicinski pf->num_vfs = num_vfs; 11363461a02SJakub Kicinski 11463461a02SJakub Kicinski dev_dbg(&pdev->dev, "Created %d VFs.\n", pf->num_vfs); 11563461a02SJakub Kicinski 11663461a02SJakub Kicinski return num_vfs; 11763461a02SJakub Kicinski #endif 11863461a02SJakub Kicinski return 0; 11963461a02SJakub Kicinski } 12063461a02SJakub Kicinski 12163461a02SJakub Kicinski static int nfp_pcie_sriov_disable(struct pci_dev *pdev) 12263461a02SJakub Kicinski { 12363461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV 12463461a02SJakub Kicinski struct nfp_pf *pf = pci_get_drvdata(pdev); 12563461a02SJakub Kicinski 12663461a02SJakub Kicinski /* If the VFs are assigned we cannot shut down SR-IOV without 12763461a02SJakub Kicinski * causing issues, so just leave the hardware available but 12863461a02SJakub Kicinski * disabled 12963461a02SJakub Kicinski */ 13063461a02SJakub Kicinski if (pci_vfs_assigned(pdev)) { 13163461a02SJakub Kicinski dev_warn(&pdev->dev, "Disabling while VFs assigned - VFs will not be deallocated\n"); 13263461a02SJakub Kicinski return -EPERM; 13363461a02SJakub Kicinski } 13463461a02SJakub Kicinski 13563461a02SJakub Kicinski pf->num_vfs = 0; 13663461a02SJakub Kicinski 13763461a02SJakub Kicinski pci_disable_sriov(pdev); 13863461a02SJakub Kicinski dev_dbg(&pdev->dev, "Removed VFs.\n"); 13963461a02SJakub Kicinski #endif 14063461a02SJakub Kicinski return 0; 14163461a02SJakub Kicinski } 14263461a02SJakub Kicinski 14363461a02SJakub Kicinski static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs) 14463461a02SJakub Kicinski { 14563461a02SJakub Kicinski if (num_vfs == 0) 14663461a02SJakub Kicinski return nfp_pcie_sriov_disable(pdev); 14763461a02SJakub Kicinski else 14863461a02SJakub Kicinski return nfp_pcie_sriov_enable(pdev, num_vfs); 14963461a02SJakub Kicinski } 15063461a02SJakub Kicinski 15163461a02SJakub Kicinski /** 15263461a02SJakub Kicinski * nfp_net_fw_find() - Find the correct firmware image for netdev mode 15363461a02SJakub Kicinski * @pdev: PCI Device structure 15463461a02SJakub Kicinski * @pf: NFP PF Device structure 15563461a02SJakub Kicinski * 15663461a02SJakub Kicinski * Return: firmware if found and requested successfully. 15763461a02SJakub Kicinski */ 15863461a02SJakub Kicinski static const struct firmware * 15963461a02SJakub Kicinski nfp_net_fw_find(struct pci_dev *pdev, struct nfp_pf *pf) 16063461a02SJakub Kicinski { 16163461a02SJakub Kicinski const struct firmware *fw = NULL; 16263461a02SJakub Kicinski struct nfp_eth_table_port *port; 16363461a02SJakub Kicinski const char *fw_model; 16463461a02SJakub Kicinski char fw_name[256]; 16563461a02SJakub Kicinski int spc, err = 0; 16663461a02SJakub Kicinski int i, j; 16763461a02SJakub Kicinski 16863461a02SJakub Kicinski if (!pf->eth_tbl) { 16963461a02SJakub Kicinski dev_err(&pdev->dev, "Error: can't identify media config\n"); 17063461a02SJakub Kicinski return NULL; 17163461a02SJakub Kicinski } 17263461a02SJakub Kicinski 1739baa4885SJakub Kicinski fw_model = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"); 17463461a02SJakub Kicinski if (!fw_model) { 17563461a02SJakub Kicinski dev_err(&pdev->dev, "Error: can't read part number\n"); 17663461a02SJakub Kicinski return NULL; 17763461a02SJakub Kicinski } 17863461a02SJakub Kicinski 17963461a02SJakub Kicinski spc = ARRAY_SIZE(fw_name); 18063461a02SJakub Kicinski spc -= snprintf(fw_name, spc, "netronome/nic_%s", fw_model); 18163461a02SJakub Kicinski 18263461a02SJakub Kicinski for (i = 0; spc > 0 && i < pf->eth_tbl->count; i += j) { 18363461a02SJakub Kicinski port = &pf->eth_tbl->ports[i]; 18463461a02SJakub Kicinski j = 1; 18563461a02SJakub Kicinski while (i + j < pf->eth_tbl->count && 18663461a02SJakub Kicinski port->speed == port[j].speed) 18763461a02SJakub Kicinski j++; 18863461a02SJakub Kicinski 18963461a02SJakub Kicinski spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, 19063461a02SJakub Kicinski "_%dx%d", j, port->speed / 1000); 19163461a02SJakub Kicinski } 19263461a02SJakub Kicinski 19363461a02SJakub Kicinski if (spc <= 0) 19463461a02SJakub Kicinski return NULL; 19563461a02SJakub Kicinski 19663461a02SJakub Kicinski spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, ".nffw"); 19763461a02SJakub Kicinski if (spc <= 0) 19863461a02SJakub Kicinski return NULL; 19963461a02SJakub Kicinski 20063461a02SJakub Kicinski err = request_firmware(&fw, fw_name, &pdev->dev); 20163461a02SJakub Kicinski if (err) 20263461a02SJakub Kicinski return NULL; 20363461a02SJakub Kicinski 20463461a02SJakub Kicinski dev_info(&pdev->dev, "Loading FW image: %s\n", fw_name); 20563461a02SJakub Kicinski 20663461a02SJakub Kicinski return fw; 20763461a02SJakub Kicinski } 20863461a02SJakub Kicinski 20963461a02SJakub Kicinski /** 21063461a02SJakub Kicinski * nfp_net_fw_load() - Load the firmware image 21163461a02SJakub Kicinski * @pdev: PCI Device structure 21263461a02SJakub Kicinski * @pf: NFP PF Device structure 21363461a02SJakub Kicinski * @nsp: NFP SP handle 21463461a02SJakub Kicinski * 21563461a02SJakub Kicinski * Return: -ERRNO, 0 for no firmware loaded, 1 for firmware loaded 21663461a02SJakub Kicinski */ 21763461a02SJakub Kicinski static int 21863461a02SJakub Kicinski nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp) 21963461a02SJakub Kicinski { 22063461a02SJakub Kicinski const struct firmware *fw; 22163461a02SJakub Kicinski u16 interface; 22263461a02SJakub Kicinski int err; 22363461a02SJakub Kicinski 22463461a02SJakub Kicinski interface = nfp_cpp_interface(pf->cpp); 22563461a02SJakub Kicinski if (NFP_CPP_INTERFACE_UNIT_of(interface) != 0) { 22663461a02SJakub Kicinski /* Only Unit 0 should reset or load firmware */ 22763461a02SJakub Kicinski dev_info(&pdev->dev, "Firmware will be loaded by partner\n"); 22863461a02SJakub Kicinski return 0; 22963461a02SJakub Kicinski } 23063461a02SJakub Kicinski 23163461a02SJakub Kicinski fw = nfp_net_fw_find(pdev, pf); 23263461a02SJakub Kicinski if (!fw) 23363461a02SJakub Kicinski return 0; 23463461a02SJakub Kicinski 23563461a02SJakub Kicinski dev_info(&pdev->dev, "Soft-reset, loading FW image\n"); 23663461a02SJakub Kicinski err = nfp_nsp_device_soft_reset(nsp); 23763461a02SJakub Kicinski if (err < 0) { 23863461a02SJakub Kicinski dev_err(&pdev->dev, "Failed to soft reset the NFP: %d\n", 23963461a02SJakub Kicinski err); 24063461a02SJakub Kicinski goto exit_release_fw; 24163461a02SJakub Kicinski } 24263461a02SJakub Kicinski 24363461a02SJakub Kicinski err = nfp_nsp_load_fw(nsp, fw); 24463461a02SJakub Kicinski 24563461a02SJakub Kicinski if (err < 0) { 24663461a02SJakub Kicinski dev_err(&pdev->dev, "FW loading failed: %d\n", err); 24763461a02SJakub Kicinski goto exit_release_fw; 24863461a02SJakub Kicinski } 24963461a02SJakub Kicinski 25063461a02SJakub Kicinski dev_info(&pdev->dev, "Finished loading FW image\n"); 25163461a02SJakub Kicinski 25263461a02SJakub Kicinski exit_release_fw: 25363461a02SJakub Kicinski release_firmware(fw); 25463461a02SJakub Kicinski 25563461a02SJakub Kicinski return err < 0 ? err : 1; 25663461a02SJakub Kicinski } 25763461a02SJakub Kicinski 258a9c83f7bSJakub Kicinski static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf) 259a9c83f7bSJakub Kicinski { 260a9c83f7bSJakub Kicinski struct nfp_nsp *nsp; 261a9c83f7bSJakub Kicinski int err; 262a9c83f7bSJakub Kicinski 263a9c83f7bSJakub Kicinski nsp = nfp_nsp_open(pf->cpp); 264a9c83f7bSJakub Kicinski if (IS_ERR(nsp)) { 265a9c83f7bSJakub Kicinski err = PTR_ERR(nsp); 266a9c83f7bSJakub Kicinski dev_err(&pdev->dev, "Failed to access the NSP: %d\n", err); 267a9c83f7bSJakub Kicinski return err; 268a9c83f7bSJakub Kicinski } 269a9c83f7bSJakub Kicinski 270a9c83f7bSJakub Kicinski err = nfp_nsp_wait(nsp); 271a9c83f7bSJakub Kicinski if (err < 0) 272a9c83f7bSJakub Kicinski goto exit_close_nsp; 273a9c83f7bSJakub Kicinski 274a9c83f7bSJakub Kicinski pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp); 275a9c83f7bSJakub Kicinski 276eefbde7eSDavid Brunecz pf->nspi = __nfp_nsp_identify(nsp); 277eefbde7eSDavid Brunecz if (pf->nspi) 278eefbde7eSDavid Brunecz dev_info(&pdev->dev, "BSP: %s\n", pf->nspi->version); 279010e2f9cSDavid Brunecz 280a9c83f7bSJakub Kicinski err = nfp_fw_load(pdev, pf, nsp); 281a9c83f7bSJakub Kicinski if (err < 0) { 28247eaa23bSJakub Kicinski kfree(pf->nspi); 283a9c83f7bSJakub Kicinski kfree(pf->eth_tbl); 284a9c83f7bSJakub Kicinski dev_err(&pdev->dev, "Failed to load FW\n"); 285a9c83f7bSJakub Kicinski goto exit_close_nsp; 286a9c83f7bSJakub Kicinski } 287a9c83f7bSJakub Kicinski 288a9c83f7bSJakub Kicinski pf->fw_loaded = !!err; 289a9c83f7bSJakub Kicinski err = 0; 290a9c83f7bSJakub Kicinski 291a9c83f7bSJakub Kicinski exit_close_nsp: 292a9c83f7bSJakub Kicinski nfp_nsp_close(nsp); 293a9c83f7bSJakub Kicinski 294a9c83f7bSJakub Kicinski return err; 295a9c83f7bSJakub Kicinski } 296a9c83f7bSJakub Kicinski 29763461a02SJakub Kicinski static void nfp_fw_unload(struct nfp_pf *pf) 29863461a02SJakub Kicinski { 29963461a02SJakub Kicinski struct nfp_nsp *nsp; 30063461a02SJakub Kicinski int err; 30163461a02SJakub Kicinski 30263461a02SJakub Kicinski nsp = nfp_nsp_open(pf->cpp); 30363461a02SJakub Kicinski if (IS_ERR(nsp)) { 30463461a02SJakub Kicinski nfp_err(pf->cpp, "Reset failed, can't open NSP\n"); 30563461a02SJakub Kicinski return; 30663461a02SJakub Kicinski } 30763461a02SJakub Kicinski 30863461a02SJakub Kicinski err = nfp_nsp_device_soft_reset(nsp); 30963461a02SJakub Kicinski if (err < 0) 31063461a02SJakub Kicinski dev_warn(&pf->pdev->dev, "Couldn't unload firmware: %d\n", err); 31163461a02SJakub Kicinski else 31263461a02SJakub Kicinski dev_info(&pf->pdev->dev, "Firmware safely unloaded\n"); 31363461a02SJakub Kicinski 31463461a02SJakub Kicinski nfp_nsp_close(nsp); 31563461a02SJakub Kicinski } 31663461a02SJakub Kicinski 31763461a02SJakub Kicinski static int nfp_pci_probe(struct pci_dev *pdev, 31863461a02SJakub Kicinski const struct pci_device_id *pci_id) 31963461a02SJakub Kicinski { 3201851f93fSSimon Horman struct devlink *devlink; 32163461a02SJakub Kicinski struct nfp_pf *pf; 32263461a02SJakub Kicinski int err; 32363461a02SJakub Kicinski 32463461a02SJakub Kicinski err = pci_enable_device(pdev); 32563461a02SJakub Kicinski if (err < 0) 32663461a02SJakub Kicinski return err; 32763461a02SJakub Kicinski 32863461a02SJakub Kicinski pci_set_master(pdev); 32963461a02SJakub Kicinski 33063461a02SJakub Kicinski err = dma_set_mask_and_coherent(&pdev->dev, 33163461a02SJakub Kicinski DMA_BIT_MASK(NFP_NET_MAX_DMA_BITS)); 33263461a02SJakub Kicinski if (err) 33363461a02SJakub Kicinski goto err_pci_disable; 33463461a02SJakub Kicinski 33563461a02SJakub Kicinski err = pci_request_regions(pdev, nfp_driver_name); 33663461a02SJakub Kicinski if (err < 0) { 33763461a02SJakub Kicinski dev_err(&pdev->dev, "Unable to reserve pci resources.\n"); 33863461a02SJakub Kicinski goto err_pci_disable; 33963461a02SJakub Kicinski } 34063461a02SJakub Kicinski 3411851f93fSSimon Horman devlink = devlink_alloc(&nfp_devlink_ops, sizeof(*pf)); 3421851f93fSSimon Horman if (!devlink) { 34363461a02SJakub Kicinski err = -ENOMEM; 34463461a02SJakub Kicinski goto err_rel_regions; 34563461a02SJakub Kicinski } 3461851f93fSSimon Horman pf = devlink_priv(devlink); 347d4e7f092SJakub Kicinski INIT_LIST_HEAD(&pf->vnics); 3483eb3b74aSJakub Kicinski INIT_LIST_HEAD(&pf->ports); 349346cfe84SJakub Kicinski mutex_init(&pf->lock); 35063461a02SJakub Kicinski pci_set_drvdata(pdev, pf); 35163461a02SJakub Kicinski pf->pdev = pdev; 35263461a02SJakub Kicinski 35363461a02SJakub Kicinski pf->cpp = nfp_cpp_from_nfp6000_pcie(pdev); 35463461a02SJakub Kicinski if (IS_ERR_OR_NULL(pf->cpp)) { 35563461a02SJakub Kicinski err = PTR_ERR(pf->cpp); 35663461a02SJakub Kicinski if (err >= 0) 35763461a02SJakub Kicinski err = -ENOMEM; 35863461a02SJakub Kicinski goto err_disable_msix; 35963461a02SJakub Kicinski } 36063461a02SJakub Kicinski 3619baa4885SJakub Kicinski pf->hwinfo = nfp_hwinfo_read(pf->cpp); 3629baa4885SJakub Kicinski 36364db09edSJakub Kicinski dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n", 3649baa4885SJakub Kicinski nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"), 3659baa4885SJakub Kicinski nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"), 3669baa4885SJakub Kicinski nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"), 3679baa4885SJakub Kicinski nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"), 3689baa4885SJakub Kicinski nfp_hwinfo_lookup(pf->hwinfo, "cpld.version")); 36964db09edSJakub Kicinski 3701851f93fSSimon Horman err = devlink_register(devlink, &pdev->dev); 371a9c83f7bSJakub Kicinski if (err) 3729baa4885SJakub Kicinski goto err_hwinfo_free; 37363461a02SJakub Kicinski 3741851f93fSSimon Horman err = nfp_nsp_init(pdev, pf); 3751851f93fSSimon Horman if (err) 3761851f93fSSimon Horman goto err_devlink_unreg; 3771851f93fSSimon Horman 3780be40e66SJakub Kicinski pf->mip = nfp_mip_open(pf->cpp); 3790be40e66SJakub Kicinski pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip); 380af4fa7eaSJakub Kicinski 381651e1f2fSJakub Kicinski err = nfp_pcie_sriov_read_nfd_limit(pf); 38263461a02SJakub Kicinski if (err) 38363461a02SJakub Kicinski goto err_fw_unload; 38463461a02SJakub Kicinski 385651e1f2fSJakub Kicinski err = nfp_net_pci_probe(pf); 386651e1f2fSJakub Kicinski if (err) 387651e1f2fSJakub Kicinski goto err_sriov_unlimit; 388651e1f2fSJakub Kicinski 389eefbde7eSDavid Brunecz err = nfp_hwmon_register(pf); 390eefbde7eSDavid Brunecz if (err) { 391eefbde7eSDavid Brunecz dev_err(&pdev->dev, "Failed to register hwmon info\n"); 392eefbde7eSDavid Brunecz goto err_net_remove; 393eefbde7eSDavid Brunecz } 394eefbde7eSDavid Brunecz 39563461a02SJakub Kicinski return 0; 39663461a02SJakub Kicinski 397eefbde7eSDavid Brunecz err_net_remove: 398eefbde7eSDavid Brunecz nfp_net_pci_remove(pf); 399651e1f2fSJakub Kicinski err_sriov_unlimit: 400651e1f2fSJakub Kicinski pci_sriov_set_totalvfs(pf->pdev, 0); 40163461a02SJakub Kicinski err_fw_unload: 402af4fa7eaSJakub Kicinski kfree(pf->rtbl); 4030be40e66SJakub Kicinski nfp_mip_close(pf->mip); 40463461a02SJakub Kicinski if (pf->fw_loaded) 40563461a02SJakub Kicinski nfp_fw_unload(pf); 40663461a02SJakub Kicinski kfree(pf->eth_tbl); 407eefbde7eSDavid Brunecz kfree(pf->nspi); 4081851f93fSSimon Horman err_devlink_unreg: 4091851f93fSSimon Horman devlink_unregister(devlink); 4109baa4885SJakub Kicinski err_hwinfo_free: 4119baa4885SJakub Kicinski kfree(pf->hwinfo); 41263461a02SJakub Kicinski nfp_cpp_free(pf->cpp); 41363461a02SJakub Kicinski err_disable_msix: 41463461a02SJakub Kicinski pci_set_drvdata(pdev, NULL); 415346cfe84SJakub Kicinski mutex_destroy(&pf->lock); 4161851f93fSSimon Horman devlink_free(devlink); 41763461a02SJakub Kicinski err_rel_regions: 41863461a02SJakub Kicinski pci_release_regions(pdev); 41963461a02SJakub Kicinski err_pci_disable: 42063461a02SJakub Kicinski pci_disable_device(pdev); 42163461a02SJakub Kicinski 42263461a02SJakub Kicinski return err; 42363461a02SJakub Kicinski } 42463461a02SJakub Kicinski 42563461a02SJakub Kicinski static void nfp_pci_remove(struct pci_dev *pdev) 42663461a02SJakub Kicinski { 42763461a02SJakub Kicinski struct nfp_pf *pf = pci_get_drvdata(pdev); 4281851f93fSSimon Horman struct devlink *devlink; 4291851f93fSSimon Horman 430eefbde7eSDavid Brunecz nfp_hwmon_unregister(pf); 431eefbde7eSDavid Brunecz 4321851f93fSSimon Horman devlink = priv_to_devlink(pf); 43363461a02SJakub Kicinski 43463461a02SJakub Kicinski nfp_net_pci_remove(pf); 43563461a02SJakub Kicinski 43663461a02SJakub Kicinski nfp_pcie_sriov_disable(pdev); 437651e1f2fSJakub Kicinski pci_sriov_set_totalvfs(pf->pdev, 0); 43863461a02SJakub Kicinski 4391851f93fSSimon Horman devlink_unregister(devlink); 4401851f93fSSimon Horman 441af4fa7eaSJakub Kicinski kfree(pf->rtbl); 4420be40e66SJakub Kicinski nfp_mip_close(pf->mip); 44363461a02SJakub Kicinski if (pf->fw_loaded) 44463461a02SJakub Kicinski nfp_fw_unload(pf); 44563461a02SJakub Kicinski 44663461a02SJakub Kicinski pci_set_drvdata(pdev, NULL); 4479baa4885SJakub Kicinski kfree(pf->hwinfo); 44863461a02SJakub Kicinski nfp_cpp_free(pf->cpp); 44963461a02SJakub Kicinski 45063461a02SJakub Kicinski kfree(pf->eth_tbl); 451eefbde7eSDavid Brunecz kfree(pf->nspi); 452346cfe84SJakub Kicinski mutex_destroy(&pf->lock); 4531851f93fSSimon Horman devlink_free(devlink); 45463461a02SJakub Kicinski pci_release_regions(pdev); 45563461a02SJakub Kicinski pci_disable_device(pdev); 45663461a02SJakub Kicinski } 45763461a02SJakub Kicinski 45863461a02SJakub Kicinski static struct pci_driver nfp_pci_driver = { 45963461a02SJakub Kicinski .name = nfp_driver_name, 46063461a02SJakub Kicinski .id_table = nfp_pci_device_ids, 46163461a02SJakub Kicinski .probe = nfp_pci_probe, 46263461a02SJakub Kicinski .remove = nfp_pci_remove, 46363461a02SJakub Kicinski .sriov_configure = nfp_pcie_sriov_configure, 46463461a02SJakub Kicinski }; 46563461a02SJakub Kicinski 4662633beb9SJakub Kicinski static int __init nfp_main_init(void) 4672633beb9SJakub Kicinski { 4682633beb9SJakub Kicinski int err; 4692633beb9SJakub Kicinski 4702633beb9SJakub Kicinski pr_info("%s: NFP PCIe Driver, Copyright (C) 2014-2017 Netronome Systems\n", 4712633beb9SJakub Kicinski nfp_driver_name); 4722633beb9SJakub Kicinski 4732633beb9SJakub Kicinski nfp_net_debugfs_create(); 4742633beb9SJakub Kicinski 47563461a02SJakub Kicinski err = pci_register_driver(&nfp_pci_driver); 47663461a02SJakub Kicinski if (err < 0) 47763461a02SJakub Kicinski goto err_destroy_debugfs; 47863461a02SJakub Kicinski 4792633beb9SJakub Kicinski err = pci_register_driver(&nfp_netvf_pci_driver); 4802633beb9SJakub Kicinski if (err) 48163461a02SJakub Kicinski goto err_unreg_pf; 4822633beb9SJakub Kicinski 4832633beb9SJakub Kicinski return err; 4842633beb9SJakub Kicinski 48563461a02SJakub Kicinski err_unreg_pf: 48663461a02SJakub Kicinski pci_unregister_driver(&nfp_pci_driver); 4872633beb9SJakub Kicinski err_destroy_debugfs: 4882633beb9SJakub Kicinski nfp_net_debugfs_destroy(); 4892633beb9SJakub Kicinski return err; 4902633beb9SJakub Kicinski } 4912633beb9SJakub Kicinski 4922633beb9SJakub Kicinski static void __exit nfp_main_exit(void) 4932633beb9SJakub Kicinski { 4942633beb9SJakub Kicinski pci_unregister_driver(&nfp_netvf_pci_driver); 49563461a02SJakub Kicinski pci_unregister_driver(&nfp_pci_driver); 4962633beb9SJakub Kicinski nfp_net_debugfs_destroy(); 4972633beb9SJakub Kicinski } 4982633beb9SJakub Kicinski 4992633beb9SJakub Kicinski module_init(nfp_main_init); 5002633beb9SJakub Kicinski module_exit(nfp_main_exit); 5012633beb9SJakub Kicinski 50263461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_1x40.nffw"); 50363461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_4x10.nffw"); 50463461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0096-0001_2x10.nffw"); 50563461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_2x40.nffw"); 50663461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_4x10_1x40.nffw"); 50763461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_8x10.nffw"); 50863461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x10.nffw"); 50963461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x25.nffw"); 51063461a02SJakub Kicinski 5112633beb9SJakub Kicinski MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>"); 5122633beb9SJakub Kicinski MODULE_LICENSE("GPL"); 5132633beb9SJakub Kicinski MODULE_DESCRIPTION("The Netronome Flow Processor (NFP) driver."); 514