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> 442633beb9SJakub Kicinski #include <linux/pci.h> 452633beb9SJakub Kicinski #include <linux/firmware.h> 462633beb9SJakub Kicinski #include <linux/vermagic.h> 472633beb9SJakub Kicinski 4863461a02SJakub Kicinski #include "nfpcore/nfp.h" 4963461a02SJakub Kicinski #include "nfpcore/nfp_cpp.h" 500bc3827fSJakub Kicinski #include "nfpcore/nfp_nffw.h" 51ce22f5a2SJakub Kicinski #include "nfpcore/nfp_nsp.h" 5263461a02SJakub Kicinski 5363461a02SJakub Kicinski #include "nfpcore/nfp6000_pcie.h" 5463461a02SJakub Kicinski 552633beb9SJakub Kicinski #include "nfp_main.h" 562633beb9SJakub Kicinski #include "nfp_net.h" 572633beb9SJakub Kicinski 582633beb9SJakub Kicinski static const char nfp_driver_name[] = "nfp"; 592633beb9SJakub Kicinski const char nfp_driver_version[] = VERMAGIC_STRING; 602633beb9SJakub Kicinski 6163461a02SJakub Kicinski static const struct pci_device_id nfp_pci_device_ids[] = { 623b473528SSimon Horman { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000, 6363461a02SJakub Kicinski PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID, 6463461a02SJakub Kicinski PCI_ANY_ID, 0, 6563461a02SJakub Kicinski }, 663b473528SSimon Horman { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP4000, 6763461a02SJakub Kicinski PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID, 6863461a02SJakub Kicinski PCI_ANY_ID, 0, 6963461a02SJakub Kicinski }, 7063461a02SJakub Kicinski { 0, } /* Required last entry. */ 7163461a02SJakub Kicinski }; 7263461a02SJakub Kicinski MODULE_DEVICE_TABLE(pci, nfp_pci_device_ids); 7363461a02SJakub Kicinski 740bc3827fSJakub Kicinski static void nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf) 750bc3827fSJakub Kicinski { 760bc3827fSJakub Kicinski #ifdef CONFIG_PCI_IOV 770bc3827fSJakub Kicinski int err; 780bc3827fSJakub Kicinski 790bc3827fSJakub Kicinski pf->limit_vfs = nfp_rtsym_read_le(pf->cpp, "nfd_vf_cfg_max_vfs", &err); 800bc3827fSJakub Kicinski if (!err) 810bc3827fSJakub Kicinski return; 820bc3827fSJakub Kicinski 830bc3827fSJakub Kicinski pf->limit_vfs = ~0; 840bc3827fSJakub Kicinski /* Allow any setting for backwards compatibility if symbol not found */ 850bc3827fSJakub Kicinski if (err != -ENOENT) 860bc3827fSJakub Kicinski nfp_warn(pf->cpp, "Warning: VF limit read failed: %d\n", err); 870bc3827fSJakub Kicinski #endif 880bc3827fSJakub Kicinski } 890bc3827fSJakub Kicinski 9063461a02SJakub Kicinski static int nfp_pcie_sriov_enable(struct pci_dev *pdev, int num_vfs) 9163461a02SJakub Kicinski { 9263461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV 9363461a02SJakub Kicinski struct nfp_pf *pf = pci_get_drvdata(pdev); 9463461a02SJakub Kicinski int err; 9563461a02SJakub Kicinski 960bc3827fSJakub Kicinski if (num_vfs > pf->limit_vfs) { 970bc3827fSJakub Kicinski nfp_info(pf->cpp, "Firmware limits number of VFs to %u\n", 980bc3827fSJakub Kicinski pf->limit_vfs); 990bc3827fSJakub Kicinski return -EINVAL; 1000bc3827fSJakub Kicinski } 1010bc3827fSJakub Kicinski 10263461a02SJakub Kicinski err = pci_enable_sriov(pdev, num_vfs); 10363461a02SJakub Kicinski if (err) { 10463461a02SJakub Kicinski dev_warn(&pdev->dev, "Failed to enable PCI sriov: %d\n", err); 10563461a02SJakub Kicinski return err; 10663461a02SJakub Kicinski } 10763461a02SJakub Kicinski 10863461a02SJakub Kicinski pf->num_vfs = num_vfs; 10963461a02SJakub Kicinski 11063461a02SJakub Kicinski dev_dbg(&pdev->dev, "Created %d VFs.\n", pf->num_vfs); 11163461a02SJakub Kicinski 11263461a02SJakub Kicinski return num_vfs; 11363461a02SJakub Kicinski #endif 11463461a02SJakub Kicinski return 0; 11563461a02SJakub Kicinski } 11663461a02SJakub Kicinski 11763461a02SJakub Kicinski static int nfp_pcie_sriov_disable(struct pci_dev *pdev) 11863461a02SJakub Kicinski { 11963461a02SJakub Kicinski #ifdef CONFIG_PCI_IOV 12063461a02SJakub Kicinski struct nfp_pf *pf = pci_get_drvdata(pdev); 12163461a02SJakub Kicinski 12263461a02SJakub Kicinski /* If the VFs are assigned we cannot shut down SR-IOV without 12363461a02SJakub Kicinski * causing issues, so just leave the hardware available but 12463461a02SJakub Kicinski * disabled 12563461a02SJakub Kicinski */ 12663461a02SJakub Kicinski if (pci_vfs_assigned(pdev)) { 12763461a02SJakub Kicinski dev_warn(&pdev->dev, "Disabling while VFs assigned - VFs will not be deallocated\n"); 12863461a02SJakub Kicinski return -EPERM; 12963461a02SJakub Kicinski } 13063461a02SJakub Kicinski 13163461a02SJakub Kicinski pf->num_vfs = 0; 13263461a02SJakub Kicinski 13363461a02SJakub Kicinski pci_disable_sriov(pdev); 13463461a02SJakub Kicinski dev_dbg(&pdev->dev, "Removed VFs.\n"); 13563461a02SJakub Kicinski #endif 13663461a02SJakub Kicinski return 0; 13763461a02SJakub Kicinski } 13863461a02SJakub Kicinski 13963461a02SJakub Kicinski static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs) 14063461a02SJakub Kicinski { 14163461a02SJakub Kicinski if (num_vfs == 0) 14263461a02SJakub Kicinski return nfp_pcie_sriov_disable(pdev); 14363461a02SJakub Kicinski else 14463461a02SJakub Kicinski return nfp_pcie_sriov_enable(pdev, num_vfs); 14563461a02SJakub Kicinski } 14663461a02SJakub Kicinski 14763461a02SJakub Kicinski /** 14863461a02SJakub Kicinski * nfp_net_fw_find() - Find the correct firmware image for netdev mode 14963461a02SJakub Kicinski * @pdev: PCI Device structure 15063461a02SJakub Kicinski * @pf: NFP PF Device structure 15163461a02SJakub Kicinski * 15263461a02SJakub Kicinski * Return: firmware if found and requested successfully. 15363461a02SJakub Kicinski */ 15463461a02SJakub Kicinski static const struct firmware * 15563461a02SJakub Kicinski nfp_net_fw_find(struct pci_dev *pdev, struct nfp_pf *pf) 15663461a02SJakub Kicinski { 15763461a02SJakub Kicinski const struct firmware *fw = NULL; 15863461a02SJakub Kicinski struct nfp_eth_table_port *port; 15963461a02SJakub Kicinski const char *fw_model; 16063461a02SJakub Kicinski char fw_name[256]; 16163461a02SJakub Kicinski int spc, err = 0; 16263461a02SJakub Kicinski int i, j; 16363461a02SJakub Kicinski 16463461a02SJakub Kicinski if (!pf->eth_tbl) { 16563461a02SJakub Kicinski dev_err(&pdev->dev, "Error: can't identify media config\n"); 16663461a02SJakub Kicinski return NULL; 16763461a02SJakub Kicinski } 16863461a02SJakub Kicinski 16963461a02SJakub Kicinski fw_model = nfp_hwinfo_lookup(pf->cpp, "assembly.partno"); 17063461a02SJakub Kicinski if (!fw_model) { 17163461a02SJakub Kicinski dev_err(&pdev->dev, "Error: can't read part number\n"); 17263461a02SJakub Kicinski return NULL; 17363461a02SJakub Kicinski } 17463461a02SJakub Kicinski 17563461a02SJakub Kicinski spc = ARRAY_SIZE(fw_name); 17663461a02SJakub Kicinski spc -= snprintf(fw_name, spc, "netronome/nic_%s", fw_model); 17763461a02SJakub Kicinski 17863461a02SJakub Kicinski for (i = 0; spc > 0 && i < pf->eth_tbl->count; i += j) { 17963461a02SJakub Kicinski port = &pf->eth_tbl->ports[i]; 18063461a02SJakub Kicinski j = 1; 18163461a02SJakub Kicinski while (i + j < pf->eth_tbl->count && 18263461a02SJakub Kicinski port->speed == port[j].speed) 18363461a02SJakub Kicinski j++; 18463461a02SJakub Kicinski 18563461a02SJakub Kicinski spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, 18663461a02SJakub Kicinski "_%dx%d", j, port->speed / 1000); 18763461a02SJakub Kicinski } 18863461a02SJakub Kicinski 18963461a02SJakub Kicinski if (spc <= 0) 19063461a02SJakub Kicinski return NULL; 19163461a02SJakub Kicinski 19263461a02SJakub Kicinski spc -= snprintf(&fw_name[ARRAY_SIZE(fw_name) - spc], spc, ".nffw"); 19363461a02SJakub Kicinski if (spc <= 0) 19463461a02SJakub Kicinski return NULL; 19563461a02SJakub Kicinski 19663461a02SJakub Kicinski err = request_firmware(&fw, fw_name, &pdev->dev); 19763461a02SJakub Kicinski if (err) 19863461a02SJakub Kicinski return NULL; 19963461a02SJakub Kicinski 20063461a02SJakub Kicinski dev_info(&pdev->dev, "Loading FW image: %s\n", fw_name); 20163461a02SJakub Kicinski 20263461a02SJakub Kicinski return fw; 20363461a02SJakub Kicinski } 20463461a02SJakub Kicinski 20563461a02SJakub Kicinski /** 20663461a02SJakub Kicinski * nfp_net_fw_load() - Load the firmware image 20763461a02SJakub Kicinski * @pdev: PCI Device structure 20863461a02SJakub Kicinski * @pf: NFP PF Device structure 20963461a02SJakub Kicinski * @nsp: NFP SP handle 21063461a02SJakub Kicinski * 21163461a02SJakub Kicinski * Return: -ERRNO, 0 for no firmware loaded, 1 for firmware loaded 21263461a02SJakub Kicinski */ 21363461a02SJakub Kicinski static int 21463461a02SJakub Kicinski nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp) 21563461a02SJakub Kicinski { 21663461a02SJakub Kicinski const struct firmware *fw; 21763461a02SJakub Kicinski u16 interface; 21863461a02SJakub Kicinski int err; 21963461a02SJakub Kicinski 22063461a02SJakub Kicinski interface = nfp_cpp_interface(pf->cpp); 22163461a02SJakub Kicinski if (NFP_CPP_INTERFACE_UNIT_of(interface) != 0) { 22263461a02SJakub Kicinski /* Only Unit 0 should reset or load firmware */ 22363461a02SJakub Kicinski dev_info(&pdev->dev, "Firmware will be loaded by partner\n"); 22463461a02SJakub Kicinski return 0; 22563461a02SJakub Kicinski } 22663461a02SJakub Kicinski 22763461a02SJakub Kicinski fw = nfp_net_fw_find(pdev, pf); 22863461a02SJakub Kicinski if (!fw) 22963461a02SJakub Kicinski return 0; 23063461a02SJakub Kicinski 23163461a02SJakub Kicinski dev_info(&pdev->dev, "Soft-reset, loading FW image\n"); 23263461a02SJakub Kicinski err = nfp_nsp_device_soft_reset(nsp); 23363461a02SJakub Kicinski if (err < 0) { 23463461a02SJakub Kicinski dev_err(&pdev->dev, "Failed to soft reset the NFP: %d\n", 23563461a02SJakub Kicinski err); 23663461a02SJakub Kicinski goto exit_release_fw; 23763461a02SJakub Kicinski } 23863461a02SJakub Kicinski 23963461a02SJakub Kicinski err = nfp_nsp_load_fw(nsp, fw); 24063461a02SJakub Kicinski 24163461a02SJakub Kicinski if (err < 0) { 24263461a02SJakub Kicinski dev_err(&pdev->dev, "FW loading failed: %d\n", err); 24363461a02SJakub Kicinski goto exit_release_fw; 24463461a02SJakub Kicinski } 24563461a02SJakub Kicinski 24663461a02SJakub Kicinski dev_info(&pdev->dev, "Finished loading FW image\n"); 24763461a02SJakub Kicinski 24863461a02SJakub Kicinski exit_release_fw: 24963461a02SJakub Kicinski release_firmware(fw); 25063461a02SJakub Kicinski 25163461a02SJakub Kicinski return err < 0 ? err : 1; 25263461a02SJakub Kicinski } 25363461a02SJakub Kicinski 254a9c83f7bSJakub Kicinski static int nfp_nsp_init(struct pci_dev *pdev, struct nfp_pf *pf) 255a9c83f7bSJakub Kicinski { 256010e2f9cSDavid Brunecz struct nfp_nsp_identify *nspi; 257a9c83f7bSJakub Kicinski struct nfp_nsp *nsp; 258a9c83f7bSJakub Kicinski int err; 259a9c83f7bSJakub Kicinski 260a9c83f7bSJakub Kicinski nsp = nfp_nsp_open(pf->cpp); 261a9c83f7bSJakub Kicinski if (IS_ERR(nsp)) { 262a9c83f7bSJakub Kicinski err = PTR_ERR(nsp); 263a9c83f7bSJakub Kicinski dev_err(&pdev->dev, "Failed to access the NSP: %d\n", err); 264a9c83f7bSJakub Kicinski return err; 265a9c83f7bSJakub Kicinski } 266a9c83f7bSJakub Kicinski 267a9c83f7bSJakub Kicinski err = nfp_nsp_wait(nsp); 268a9c83f7bSJakub Kicinski if (err < 0) 269a9c83f7bSJakub Kicinski goto exit_close_nsp; 270a9c83f7bSJakub Kicinski 271a9c83f7bSJakub Kicinski pf->eth_tbl = __nfp_eth_read_ports(pf->cpp, nsp); 272a9c83f7bSJakub Kicinski 273010e2f9cSDavid Brunecz nspi = __nfp_nsp_identify(nsp); 274010e2f9cSDavid Brunecz if (nspi) { 275010e2f9cSDavid Brunecz dev_info(&pdev->dev, "BSP: %s\n", nspi->version); 276010e2f9cSDavid Brunecz kfree(nspi); 277010e2f9cSDavid Brunecz } 278010e2f9cSDavid Brunecz 279a9c83f7bSJakub Kicinski err = nfp_fw_load(pdev, pf, nsp); 280a9c83f7bSJakub Kicinski if (err < 0) { 281a9c83f7bSJakub Kicinski kfree(pf->eth_tbl); 282a9c83f7bSJakub Kicinski dev_err(&pdev->dev, "Failed to load FW\n"); 283a9c83f7bSJakub Kicinski goto exit_close_nsp; 284a9c83f7bSJakub Kicinski } 285a9c83f7bSJakub Kicinski 286a9c83f7bSJakub Kicinski pf->fw_loaded = !!err; 287a9c83f7bSJakub Kicinski err = 0; 288a9c83f7bSJakub Kicinski 289a9c83f7bSJakub Kicinski exit_close_nsp: 290a9c83f7bSJakub Kicinski nfp_nsp_close(nsp); 291a9c83f7bSJakub Kicinski 292a9c83f7bSJakub Kicinski return err; 293a9c83f7bSJakub Kicinski } 294a9c83f7bSJakub Kicinski 29563461a02SJakub Kicinski static void nfp_fw_unload(struct nfp_pf *pf) 29663461a02SJakub Kicinski { 29763461a02SJakub Kicinski struct nfp_nsp *nsp; 29863461a02SJakub Kicinski int err; 29963461a02SJakub Kicinski 30063461a02SJakub Kicinski nsp = nfp_nsp_open(pf->cpp); 30163461a02SJakub Kicinski if (IS_ERR(nsp)) { 30263461a02SJakub Kicinski nfp_err(pf->cpp, "Reset failed, can't open NSP\n"); 30363461a02SJakub Kicinski return; 30463461a02SJakub Kicinski } 30563461a02SJakub Kicinski 30663461a02SJakub Kicinski err = nfp_nsp_device_soft_reset(nsp); 30763461a02SJakub Kicinski if (err < 0) 30863461a02SJakub Kicinski dev_warn(&pf->pdev->dev, "Couldn't unload firmware: %d\n", err); 30963461a02SJakub Kicinski else 31063461a02SJakub Kicinski dev_info(&pf->pdev->dev, "Firmware safely unloaded\n"); 31163461a02SJakub Kicinski 31263461a02SJakub Kicinski nfp_nsp_close(nsp); 31363461a02SJakub Kicinski } 31463461a02SJakub Kicinski 31563461a02SJakub Kicinski static int nfp_pci_probe(struct pci_dev *pdev, 31663461a02SJakub Kicinski const struct pci_device_id *pci_id) 31763461a02SJakub Kicinski { 31863461a02SJakub Kicinski struct nfp_pf *pf; 31963461a02SJakub Kicinski int err; 32063461a02SJakub Kicinski 32163461a02SJakub Kicinski err = pci_enable_device(pdev); 32263461a02SJakub Kicinski if (err < 0) 32363461a02SJakub Kicinski return err; 32463461a02SJakub Kicinski 32563461a02SJakub Kicinski pci_set_master(pdev); 32663461a02SJakub Kicinski 32763461a02SJakub Kicinski err = dma_set_mask_and_coherent(&pdev->dev, 32863461a02SJakub Kicinski DMA_BIT_MASK(NFP_NET_MAX_DMA_BITS)); 32963461a02SJakub Kicinski if (err) 33063461a02SJakub Kicinski goto err_pci_disable; 33163461a02SJakub Kicinski 33263461a02SJakub Kicinski err = pci_request_regions(pdev, nfp_driver_name); 33363461a02SJakub Kicinski if (err < 0) { 33463461a02SJakub Kicinski dev_err(&pdev->dev, "Unable to reserve pci resources.\n"); 33563461a02SJakub Kicinski goto err_pci_disable; 33663461a02SJakub Kicinski } 33763461a02SJakub Kicinski 33863461a02SJakub Kicinski pf = kzalloc(sizeof(*pf), GFP_KERNEL); 33963461a02SJakub Kicinski if (!pf) { 34063461a02SJakub Kicinski err = -ENOMEM; 34163461a02SJakub Kicinski goto err_rel_regions; 34263461a02SJakub Kicinski } 34363461a02SJakub Kicinski INIT_LIST_HEAD(&pf->ports); 34463461a02SJakub Kicinski pci_set_drvdata(pdev, pf); 34563461a02SJakub Kicinski pf->pdev = pdev; 34663461a02SJakub Kicinski 34763461a02SJakub Kicinski pf->cpp = nfp_cpp_from_nfp6000_pcie(pdev); 34863461a02SJakub Kicinski if (IS_ERR_OR_NULL(pf->cpp)) { 34963461a02SJakub Kicinski err = PTR_ERR(pf->cpp); 35063461a02SJakub Kicinski if (err >= 0) 35163461a02SJakub Kicinski err = -ENOMEM; 35263461a02SJakub Kicinski goto err_disable_msix; 35363461a02SJakub Kicinski } 35463461a02SJakub Kicinski 35564db09edSJakub Kicinski dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n", 35664db09edSJakub Kicinski nfp_hwinfo_lookup(pf->cpp, "assembly.vendor"), 35764db09edSJakub Kicinski nfp_hwinfo_lookup(pf->cpp, "assembly.partno"), 35864db09edSJakub Kicinski nfp_hwinfo_lookup(pf->cpp, "assembly.serial"), 35964db09edSJakub Kicinski nfp_hwinfo_lookup(pf->cpp, "assembly.revision"), 36064db09edSJakub Kicinski nfp_hwinfo_lookup(pf->cpp, "cpld.version")); 36164db09edSJakub Kicinski 362a9c83f7bSJakub Kicinski err = nfp_nsp_init(pdev, pf); 363a9c83f7bSJakub Kicinski if (err) 36463461a02SJakub Kicinski goto err_cpp_free; 36563461a02SJakub Kicinski 3660bc3827fSJakub Kicinski nfp_pcie_sriov_read_nfd_limit(pf); 3670bc3827fSJakub Kicinski 36863461a02SJakub Kicinski err = nfp_net_pci_probe(pf); 36963461a02SJakub Kicinski if (err) 37063461a02SJakub Kicinski goto err_fw_unload; 37163461a02SJakub Kicinski 37263461a02SJakub Kicinski return 0; 37363461a02SJakub Kicinski 37463461a02SJakub Kicinski err_fw_unload: 37563461a02SJakub Kicinski if (pf->fw_loaded) 37663461a02SJakub Kicinski nfp_fw_unload(pf); 37763461a02SJakub Kicinski kfree(pf->eth_tbl); 37863461a02SJakub Kicinski err_cpp_free: 37963461a02SJakub Kicinski nfp_cpp_free(pf->cpp); 38063461a02SJakub Kicinski err_disable_msix: 38163461a02SJakub Kicinski pci_set_drvdata(pdev, NULL); 38263461a02SJakub Kicinski kfree(pf); 38363461a02SJakub Kicinski err_rel_regions: 38463461a02SJakub Kicinski pci_release_regions(pdev); 38563461a02SJakub Kicinski err_pci_disable: 38663461a02SJakub Kicinski pci_disable_device(pdev); 38763461a02SJakub Kicinski 38863461a02SJakub Kicinski return err; 38963461a02SJakub Kicinski } 39063461a02SJakub Kicinski 39163461a02SJakub Kicinski static void nfp_pci_remove(struct pci_dev *pdev) 39263461a02SJakub Kicinski { 39363461a02SJakub Kicinski struct nfp_pf *pf = pci_get_drvdata(pdev); 39463461a02SJakub Kicinski 39563461a02SJakub Kicinski nfp_net_pci_remove(pf); 39663461a02SJakub Kicinski 39763461a02SJakub Kicinski nfp_pcie_sriov_disable(pdev); 39863461a02SJakub Kicinski 39963461a02SJakub Kicinski if (pf->fw_loaded) 40063461a02SJakub Kicinski nfp_fw_unload(pf); 40163461a02SJakub Kicinski 40263461a02SJakub Kicinski pci_set_drvdata(pdev, NULL); 40363461a02SJakub Kicinski nfp_cpp_free(pf->cpp); 40463461a02SJakub Kicinski 40563461a02SJakub Kicinski kfree(pf->eth_tbl); 40663461a02SJakub Kicinski kfree(pf); 40763461a02SJakub Kicinski pci_release_regions(pdev); 40863461a02SJakub Kicinski pci_disable_device(pdev); 40963461a02SJakub Kicinski } 41063461a02SJakub Kicinski 41163461a02SJakub Kicinski static struct pci_driver nfp_pci_driver = { 41263461a02SJakub Kicinski .name = nfp_driver_name, 41363461a02SJakub Kicinski .id_table = nfp_pci_device_ids, 41463461a02SJakub Kicinski .probe = nfp_pci_probe, 41563461a02SJakub Kicinski .remove = nfp_pci_remove, 41663461a02SJakub Kicinski .sriov_configure = nfp_pcie_sriov_configure, 41763461a02SJakub Kicinski }; 41863461a02SJakub Kicinski 4192633beb9SJakub Kicinski static int __init nfp_main_init(void) 4202633beb9SJakub Kicinski { 4212633beb9SJakub Kicinski int err; 4222633beb9SJakub Kicinski 4232633beb9SJakub Kicinski pr_info("%s: NFP PCIe Driver, Copyright (C) 2014-2017 Netronome Systems\n", 4242633beb9SJakub Kicinski nfp_driver_name); 4252633beb9SJakub Kicinski 4262633beb9SJakub Kicinski nfp_net_debugfs_create(); 4272633beb9SJakub Kicinski 42863461a02SJakub Kicinski err = pci_register_driver(&nfp_pci_driver); 42963461a02SJakub Kicinski if (err < 0) 43063461a02SJakub Kicinski goto err_destroy_debugfs; 43163461a02SJakub Kicinski 4322633beb9SJakub Kicinski err = pci_register_driver(&nfp_netvf_pci_driver); 4332633beb9SJakub Kicinski if (err) 43463461a02SJakub Kicinski goto err_unreg_pf; 4352633beb9SJakub Kicinski 4362633beb9SJakub Kicinski return err; 4372633beb9SJakub Kicinski 43863461a02SJakub Kicinski err_unreg_pf: 43963461a02SJakub Kicinski pci_unregister_driver(&nfp_pci_driver); 4402633beb9SJakub Kicinski err_destroy_debugfs: 4412633beb9SJakub Kicinski nfp_net_debugfs_destroy(); 4422633beb9SJakub Kicinski return err; 4432633beb9SJakub Kicinski } 4442633beb9SJakub Kicinski 4452633beb9SJakub Kicinski static void __exit nfp_main_exit(void) 4462633beb9SJakub Kicinski { 4472633beb9SJakub Kicinski pci_unregister_driver(&nfp_netvf_pci_driver); 44863461a02SJakub Kicinski pci_unregister_driver(&nfp_pci_driver); 4492633beb9SJakub Kicinski nfp_net_debugfs_destroy(); 4502633beb9SJakub Kicinski } 4512633beb9SJakub Kicinski 4522633beb9SJakub Kicinski module_init(nfp_main_init); 4532633beb9SJakub Kicinski module_exit(nfp_main_exit); 4542633beb9SJakub Kicinski 45563461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_1x40.nffw"); 45663461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_4x10.nffw"); 45763461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0096-0001_2x10.nffw"); 45863461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_2x40.nffw"); 45963461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_4x10_1x40.nffw"); 46063461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0097-0001_8x10.nffw"); 46163461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x10.nffw"); 46263461a02SJakub Kicinski MODULE_FIRMWARE("netronome/nic_AMDA0099-0001_2x25.nffw"); 46363461a02SJakub Kicinski 4642633beb9SJakub Kicinski MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>"); 4652633beb9SJakub Kicinski MODULE_LICENSE("GPL"); 4662633beb9SJakub Kicinski MODULE_DESCRIPTION("The Netronome Flow Processor (NFP) driver."); 467