1fe56b9e6SYuval Mintz /* QLogic qed NIC Driver 2e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 3fe56b9e6SYuval Mintz * 4e8f1cb50SMintz, Yuval * This software is available to you under a choice of one of two 5e8f1cb50SMintz, Yuval * licenses. You may choose to be licensed under the terms of the GNU 6e8f1cb50SMintz, Yuval * General Public License (GPL) Version 2, available from the file 7e8f1cb50SMintz, Yuval * COPYING in the main directory of this source tree, or the 8e8f1cb50SMintz, Yuval * OpenIB.org BSD license below: 9e8f1cb50SMintz, Yuval * 10e8f1cb50SMintz, Yuval * Redistribution and use in source and binary forms, with or 11e8f1cb50SMintz, Yuval * without modification, are permitted provided that the following 12e8f1cb50SMintz, Yuval * conditions are met: 13e8f1cb50SMintz, Yuval * 14e8f1cb50SMintz, Yuval * - Redistributions of source code must retain the above 15e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 16e8f1cb50SMintz, Yuval * disclaimer. 17e8f1cb50SMintz, Yuval * 18e8f1cb50SMintz, Yuval * - Redistributions in binary form must reproduce the above 19e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 20e8f1cb50SMintz, Yuval * disclaimer in the documentation and /or other materials 21e8f1cb50SMintz, Yuval * provided with the distribution. 22e8f1cb50SMintz, Yuval * 23e8f1cb50SMintz, Yuval * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e8f1cb50SMintz, Yuval * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e8f1cb50SMintz, Yuval * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e8f1cb50SMintz, Yuval * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e8f1cb50SMintz, Yuval * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e8f1cb50SMintz, Yuval * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e8f1cb50SMintz, Yuval * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e8f1cb50SMintz, Yuval * SOFTWARE. 31fe56b9e6SYuval Mintz */ 32fe56b9e6SYuval Mintz 33fe56b9e6SYuval Mintz #include <linux/stddef.h> 34fe56b9e6SYuval Mintz #include <linux/pci.h> 35fe56b9e6SYuval Mintz #include <linux/kernel.h> 36fe56b9e6SYuval Mintz #include <linux/slab.h> 37fe56b9e6SYuval Mintz #include <linux/delay.h> 38fe56b9e6SYuval Mintz #include <asm/byteorder.h> 39fe56b9e6SYuval Mintz #include <linux/dma-mapping.h> 40fe56b9e6SYuval Mintz #include <linux/string.h> 41fe56b9e6SYuval Mintz #include <linux/module.h> 42fe56b9e6SYuval Mintz #include <linux/interrupt.h> 43fe56b9e6SYuval Mintz #include <linux/workqueue.h> 44fe56b9e6SYuval Mintz #include <linux/ethtool.h> 45fe56b9e6SYuval Mintz #include <linux/etherdevice.h> 46fe56b9e6SYuval Mintz #include <linux/vmalloc.h> 475d24bcf1STomer Tayar #include <linux/crash_dump.h> 48fe56b9e6SYuval Mintz #include <linux/qed/qed_if.h> 490a7fb11cSYuval Mintz #include <linux/qed/qed_ll2_if.h> 50fe56b9e6SYuval Mintz 51fe56b9e6SYuval Mintz #include "qed.h" 5237bff2b9SYuval Mintz #include "qed_sriov.h" 53fe56b9e6SYuval Mintz #include "qed_sp.h" 54fe56b9e6SYuval Mintz #include "qed_dev_api.h" 550a7fb11cSYuval Mintz #include "qed_ll2.h" 561e128c81SArun Easi #include "qed_fcoe.h" 572f2b2614SMintz, Yuval #include "qed_iscsi.h" 582f2b2614SMintz, Yuval 59fe56b9e6SYuval Mintz #include "qed_mcp.h" 60fe56b9e6SYuval Mintz #include "qed_hw.h" 6103dc76caSSudarsana Reddy Kalluru #include "qed_selftest.h" 621e128c81SArun Easi #include "qed_debug.h" 63fe56b9e6SYuval Mintz 6451ff1725SRam Amrani #define QED_ROCE_QPS (8192) 6551ff1725SRam Amrani #define QED_ROCE_DPIS (8) 6651ff1725SRam Amrani 675abd7e92SYuval Mintz static char version[] = 685abd7e92SYuval Mintz "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n"; 69fe56b9e6SYuval Mintz 705abd7e92SYuval Mintz MODULE_DESCRIPTION("QLogic FastLinQ 4xxxx Core Module"); 71fe56b9e6SYuval Mintz MODULE_LICENSE("GPL"); 72fe56b9e6SYuval Mintz MODULE_VERSION(DRV_MODULE_VERSION); 73fe56b9e6SYuval Mintz 74fe56b9e6SYuval Mintz #define FW_FILE_VERSION \ 75fe56b9e6SYuval Mintz __stringify(FW_MAJOR_VERSION) "." \ 76fe56b9e6SYuval Mintz __stringify(FW_MINOR_VERSION) "." \ 77fe56b9e6SYuval Mintz __stringify(FW_REVISION_VERSION) "." \ 78fe56b9e6SYuval Mintz __stringify(FW_ENGINEERING_VERSION) 79fe56b9e6SYuval Mintz 80fe56b9e6SYuval Mintz #define QED_FW_FILE_NAME \ 81fe56b9e6SYuval Mintz "qed/qed_init_values_zipped-" FW_FILE_VERSION ".bin" 82fe56b9e6SYuval Mintz 83d43d3f0fSYuval Mintz MODULE_FIRMWARE(QED_FW_FILE_NAME); 84d43d3f0fSYuval Mintz 85fe56b9e6SYuval Mintz static int __init qed_init(void) 86fe56b9e6SYuval Mintz { 87fe56b9e6SYuval Mintz pr_info("%s", version); 88fe56b9e6SYuval Mintz 89fe56b9e6SYuval Mintz return 0; 90fe56b9e6SYuval Mintz } 91fe56b9e6SYuval Mintz 92fe56b9e6SYuval Mintz static void __exit qed_cleanup(void) 93fe56b9e6SYuval Mintz { 94fe56b9e6SYuval Mintz pr_notice("qed_cleanup called\n"); 95fe56b9e6SYuval Mintz } 96fe56b9e6SYuval Mintz 97fe56b9e6SYuval Mintz module_init(qed_init); 98fe56b9e6SYuval Mintz module_exit(qed_cleanup); 99fe56b9e6SYuval Mintz 100fe56b9e6SYuval Mintz /* Check if the DMA controller on the machine can properly handle the DMA 101fe56b9e6SYuval Mintz * addressing required by the device. 102fe56b9e6SYuval Mintz */ 103fe56b9e6SYuval Mintz static int qed_set_coherency_mask(struct qed_dev *cdev) 104fe56b9e6SYuval Mintz { 105fe56b9e6SYuval Mintz struct device *dev = &cdev->pdev->dev; 106fe56b9e6SYuval Mintz 107fe56b9e6SYuval Mintz if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) { 108fe56b9e6SYuval Mintz if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) { 109fe56b9e6SYuval Mintz DP_NOTICE(cdev, 110fe56b9e6SYuval Mintz "Can't request 64-bit consistent allocations\n"); 111fe56b9e6SYuval Mintz return -EIO; 112fe56b9e6SYuval Mintz } 113fe56b9e6SYuval Mintz } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) { 114fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Can't request 64b/32b DMA addresses\n"); 115fe56b9e6SYuval Mintz return -EIO; 116fe56b9e6SYuval Mintz } 117fe56b9e6SYuval Mintz 118fe56b9e6SYuval Mintz return 0; 119fe56b9e6SYuval Mintz } 120fe56b9e6SYuval Mintz 121fe56b9e6SYuval Mintz static void qed_free_pci(struct qed_dev *cdev) 122fe56b9e6SYuval Mintz { 123fe56b9e6SYuval Mintz struct pci_dev *pdev = cdev->pdev; 124fe56b9e6SYuval Mintz 125fe56b9e6SYuval Mintz if (cdev->doorbells) 126fe56b9e6SYuval Mintz iounmap(cdev->doorbells); 127fe56b9e6SYuval Mintz if (cdev->regview) 128fe56b9e6SYuval Mintz iounmap(cdev->regview); 129fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) 130fe56b9e6SYuval Mintz pci_release_regions(pdev); 131fe56b9e6SYuval Mintz 132fe56b9e6SYuval Mintz pci_disable_device(pdev); 133fe56b9e6SYuval Mintz } 134fe56b9e6SYuval Mintz 1350dfaba6dSYuval Mintz #define PCI_REVISION_ID_ERROR_VAL 0xff 1360dfaba6dSYuval Mintz 137fe56b9e6SYuval Mintz /* Performs PCI initializations as well as initializing PCI-related parameters 138fe56b9e6SYuval Mintz * in the device structrue. Returns 0 in case of success. 139fe56b9e6SYuval Mintz */ 1401a635e48SYuval Mintz static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev) 141fe56b9e6SYuval Mintz { 1420dfaba6dSYuval Mintz u8 rev_id; 143fe56b9e6SYuval Mintz int rc; 144fe56b9e6SYuval Mintz 145fe56b9e6SYuval Mintz cdev->pdev = pdev; 146fe56b9e6SYuval Mintz 147fe56b9e6SYuval Mintz rc = pci_enable_device(pdev); 148fe56b9e6SYuval Mintz if (rc) { 149fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot enable PCI device\n"); 150fe56b9e6SYuval Mintz goto err0; 151fe56b9e6SYuval Mintz } 152fe56b9e6SYuval Mintz 153fe56b9e6SYuval Mintz if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 154fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #0\n"); 155fe56b9e6SYuval Mintz rc = -EIO; 156fe56b9e6SYuval Mintz goto err1; 157fe56b9e6SYuval Mintz } 158fe56b9e6SYuval Mintz 1591408cc1fSYuval Mintz if (IS_PF(cdev) && !(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { 160fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #2\n"); 161fe56b9e6SYuval Mintz rc = -EIO; 162fe56b9e6SYuval Mintz goto err1; 163fe56b9e6SYuval Mintz } 164fe56b9e6SYuval Mintz 165fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) { 166fe56b9e6SYuval Mintz rc = pci_request_regions(pdev, "qed"); 167fe56b9e6SYuval Mintz if (rc) { 168fe56b9e6SYuval Mintz DP_NOTICE(cdev, 169fe56b9e6SYuval Mintz "Failed to request PCI memory resources\n"); 170fe56b9e6SYuval Mintz goto err1; 171fe56b9e6SYuval Mintz } 172fe56b9e6SYuval Mintz pci_set_master(pdev); 173fe56b9e6SYuval Mintz pci_save_state(pdev); 174fe56b9e6SYuval Mintz } 175fe56b9e6SYuval Mintz 1760dfaba6dSYuval Mintz pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); 1770dfaba6dSYuval Mintz if (rev_id == PCI_REVISION_ID_ERROR_VAL) { 1780dfaba6dSYuval Mintz DP_NOTICE(cdev, 1790dfaba6dSYuval Mintz "Detected PCI device error [rev_id 0x%x]. Probably due to prior indication. Aborting.\n", 1800dfaba6dSYuval Mintz rev_id); 1810dfaba6dSYuval Mintz rc = -ENODEV; 1820dfaba6dSYuval Mintz goto err2; 1830dfaba6dSYuval Mintz } 184fe56b9e6SYuval Mintz if (!pci_is_pcie(pdev)) { 185fe56b9e6SYuval Mintz DP_NOTICE(cdev, "The bus is not PCI Express\n"); 186fe56b9e6SYuval Mintz rc = -EIO; 187fe56b9e6SYuval Mintz goto err2; 188fe56b9e6SYuval Mintz } 189fe56b9e6SYuval Mintz 190fe56b9e6SYuval Mintz cdev->pci_params.pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); 191416cdf06SYuval Mintz if (IS_PF(cdev) && !cdev->pci_params.pm_cap) 192fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot find power management capability\n"); 193fe56b9e6SYuval Mintz 194fe56b9e6SYuval Mintz rc = qed_set_coherency_mask(cdev); 195fe56b9e6SYuval Mintz if (rc) 196fe56b9e6SYuval Mintz goto err2; 197fe56b9e6SYuval Mintz 198fe56b9e6SYuval Mintz cdev->pci_params.mem_start = pci_resource_start(pdev, 0); 199fe56b9e6SYuval Mintz cdev->pci_params.mem_end = pci_resource_end(pdev, 0); 200fe56b9e6SYuval Mintz cdev->pci_params.irq = pdev->irq; 201fe56b9e6SYuval Mintz 202fe56b9e6SYuval Mintz cdev->regview = pci_ioremap_bar(pdev, 0); 203fe56b9e6SYuval Mintz if (!cdev->regview) { 204fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map register space, aborting\n"); 205fe56b9e6SYuval Mintz rc = -ENOMEM; 206fe56b9e6SYuval Mintz goto err2; 207fe56b9e6SYuval Mintz } 208fe56b9e6SYuval Mintz 2091408cc1fSYuval Mintz if (IS_PF(cdev)) { 210fe56b9e6SYuval Mintz cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2); 211fe56b9e6SYuval Mintz cdev->db_size = pci_resource_len(cdev->pdev, 2); 212fe56b9e6SYuval Mintz cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size); 213fe56b9e6SYuval Mintz if (!cdev->doorbells) { 214fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map doorbell space\n"); 215fe56b9e6SYuval Mintz return -ENOMEM; 216fe56b9e6SYuval Mintz } 2171408cc1fSYuval Mintz } 218fe56b9e6SYuval Mintz 219fe56b9e6SYuval Mintz return 0; 220fe56b9e6SYuval Mintz 221fe56b9e6SYuval Mintz err2: 222fe56b9e6SYuval Mintz pci_release_regions(pdev); 223fe56b9e6SYuval Mintz err1: 224fe56b9e6SYuval Mintz pci_disable_device(pdev); 225fe56b9e6SYuval Mintz err0: 226fe56b9e6SYuval Mintz return rc; 227fe56b9e6SYuval Mintz } 228fe56b9e6SYuval Mintz 229fe56b9e6SYuval Mintz int qed_fill_dev_info(struct qed_dev *cdev, 230fe56b9e6SYuval Mintz struct qed_dev_info *dev_info) 231fe56b9e6SYuval Mintz { 23219489c7fSChopra, Manish struct qed_tunnel_info *tun = &cdev->tunnel; 233cee4d264SManish Chopra struct qed_ptt *ptt; 234cee4d264SManish Chopra 235fe56b9e6SYuval Mintz memset(dev_info, 0, sizeof(struct qed_dev_info)); 236fe56b9e6SYuval Mintz 23719489c7fSChopra, Manish if (tun->vxlan.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 23819489c7fSChopra, Manish tun->vxlan.b_mode_enabled) 23919489c7fSChopra, Manish dev_info->vxlan_enable = true; 24019489c7fSChopra, Manish 24119489c7fSChopra, Manish if (tun->l2_gre.b_mode_enabled && tun->ip_gre.b_mode_enabled && 24219489c7fSChopra, Manish tun->l2_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 24319489c7fSChopra, Manish tun->ip_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 24419489c7fSChopra, Manish dev_info->gre_enable = true; 24519489c7fSChopra, Manish 24619489c7fSChopra, Manish if (tun->l2_geneve.b_mode_enabled && tun->ip_geneve.b_mode_enabled && 24719489c7fSChopra, Manish tun->l2_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 24819489c7fSChopra, Manish tun->ip_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 24919489c7fSChopra, Manish dev_info->geneve_enable = true; 25019489c7fSChopra, Manish 251fe56b9e6SYuval Mintz dev_info->num_hwfns = cdev->num_hwfns; 252fe56b9e6SYuval Mintz dev_info->pci_mem_start = cdev->pci_params.mem_start; 253fe56b9e6SYuval Mintz dev_info->pci_mem_end = cdev->pci_params.mem_end; 254fe56b9e6SYuval Mintz dev_info->pci_irq = cdev->pci_params.irq; 25551ff1725SRam Amrani dev_info->rdma_supported = (cdev->hwfns[0].hw_info.personality == 25651ff1725SRam Amrani QED_PCI_ETH_ROCE); 257fc48b7a6SYuval Mintz dev_info->is_mf_default = IS_MF_DEFAULT(&cdev->hwfns[0]); 2589c79ddaaSMintz, Yuval dev_info->dev_type = cdev->type; 259fe56b9e6SYuval Mintz ether_addr_copy(dev_info->hw_mac, cdev->hwfns[0].hw_info.hw_mac_addr); 260fe56b9e6SYuval Mintz 2611408cc1fSYuval Mintz if (IS_PF(cdev)) { 262fe56b9e6SYuval Mintz dev_info->fw_major = FW_MAJOR_VERSION; 263fe56b9e6SYuval Mintz dev_info->fw_minor = FW_MINOR_VERSION; 264fe56b9e6SYuval Mintz dev_info->fw_rev = FW_REVISION_VERSION; 265fe56b9e6SYuval Mintz dev_info->fw_eng = FW_ENGINEERING_VERSION; 266fe56b9e6SYuval Mintz dev_info->mf_mode = cdev->mf_mode; 267831bfb0eSYuval Mintz dev_info->tx_switching = true; 26814d39648SMintz, Yuval 26914d39648SMintz, Yuval if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support == 27014d39648SMintz, Yuval QED_WOL_SUPPORT_PME) 27114d39648SMintz, Yuval dev_info->wol_support = true; 2721408cc1fSYuval Mintz } else { 2731408cc1fSYuval Mintz qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, 2741408cc1fSYuval Mintz &dev_info->fw_minor, &dev_info->fw_rev, 2751408cc1fSYuval Mintz &dev_info->fw_eng); 2761408cc1fSYuval Mintz } 277fe56b9e6SYuval Mintz 2781408cc1fSYuval Mintz if (IS_PF(cdev)) { 279cee4d264SManish Chopra ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 280cee4d264SManish Chopra if (ptt) { 2811408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), ptt, 2821408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 2831408cc1fSYuval Mintz 284ae33666aSTomer Tayar qed_mcp_get_mbi_ver(QED_LEADING_HWFN(cdev), ptt, 285ae33666aSTomer Tayar &dev_info->mbi_version); 286ae33666aSTomer Tayar 287cee4d264SManish Chopra qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt, 288cee4d264SManish Chopra &dev_info->flash_size); 289cee4d264SManish Chopra 290cee4d264SManish Chopra qed_ptt_release(QED_LEADING_HWFN(cdev), ptt); 291cee4d264SManish Chopra } 2921408cc1fSYuval Mintz } else { 2931408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), NULL, 2941408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 2951408cc1fSYuval Mintz } 296cee4d264SManish Chopra 2970fefbfbaSSudarsana Kalluru dev_info->mtu = QED_LEADING_HWFN(cdev)->hw_info.mtu; 2980fefbfbaSSudarsana Kalluru 299fe56b9e6SYuval Mintz return 0; 300fe56b9e6SYuval Mintz } 301fe56b9e6SYuval Mintz 302fe56b9e6SYuval Mintz static void qed_free_cdev(struct qed_dev *cdev) 303fe56b9e6SYuval Mintz { 304fe56b9e6SYuval Mintz kfree((void *)cdev); 305fe56b9e6SYuval Mintz } 306fe56b9e6SYuval Mintz 307fe56b9e6SYuval Mintz static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev) 308fe56b9e6SYuval Mintz { 309fe56b9e6SYuval Mintz struct qed_dev *cdev; 310fe56b9e6SYuval Mintz 311fe56b9e6SYuval Mintz cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 312fe56b9e6SYuval Mintz if (!cdev) 313fe56b9e6SYuval Mintz return cdev; 314fe56b9e6SYuval Mintz 315fe56b9e6SYuval Mintz qed_init_struct(cdev); 316fe56b9e6SYuval Mintz 317fe56b9e6SYuval Mintz return cdev; 318fe56b9e6SYuval Mintz } 319fe56b9e6SYuval Mintz 320fe56b9e6SYuval Mintz /* Sets the requested power state */ 3211a635e48SYuval Mintz static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state) 322fe56b9e6SYuval Mintz { 323fe56b9e6SYuval Mintz if (!cdev) 324fe56b9e6SYuval Mintz return -ENODEV; 325fe56b9e6SYuval Mintz 326fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n"); 327fe56b9e6SYuval Mintz return 0; 328fe56b9e6SYuval Mintz } 329fe56b9e6SYuval Mintz 330fe56b9e6SYuval Mintz /* probing */ 331fe56b9e6SYuval Mintz static struct qed_dev *qed_probe(struct pci_dev *pdev, 3321408cc1fSYuval Mintz struct qed_probe_params *params) 333fe56b9e6SYuval Mintz { 334fe56b9e6SYuval Mintz struct qed_dev *cdev; 335fe56b9e6SYuval Mintz int rc; 336fe56b9e6SYuval Mintz 337fe56b9e6SYuval Mintz cdev = qed_alloc_cdev(pdev); 338fe56b9e6SYuval Mintz if (!cdev) 339fe56b9e6SYuval Mintz goto err0; 340fe56b9e6SYuval Mintz 341712c3cbfSMintz, Yuval cdev->drv_type = DRV_ID_DRV_TYPE_LINUX; 3421408cc1fSYuval Mintz cdev->protocol = params->protocol; 343fe56b9e6SYuval Mintz 3441408cc1fSYuval Mintz if (params->is_vf) 3451408cc1fSYuval Mintz cdev->b_is_vf = true; 3461408cc1fSYuval Mintz 3471408cc1fSYuval Mintz qed_init_dp(cdev, params->dp_module, params->dp_level); 348fe56b9e6SYuval Mintz 349fe56b9e6SYuval Mintz rc = qed_init_pci(cdev, pdev); 350fe56b9e6SYuval Mintz if (rc) { 351fe56b9e6SYuval Mintz DP_ERR(cdev, "init pci failed\n"); 352fe56b9e6SYuval Mintz goto err1; 353fe56b9e6SYuval Mintz } 354fe56b9e6SYuval Mintz DP_INFO(cdev, "PCI init completed successfully\n"); 355fe56b9e6SYuval Mintz 356fe56b9e6SYuval Mintz rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); 357fe56b9e6SYuval Mintz if (rc) { 358fe56b9e6SYuval Mintz DP_ERR(cdev, "hw prepare failed\n"); 359fe56b9e6SYuval Mintz goto err2; 360fe56b9e6SYuval Mintz } 361fe56b9e6SYuval Mintz 362fe56b9e6SYuval Mintz DP_INFO(cdev, "qed_probe completed successffuly\n"); 363fe56b9e6SYuval Mintz 364fe56b9e6SYuval Mintz return cdev; 365fe56b9e6SYuval Mintz 366fe56b9e6SYuval Mintz err2: 367fe56b9e6SYuval Mintz qed_free_pci(cdev); 368fe56b9e6SYuval Mintz err1: 369fe56b9e6SYuval Mintz qed_free_cdev(cdev); 370fe56b9e6SYuval Mintz err0: 371fe56b9e6SYuval Mintz return NULL; 372fe56b9e6SYuval Mintz } 373fe56b9e6SYuval Mintz 374fe56b9e6SYuval Mintz static void qed_remove(struct qed_dev *cdev) 375fe56b9e6SYuval Mintz { 376fe56b9e6SYuval Mintz if (!cdev) 377fe56b9e6SYuval Mintz return; 378fe56b9e6SYuval Mintz 379fe56b9e6SYuval Mintz qed_hw_remove(cdev); 380fe56b9e6SYuval Mintz 381fe56b9e6SYuval Mintz qed_free_pci(cdev); 382fe56b9e6SYuval Mintz 383fe56b9e6SYuval Mintz qed_set_power_state(cdev, PCI_D3hot); 384fe56b9e6SYuval Mintz 385fe56b9e6SYuval Mintz qed_free_cdev(cdev); 386fe56b9e6SYuval Mintz } 387fe56b9e6SYuval Mintz 388fe56b9e6SYuval Mintz static void qed_disable_msix(struct qed_dev *cdev) 389fe56b9e6SYuval Mintz { 390fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 391fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 392fe56b9e6SYuval Mintz kfree(cdev->int_params.msix_table); 393fe56b9e6SYuval Mintz } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) { 394fe56b9e6SYuval Mintz pci_disable_msi(cdev->pdev); 395fe56b9e6SYuval Mintz } 396fe56b9e6SYuval Mintz 397fe56b9e6SYuval Mintz memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param)); 398fe56b9e6SYuval Mintz } 399fe56b9e6SYuval Mintz 400fe56b9e6SYuval Mintz static int qed_enable_msix(struct qed_dev *cdev, 401fe56b9e6SYuval Mintz struct qed_int_params *int_params) 402fe56b9e6SYuval Mintz { 403fe56b9e6SYuval Mintz int i, rc, cnt; 404fe56b9e6SYuval Mintz 405fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 406fe56b9e6SYuval Mintz 407fe56b9e6SYuval Mintz for (i = 0; i < cnt; i++) 408fe56b9e6SYuval Mintz int_params->msix_table[i].entry = i; 409fe56b9e6SYuval Mintz 410fe56b9e6SYuval Mintz rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table, 411fe56b9e6SYuval Mintz int_params->in.min_msix_cnt, cnt); 412fe56b9e6SYuval Mintz if (rc < cnt && rc >= int_params->in.min_msix_cnt && 413fe56b9e6SYuval Mintz (rc % cdev->num_hwfns)) { 414fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 415fe56b9e6SYuval Mintz 416fe56b9e6SYuval Mintz /* If fastpath is initialized, we need at least one interrupt 417fe56b9e6SYuval Mintz * per hwfn [and the slow path interrupts]. New requested number 418fe56b9e6SYuval Mintz * should be a multiple of the number of hwfns. 419fe56b9e6SYuval Mintz */ 420fe56b9e6SYuval Mintz cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns; 421fe56b9e6SYuval Mintz DP_NOTICE(cdev, 422fe56b9e6SYuval Mintz "Trying to enable MSI-X with less vectors (%d out of %d)\n", 423fe56b9e6SYuval Mintz cnt, int_params->in.num_vectors); 4241a635e48SYuval Mintz rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table, 4251a635e48SYuval Mintz cnt); 426fe56b9e6SYuval Mintz if (!rc) 427fe56b9e6SYuval Mintz rc = cnt; 428fe56b9e6SYuval Mintz } 429fe56b9e6SYuval Mintz 430fe56b9e6SYuval Mintz if (rc > 0) { 431fe56b9e6SYuval Mintz /* MSI-x configuration was achieved */ 432fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSIX; 433fe56b9e6SYuval Mintz int_params->out.num_vectors = rc; 434fe56b9e6SYuval Mintz rc = 0; 435fe56b9e6SYuval Mintz } else { 436fe56b9e6SYuval Mintz DP_NOTICE(cdev, 437fe56b9e6SYuval Mintz "Failed to enable MSI-X [Requested %d vectors][rc %d]\n", 438fe56b9e6SYuval Mintz cnt, rc); 439fe56b9e6SYuval Mintz } 440fe56b9e6SYuval Mintz 441fe56b9e6SYuval Mintz return rc; 442fe56b9e6SYuval Mintz } 443fe56b9e6SYuval Mintz 444fe56b9e6SYuval Mintz /* This function outputs the int mode and the number of enabled msix vector */ 445fe56b9e6SYuval Mintz static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) 446fe56b9e6SYuval Mintz { 447fe56b9e6SYuval Mintz struct qed_int_params *int_params = &cdev->int_params; 448fe56b9e6SYuval Mintz struct msix_entry *tbl; 449fe56b9e6SYuval Mintz int rc = 0, cnt; 450fe56b9e6SYuval Mintz 451fe56b9e6SYuval Mintz switch (int_params->in.int_mode) { 452fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 453fe56b9e6SYuval Mintz /* Allocate MSIX table */ 454fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 455fe56b9e6SYuval Mintz int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL); 456fe56b9e6SYuval Mintz if (!int_params->msix_table) { 457fe56b9e6SYuval Mintz rc = -ENOMEM; 458fe56b9e6SYuval Mintz goto out; 459fe56b9e6SYuval Mintz } 460fe56b9e6SYuval Mintz 461fe56b9e6SYuval Mintz /* Enable MSIX */ 462fe56b9e6SYuval Mintz rc = qed_enable_msix(cdev, int_params); 463fe56b9e6SYuval Mintz if (!rc) 464fe56b9e6SYuval Mintz goto out; 465fe56b9e6SYuval Mintz 466fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI-X\n"); 467fe56b9e6SYuval Mintz kfree(int_params->msix_table); 468fe56b9e6SYuval Mintz if (force_mode) 469fe56b9e6SYuval Mintz goto out; 470fe56b9e6SYuval Mintz /* Fallthrough */ 471fe56b9e6SYuval Mintz 472fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 473bb13ace7SSudarsana Reddy Kalluru if (cdev->num_hwfns == 1) { 474fe56b9e6SYuval Mintz rc = pci_enable_msi(cdev->pdev); 475fe56b9e6SYuval Mintz if (!rc) { 476fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSI; 477fe56b9e6SYuval Mintz goto out; 478fe56b9e6SYuval Mintz } 479fe56b9e6SYuval Mintz 480fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI\n"); 481fe56b9e6SYuval Mintz if (force_mode) 482fe56b9e6SYuval Mintz goto out; 483bb13ace7SSudarsana Reddy Kalluru } 484fe56b9e6SYuval Mintz /* Fallthrough */ 485fe56b9e6SYuval Mintz 486fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 487fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_INTA; 488fe56b9e6SYuval Mintz rc = 0; 489fe56b9e6SYuval Mintz goto out; 490fe56b9e6SYuval Mintz default: 491fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Unknown int_mode value %d\n", 492fe56b9e6SYuval Mintz int_params->in.int_mode); 493fe56b9e6SYuval Mintz rc = -EINVAL; 494fe56b9e6SYuval Mintz } 495fe56b9e6SYuval Mintz 496fe56b9e6SYuval Mintz out: 497525ef5c0SYuval Mintz if (!rc) 498525ef5c0SYuval Mintz DP_INFO(cdev, "Using %s interrupts\n", 499525ef5c0SYuval Mintz int_params->out.int_mode == QED_INT_MODE_INTA ? 500525ef5c0SYuval Mintz "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ? 501525ef5c0SYuval Mintz "MSI" : "MSIX"); 502fe56b9e6SYuval Mintz cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE; 503fe56b9e6SYuval Mintz 504fe56b9e6SYuval Mintz return rc; 505fe56b9e6SYuval Mintz } 506fe56b9e6SYuval Mintz 507fe56b9e6SYuval Mintz static void qed_simd_handler_config(struct qed_dev *cdev, void *token, 508fe56b9e6SYuval Mintz int index, void(*handler)(void *)) 509fe56b9e6SYuval Mintz { 510fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 511fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 512fe56b9e6SYuval Mintz 513fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].func = handler; 514fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].token = token; 515fe56b9e6SYuval Mintz } 516fe56b9e6SYuval Mintz 517fe56b9e6SYuval Mintz static void qed_simd_handler_clean(struct qed_dev *cdev, int index) 518fe56b9e6SYuval Mintz { 519fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 520fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 521fe56b9e6SYuval Mintz 522fe56b9e6SYuval Mintz memset(&hwfn->simd_proto_handler[relative_idx], 0, 523fe56b9e6SYuval Mintz sizeof(struct qed_simd_fp_handler)); 524fe56b9e6SYuval Mintz } 525fe56b9e6SYuval Mintz 526fe56b9e6SYuval Mintz static irqreturn_t qed_msix_sp_int(int irq, void *tasklet) 527fe56b9e6SYuval Mintz { 528fe56b9e6SYuval Mintz tasklet_schedule((struct tasklet_struct *)tasklet); 529fe56b9e6SYuval Mintz return IRQ_HANDLED; 530fe56b9e6SYuval Mintz } 531fe56b9e6SYuval Mintz 532fe56b9e6SYuval Mintz static irqreturn_t qed_single_int(int irq, void *dev_instance) 533fe56b9e6SYuval Mintz { 534fe56b9e6SYuval Mintz struct qed_dev *cdev = (struct qed_dev *)dev_instance; 535fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 536fe56b9e6SYuval Mintz irqreturn_t rc = IRQ_NONE; 537fe56b9e6SYuval Mintz u64 status; 538fe56b9e6SYuval Mintz int i, j; 539fe56b9e6SYuval Mintz 540fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 541fe56b9e6SYuval Mintz status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]); 542fe56b9e6SYuval Mintz 543fe56b9e6SYuval Mintz if (!status) 544fe56b9e6SYuval Mintz continue; 545fe56b9e6SYuval Mintz 546fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 547fe56b9e6SYuval Mintz 548fe56b9e6SYuval Mintz /* Slowpath interrupt */ 549fe56b9e6SYuval Mintz if (unlikely(status & 0x1)) { 550fe56b9e6SYuval Mintz tasklet_schedule(hwfn->sp_dpc); 551fe56b9e6SYuval Mintz status &= ~0x1; 552fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 553fe56b9e6SYuval Mintz } 554fe56b9e6SYuval Mintz 555fe56b9e6SYuval Mintz /* Fastpath interrupts */ 556fe56b9e6SYuval Mintz for (j = 0; j < 64; j++) { 557fe56b9e6SYuval Mintz if ((0x2ULL << j) & status) { 558fe56b9e6SYuval Mintz hwfn->simd_proto_handler[j].func( 559fe56b9e6SYuval Mintz hwfn->simd_proto_handler[j].token); 560fe56b9e6SYuval Mintz status &= ~(0x2ULL << j); 561fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 562fe56b9e6SYuval Mintz } 563fe56b9e6SYuval Mintz } 564fe56b9e6SYuval Mintz 565fe56b9e6SYuval Mintz if (unlikely(status)) 566fe56b9e6SYuval Mintz DP_VERBOSE(hwfn, NETIF_MSG_INTR, 567fe56b9e6SYuval Mintz "got an unknown interrupt status 0x%llx\n", 568fe56b9e6SYuval Mintz status); 569fe56b9e6SYuval Mintz } 570fe56b9e6SYuval Mintz 571fe56b9e6SYuval Mintz return rc; 572fe56b9e6SYuval Mintz } 573fe56b9e6SYuval Mintz 5748f16bc97SSudarsana Kalluru int qed_slowpath_irq_req(struct qed_hwfn *hwfn) 575fe56b9e6SYuval Mintz { 5768f16bc97SSudarsana Kalluru struct qed_dev *cdev = hwfn->cdev; 577525ef5c0SYuval Mintz u32 int_mode; 5788f16bc97SSudarsana Kalluru int rc = 0; 5798f16bc97SSudarsana Kalluru u8 id; 580fe56b9e6SYuval Mintz 581525ef5c0SYuval Mintz int_mode = cdev->int_params.out.int_mode; 582525ef5c0SYuval Mintz if (int_mode == QED_INT_MODE_MSIX) { 5838f16bc97SSudarsana Kalluru id = hwfn->my_id; 5848f16bc97SSudarsana Kalluru snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x", 5858f16bc97SSudarsana Kalluru id, cdev->pdev->bus->number, 5868f16bc97SSudarsana Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 5878f16bc97SSudarsana Kalluru rc = request_irq(cdev->int_params.msix_table[id].vector, 5888f16bc97SSudarsana Kalluru qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); 589fe56b9e6SYuval Mintz } else { 590fe56b9e6SYuval Mintz unsigned long flags = 0; 591fe56b9e6SYuval Mintz 592fe56b9e6SYuval Mintz snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x", 593fe56b9e6SYuval Mintz cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), 594fe56b9e6SYuval Mintz PCI_FUNC(cdev->pdev->devfn)); 595fe56b9e6SYuval Mintz 596fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA) 597fe56b9e6SYuval Mintz flags |= IRQF_SHARED; 598fe56b9e6SYuval Mintz 599fe56b9e6SYuval Mintz rc = request_irq(cdev->pdev->irq, qed_single_int, 600fe56b9e6SYuval Mintz flags, cdev->name, cdev); 601fe56b9e6SYuval Mintz } 602fe56b9e6SYuval Mintz 603525ef5c0SYuval Mintz if (rc) 604525ef5c0SYuval Mintz DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc); 605525ef5c0SYuval Mintz else 606525ef5c0SYuval Mintz DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP), 607525ef5c0SYuval Mintz "Requested slowpath %s\n", 608525ef5c0SYuval Mintz (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ"); 609525ef5c0SYuval Mintz 610fe56b9e6SYuval Mintz return rc; 611fe56b9e6SYuval Mintz } 612fe56b9e6SYuval Mintz 61306892f2eSTomer Tayar static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn) 61406892f2eSTomer Tayar { 61506892f2eSTomer Tayar /* Calling the disable function will make sure that any 61606892f2eSTomer Tayar * currently-running function is completed. The following call to the 61706892f2eSTomer Tayar * enable function makes this sequence a flush-like operation. 61806892f2eSTomer Tayar */ 61906892f2eSTomer Tayar if (p_hwfn->b_sp_dpc_enabled) { 62006892f2eSTomer Tayar tasklet_disable(p_hwfn->sp_dpc); 62106892f2eSTomer Tayar tasklet_enable(p_hwfn->sp_dpc); 62206892f2eSTomer Tayar } 62306892f2eSTomer Tayar } 62406892f2eSTomer Tayar 6251226337aSTomer Tayar void qed_slowpath_irq_sync(struct qed_hwfn *p_hwfn) 6261226337aSTomer Tayar { 6271226337aSTomer Tayar struct qed_dev *cdev = p_hwfn->cdev; 6281226337aSTomer Tayar u8 id = p_hwfn->my_id; 6291226337aSTomer Tayar u32 int_mode; 6301226337aSTomer Tayar 6311226337aSTomer Tayar int_mode = cdev->int_params.out.int_mode; 6321226337aSTomer Tayar if (int_mode == QED_INT_MODE_MSIX) 6331226337aSTomer Tayar synchronize_irq(cdev->int_params.msix_table[id].vector); 6341226337aSTomer Tayar else 6351226337aSTomer Tayar synchronize_irq(cdev->pdev->irq); 63606892f2eSTomer Tayar 63706892f2eSTomer Tayar qed_slowpath_tasklet_flush(p_hwfn); 6381226337aSTomer Tayar } 6391226337aSTomer Tayar 640fe56b9e6SYuval Mintz static void qed_slowpath_irq_free(struct qed_dev *cdev) 641fe56b9e6SYuval Mintz { 642fe56b9e6SYuval Mintz int i; 643fe56b9e6SYuval Mintz 644fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 645fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 6468f16bc97SSudarsana Kalluru if (!cdev->hwfns[i].b_int_requested) 6478f16bc97SSudarsana Kalluru break; 648fe56b9e6SYuval Mintz synchronize_irq(cdev->int_params.msix_table[i].vector); 649fe56b9e6SYuval Mintz free_irq(cdev->int_params.msix_table[i].vector, 650fe56b9e6SYuval Mintz cdev->hwfns[i].sp_dpc); 651fe56b9e6SYuval Mintz } 652fe56b9e6SYuval Mintz } else { 6538f16bc97SSudarsana Kalluru if (QED_LEADING_HWFN(cdev)->b_int_requested) 654fe56b9e6SYuval Mintz free_irq(cdev->pdev->irq, cdev); 655fe56b9e6SYuval Mintz } 6568f16bc97SSudarsana Kalluru qed_int_disable_post_isr_release(cdev); 657fe56b9e6SYuval Mintz } 658fe56b9e6SYuval Mintz 659fe56b9e6SYuval Mintz static int qed_nic_stop(struct qed_dev *cdev) 660fe56b9e6SYuval Mintz { 661fe56b9e6SYuval Mintz int i, rc; 662fe56b9e6SYuval Mintz 663fe56b9e6SYuval Mintz rc = qed_hw_stop(cdev); 664fe56b9e6SYuval Mintz 665fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 666fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 667fe56b9e6SYuval Mintz 668fe56b9e6SYuval Mintz if (p_hwfn->b_sp_dpc_enabled) { 669fe56b9e6SYuval Mintz tasklet_disable(p_hwfn->sp_dpc); 670fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = false; 671fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_IFDOWN, 672fe56b9e6SYuval Mintz "Disabled sp taskelt [hwfn %d] at %p\n", 673fe56b9e6SYuval Mintz i, p_hwfn->sp_dpc); 674fe56b9e6SYuval Mintz } 675fe56b9e6SYuval Mintz } 676fe56b9e6SYuval Mintz 677c965db44STomer Tayar qed_dbg_pf_exit(cdev); 678c965db44STomer Tayar 679fe56b9e6SYuval Mintz return rc; 680fe56b9e6SYuval Mintz } 681fe56b9e6SYuval Mintz 682fe56b9e6SYuval Mintz static int qed_nic_setup(struct qed_dev *cdev) 683fe56b9e6SYuval Mintz { 6840a7fb11cSYuval Mintz int rc, i; 6850a7fb11cSYuval Mintz 6860a7fb11cSYuval Mintz /* Determine if interface is going to require LL2 */ 6870a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) { 6880a7fb11cSYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 6890a7fb11cSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 6900a7fb11cSYuval Mintz 6910a7fb11cSYuval Mintz p_hwfn->using_ll2 = true; 6920a7fb11cSYuval Mintz } 6930a7fb11cSYuval Mintz } 694fe56b9e6SYuval Mintz 695fe56b9e6SYuval Mintz rc = qed_resc_alloc(cdev); 696fe56b9e6SYuval Mintz if (rc) 697fe56b9e6SYuval Mintz return rc; 698fe56b9e6SYuval Mintz 699fe56b9e6SYuval Mintz DP_INFO(cdev, "Allocated qed resources\n"); 700fe56b9e6SYuval Mintz 701fe56b9e6SYuval Mintz qed_resc_setup(cdev); 702fe56b9e6SYuval Mintz 703fe56b9e6SYuval Mintz return rc; 704fe56b9e6SYuval Mintz } 705fe56b9e6SYuval Mintz 706fe56b9e6SYuval Mintz static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt) 707fe56b9e6SYuval Mintz { 708fe56b9e6SYuval Mintz int limit = 0; 709fe56b9e6SYuval Mintz 710fe56b9e6SYuval Mintz /* Mark the fastpath as free/used */ 711fe56b9e6SYuval Mintz cdev->int_params.fp_initialized = cnt ? true : false; 712fe56b9e6SYuval Mintz 713fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX) 714fe56b9e6SYuval Mintz limit = cdev->num_hwfns * 63; 715fe56b9e6SYuval Mintz else if (cdev->int_params.fp_msix_cnt) 716fe56b9e6SYuval Mintz limit = cdev->int_params.fp_msix_cnt; 717fe56b9e6SYuval Mintz 718fe56b9e6SYuval Mintz if (!limit) 719fe56b9e6SYuval Mintz return -ENOMEM; 720fe56b9e6SYuval Mintz 721fe56b9e6SYuval Mintz return min_t(int, cnt, limit); 722fe56b9e6SYuval Mintz } 723fe56b9e6SYuval Mintz 724fe56b9e6SYuval Mintz static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info) 725fe56b9e6SYuval Mintz { 726fe56b9e6SYuval Mintz memset(info, 0, sizeof(struct qed_int_info)); 727fe56b9e6SYuval Mintz 728fe56b9e6SYuval Mintz if (!cdev->int_params.fp_initialized) { 729fe56b9e6SYuval Mintz DP_INFO(cdev, 730fe56b9e6SYuval Mintz "Protocol driver requested interrupt information, but its support is not yet configured\n"); 731fe56b9e6SYuval Mintz return -EINVAL; 732fe56b9e6SYuval Mintz } 733fe56b9e6SYuval Mintz 734fe56b9e6SYuval Mintz /* Need to expose only MSI-X information; Single IRQ is handled solely 735fe56b9e6SYuval Mintz * by qed. 736fe56b9e6SYuval Mintz */ 737fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 738fe56b9e6SYuval Mintz int msix_base = cdev->int_params.fp_msix_base; 739fe56b9e6SYuval Mintz 740fe56b9e6SYuval Mintz info->msix_cnt = cdev->int_params.fp_msix_cnt; 741fe56b9e6SYuval Mintz info->msix = &cdev->int_params.msix_table[msix_base]; 742fe56b9e6SYuval Mintz } 743fe56b9e6SYuval Mintz 744fe56b9e6SYuval Mintz return 0; 745fe56b9e6SYuval Mintz } 746fe56b9e6SYuval Mintz 747fe56b9e6SYuval Mintz static int qed_slowpath_setup_int(struct qed_dev *cdev, 748fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 749fe56b9e6SYuval Mintz { 7504ac801b7SYuval Mintz struct qed_sb_cnt_info sb_cnt_info; 7510189efb8SYuval Mintz int num_l2_queues = 0; 7524ac801b7SYuval Mintz int rc; 7534ac801b7SYuval Mintz int i; 754fe56b9e6SYuval Mintz 7551d2c2024SSudarsana Reddy Kalluru if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { 7561d2c2024SSudarsana Reddy Kalluru DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); 7571d2c2024SSudarsana Reddy Kalluru return -EINVAL; 7581d2c2024SSudarsana Reddy Kalluru } 7591d2c2024SSudarsana Reddy Kalluru 7601d2c2024SSudarsana Reddy Kalluru memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 761fe56b9e6SYuval Mintz cdev->int_params.in.int_mode = int_mode; 7624ac801b7SYuval Mintz for_each_hwfn(cdev, i) { 7634ac801b7SYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); 7644ac801b7SYuval Mintz qed_int_get_num_sbs(&cdev->hwfns[i], &sb_cnt_info); 765726fdbe9SMintz, Yuval cdev->int_params.in.num_vectors += sb_cnt_info.cnt; 7664ac801b7SYuval Mintz cdev->int_params.in.num_vectors++; /* slowpath */ 7674ac801b7SYuval Mintz } 768fe56b9e6SYuval Mintz 769fe56b9e6SYuval Mintz /* We want a minimum of one slowpath and one fastpath vector per hwfn */ 770fe56b9e6SYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; 771fe56b9e6SYuval Mintz 772fe56b9e6SYuval Mintz rc = qed_set_int_mode(cdev, false); 773fe56b9e6SYuval Mintz if (rc) { 774fe56b9e6SYuval Mintz DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); 775fe56b9e6SYuval Mintz return rc; 776fe56b9e6SYuval Mintz } 777fe56b9e6SYuval Mintz 778fe56b9e6SYuval Mintz cdev->int_params.fp_msix_base = cdev->num_hwfns; 779fe56b9e6SYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors - 780fe56b9e6SYuval Mintz cdev->num_hwfns; 781fe56b9e6SYuval Mintz 7822f782278SMintz, Yuval if (!IS_ENABLED(CONFIG_QED_RDMA) || 7832f782278SMintz, Yuval QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH_ROCE) 7840189efb8SYuval Mintz return 0; 7850189efb8SYuval Mintz 78651ff1725SRam Amrani for_each_hwfn(cdev, i) 78751ff1725SRam Amrani num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE); 78851ff1725SRam Amrani 78951ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, 79051ff1725SRam Amrani "cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n", 79151ff1725SRam Amrani cdev->int_params.fp_msix_cnt, num_l2_queues); 79251ff1725SRam Amrani 79351ff1725SRam Amrani if (cdev->int_params.fp_msix_cnt > num_l2_queues) { 79451ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 79551ff1725SRam Amrani (cdev->int_params.fp_msix_cnt - num_l2_queues) 79651ff1725SRam Amrani / cdev->num_hwfns; 79751ff1725SRam Amrani cdev->int_params.rdma_msix_base = 79851ff1725SRam Amrani cdev->int_params.fp_msix_base + num_l2_queues; 79951ff1725SRam Amrani cdev->int_params.fp_msix_cnt = num_l2_queues; 80051ff1725SRam Amrani } else { 80151ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 0; 80251ff1725SRam Amrani } 80351ff1725SRam Amrani 80451ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n", 80551ff1725SRam Amrani cdev->int_params.rdma_msix_cnt, 80651ff1725SRam Amrani cdev->int_params.rdma_msix_base); 80751ff1725SRam Amrani 808fe56b9e6SYuval Mintz return 0; 809fe56b9e6SYuval Mintz } 810fe56b9e6SYuval Mintz 8111408cc1fSYuval Mintz static int qed_slowpath_vf_setup_int(struct qed_dev *cdev) 8121408cc1fSYuval Mintz { 8131408cc1fSYuval Mintz int rc; 8141408cc1fSYuval Mintz 8151408cc1fSYuval Mintz memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 8161408cc1fSYuval Mintz cdev->int_params.in.int_mode = QED_INT_MODE_MSIX; 8171408cc1fSYuval Mintz 8181408cc1fSYuval Mintz qed_vf_get_num_rxqs(QED_LEADING_HWFN(cdev), 8191408cc1fSYuval Mintz &cdev->int_params.in.num_vectors); 8201408cc1fSYuval Mintz if (cdev->num_hwfns > 1) { 8211408cc1fSYuval Mintz u8 vectors = 0; 8221408cc1fSYuval Mintz 8231408cc1fSYuval Mintz qed_vf_get_num_rxqs(&cdev->hwfns[1], &vectors); 8241408cc1fSYuval Mintz cdev->int_params.in.num_vectors += vectors; 8251408cc1fSYuval Mintz } 8261408cc1fSYuval Mintz 8271408cc1fSYuval Mintz /* We want a minimum of one fastpath vector per vf hwfn */ 8281408cc1fSYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns; 8291408cc1fSYuval Mintz 8301408cc1fSYuval Mintz rc = qed_set_int_mode(cdev, true); 8311408cc1fSYuval Mintz if (rc) 8321408cc1fSYuval Mintz return rc; 8331408cc1fSYuval Mintz 8341408cc1fSYuval Mintz cdev->int_params.fp_msix_base = 0; 8351408cc1fSYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors; 8361408cc1fSYuval Mintz 8371408cc1fSYuval Mintz return 0; 8381408cc1fSYuval Mintz } 8391408cc1fSYuval Mintz 840fe56b9e6SYuval Mintz u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, 841fe56b9e6SYuval Mintz u8 *input_buf, u32 max_size, u8 *unzip_buf) 842fe56b9e6SYuval Mintz { 843fe56b9e6SYuval Mintz int rc; 844fe56b9e6SYuval Mintz 845fe56b9e6SYuval Mintz p_hwfn->stream->next_in = input_buf; 846fe56b9e6SYuval Mintz p_hwfn->stream->avail_in = input_len; 847fe56b9e6SYuval Mintz p_hwfn->stream->next_out = unzip_buf; 848fe56b9e6SYuval Mintz p_hwfn->stream->avail_out = max_size; 849fe56b9e6SYuval Mintz 850fe56b9e6SYuval Mintz rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS); 851fe56b9e6SYuval Mintz 852fe56b9e6SYuval Mintz if (rc != Z_OK) { 853fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n", 854fe56b9e6SYuval Mintz rc); 855fe56b9e6SYuval Mintz return 0; 856fe56b9e6SYuval Mintz } 857fe56b9e6SYuval Mintz 858fe56b9e6SYuval Mintz rc = zlib_inflate(p_hwfn->stream, Z_FINISH); 859fe56b9e6SYuval Mintz zlib_inflateEnd(p_hwfn->stream); 860fe56b9e6SYuval Mintz 861fe56b9e6SYuval Mintz if (rc != Z_OK && rc != Z_STREAM_END) { 862fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n", 863fe56b9e6SYuval Mintz p_hwfn->stream->msg, rc); 864fe56b9e6SYuval Mintz return 0; 865fe56b9e6SYuval Mintz } 866fe56b9e6SYuval Mintz 867fe56b9e6SYuval Mintz return p_hwfn->stream->total_out / 4; 868fe56b9e6SYuval Mintz } 869fe56b9e6SYuval Mintz 870fe56b9e6SYuval Mintz static int qed_alloc_stream_mem(struct qed_dev *cdev) 871fe56b9e6SYuval Mintz { 872fe56b9e6SYuval Mintz int i; 873fe56b9e6SYuval Mintz void *workspace; 874fe56b9e6SYuval Mintz 875fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 876fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 877fe56b9e6SYuval Mintz 878fe56b9e6SYuval Mintz p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL); 879fe56b9e6SYuval Mintz if (!p_hwfn->stream) 880fe56b9e6SYuval Mintz return -ENOMEM; 881fe56b9e6SYuval Mintz 882fe56b9e6SYuval Mintz workspace = vzalloc(zlib_inflate_workspacesize()); 883fe56b9e6SYuval Mintz if (!workspace) 884fe56b9e6SYuval Mintz return -ENOMEM; 885fe56b9e6SYuval Mintz p_hwfn->stream->workspace = workspace; 886fe56b9e6SYuval Mintz } 887fe56b9e6SYuval Mintz 888fe56b9e6SYuval Mintz return 0; 889fe56b9e6SYuval Mintz } 890fe56b9e6SYuval Mintz 891fe56b9e6SYuval Mintz static void qed_free_stream_mem(struct qed_dev *cdev) 892fe56b9e6SYuval Mintz { 893fe56b9e6SYuval Mintz int i; 894fe56b9e6SYuval Mintz 895fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 896fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 897fe56b9e6SYuval Mintz 898fe56b9e6SYuval Mintz if (!p_hwfn->stream) 899fe56b9e6SYuval Mintz return; 900fe56b9e6SYuval Mintz 901fe56b9e6SYuval Mintz vfree(p_hwfn->stream->workspace); 902fe56b9e6SYuval Mintz kfree(p_hwfn->stream); 903fe56b9e6SYuval Mintz } 904fe56b9e6SYuval Mintz } 905fe56b9e6SYuval Mintz 906fe56b9e6SYuval Mintz static void qed_update_pf_params(struct qed_dev *cdev, 907fe56b9e6SYuval Mintz struct qed_pf_params *params) 908fe56b9e6SYuval Mintz { 909fe56b9e6SYuval Mintz int i; 910fe56b9e6SYuval Mintz 9115c5f2609SRam Amrani if (IS_ENABLED(CONFIG_QED_RDMA)) { 9120189efb8SYuval Mintz params->rdma_pf_params.num_qps = QED_ROCE_QPS; 9130189efb8SYuval Mintz params->rdma_pf_params.min_dpis = QED_ROCE_DPIS; 9140189efb8SYuval Mintz /* divide by 3 the MRs to avoid MF ILT overflow */ 9150189efb8SYuval Mintz params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX; 916fe56b9e6SYuval Mintz } 917fe56b9e6SYuval Mintz 918d51e4af5SChopra, Manish if (cdev->num_hwfns > 1 || IS_VF(cdev)) 919d51e4af5SChopra, Manish params->eth_pf_params.num_arfs_filters = 0; 920d51e4af5SChopra, Manish 921e1d32acbSMintz, Yuval /* In case we might support RDMA, don't allow qede to be greedy 922e1d32acbSMintz, Yuval * with the L2 contexts. Allow for 64 queues [rx, tx, xdp] per hwfn. 923e1d32acbSMintz, Yuval */ 924e1d32acbSMintz, Yuval if (QED_LEADING_HWFN(cdev)->hw_info.personality == 925e1d32acbSMintz, Yuval QED_PCI_ETH_ROCE) { 926e1d32acbSMintz, Yuval u16 *num_cons; 927e1d32acbSMintz, Yuval 928e1d32acbSMintz, Yuval num_cons = ¶ms->eth_pf_params.num_cons; 929e1d32acbSMintz, Yuval *num_cons = min_t(u16, *num_cons, 192); 930e1d32acbSMintz, Yuval } 931e1d32acbSMintz, Yuval 9325c5f2609SRam Amrani for (i = 0; i < cdev->num_hwfns; i++) { 9335c5f2609SRam Amrani struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 9345c5f2609SRam Amrani 9355c5f2609SRam Amrani p_hwfn->pf_params = *params; 9365c5f2609SRam Amrani } 9375c5f2609SRam Amrani } 9385c5f2609SRam Amrani 939fe56b9e6SYuval Mintz static int qed_slowpath_start(struct qed_dev *cdev, 940fe56b9e6SYuval Mintz struct qed_slowpath_params *params) 941fe56b9e6SYuval Mintz { 9425d24bcf1STomer Tayar struct qed_drv_load_params drv_load_params; 943c0c2d0b4SMintz, Yuval struct qed_hw_init_params hw_init_params; 944fe56b9e6SYuval Mintz struct qed_mcp_drv_version drv_version; 94519968430SChopra, Manish struct qed_tunnel_info tunn_info; 946fe56b9e6SYuval Mintz const u8 *data = NULL; 947fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 94807ff2ed0SMintz, Yuval #ifdef CONFIG_RFS_ACCEL 949c78c70faSSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 95007ff2ed0SMintz, Yuval #endif 95137bff2b9SYuval Mintz int rc = -EINVAL; 95237bff2b9SYuval Mintz 95337bff2b9SYuval Mintz if (qed_iov_wq_start(cdev)) 95437bff2b9SYuval Mintz goto err; 955fe56b9e6SYuval Mintz 9561408cc1fSYuval Mintz if (IS_PF(cdev)) { 957fe56b9e6SYuval Mintz rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME, 958fe56b9e6SYuval Mintz &cdev->pdev->dev); 959fe56b9e6SYuval Mintz if (rc) { 960fe56b9e6SYuval Mintz DP_NOTICE(cdev, 961fe56b9e6SYuval Mintz "Failed to find fw file - /lib/firmware/%s\n", 962fe56b9e6SYuval Mintz QED_FW_FILE_NAME); 963fe56b9e6SYuval Mintz goto err; 964fe56b9e6SYuval Mintz } 965c78c70faSSudarsana Reddy Kalluru 966d51e4af5SChopra, Manish #ifdef CONFIG_RFS_ACCEL 967d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) { 968d51e4af5SChopra, Manish p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 969d51e4af5SChopra, Manish if (p_ptt) { 970d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt = p_ptt; 971d51e4af5SChopra, Manish } else { 972d51e4af5SChopra, Manish DP_NOTICE(cdev, 973d51e4af5SChopra, Manish "Failed to acquire PTT for aRFS\n"); 974d51e4af5SChopra, Manish goto err; 975d51e4af5SChopra, Manish } 976d51e4af5SChopra, Manish } 977d51e4af5SChopra, Manish #endif 9781408cc1fSYuval Mintz } 979fe56b9e6SYuval Mintz 9800e191827SSudarsana Reddy Kalluru cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS; 981fe56b9e6SYuval Mintz rc = qed_nic_setup(cdev); 982fe56b9e6SYuval Mintz if (rc) 983fe56b9e6SYuval Mintz goto err; 984fe56b9e6SYuval Mintz 9851408cc1fSYuval Mintz if (IS_PF(cdev)) 986fe56b9e6SYuval Mintz rc = qed_slowpath_setup_int(cdev, params->int_mode); 9871408cc1fSYuval Mintz else 9881408cc1fSYuval Mintz rc = qed_slowpath_vf_setup_int(cdev); 989fe56b9e6SYuval Mintz if (rc) 990fe56b9e6SYuval Mintz goto err1; 991fe56b9e6SYuval Mintz 9921408cc1fSYuval Mintz if (IS_PF(cdev)) { 993fe56b9e6SYuval Mintz /* Allocate stream for unzipping */ 994fe56b9e6SYuval Mintz rc = qed_alloc_stream_mem(cdev); 9952591c280SJoe Perches if (rc) 9968f16bc97SSudarsana Kalluru goto err2; 997fe56b9e6SYuval Mintz 9988ac1ed79SJoe Perches /* First Dword used to differentiate between various sources */ 999351a4dedSYuval Mintz data = cdev->firmware->data + sizeof(u32); 1000c965db44STomer Tayar 1001c965db44STomer Tayar qed_dbg_pf_init(cdev); 10021408cc1fSYuval Mintz } 1003fe56b9e6SYuval Mintz 10041408cc1fSYuval Mintz /* Start the slowpath */ 1005c0c2d0b4SMintz, Yuval memset(&hw_init_params, 0, sizeof(hw_init_params)); 100619968430SChopra, Manish memset(&tunn_info, 0, sizeof(tunn_info)); 100719968430SChopra, Manish tunn_info.vxlan.b_mode_enabled = true; 100819968430SChopra, Manish tunn_info.l2_gre.b_mode_enabled = true; 100919968430SChopra, Manish tunn_info.ip_gre.b_mode_enabled = true; 101019968430SChopra, Manish tunn_info.l2_geneve.b_mode_enabled = true; 101119968430SChopra, Manish tunn_info.ip_geneve.b_mode_enabled = true; 101219968430SChopra, Manish tunn_info.vxlan.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101319968430SChopra, Manish tunn_info.l2_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101419968430SChopra, Manish tunn_info.ip_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101519968430SChopra, Manish tunn_info.l2_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101619968430SChopra, Manish tunn_info.ip_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 1017c0c2d0b4SMintz, Yuval hw_init_params.p_tunn = &tunn_info; 1018c0c2d0b4SMintz, Yuval hw_init_params.b_hw_start = true; 1019c0c2d0b4SMintz, Yuval hw_init_params.int_mode = cdev->int_params.out.int_mode; 1020c0c2d0b4SMintz, Yuval hw_init_params.allow_npar_tx_switch = true; 1021c0c2d0b4SMintz, Yuval hw_init_params.bin_fw_data = data; 1022c0c2d0b4SMintz, Yuval 10235d24bcf1STomer Tayar memset(&drv_load_params, 0, sizeof(drv_load_params)); 10245d24bcf1STomer Tayar drv_load_params.is_crash_kernel = is_kdump_kernel(); 10255d24bcf1STomer Tayar drv_load_params.mfw_timeout_val = QED_LOAD_REQ_LOCK_TO_DEFAULT; 10265d24bcf1STomer Tayar drv_load_params.avoid_eng_reset = false; 10275d24bcf1STomer Tayar drv_load_params.override_force_load = QED_OVERRIDE_FORCE_LOAD_NONE; 10285d24bcf1STomer Tayar hw_init_params.p_drv_load_params = &drv_load_params; 10295d24bcf1STomer Tayar 1030c0c2d0b4SMintz, Yuval rc = qed_hw_init(cdev, &hw_init_params); 1031fe56b9e6SYuval Mintz if (rc) 10328c925c44SYuval Mintz goto err2; 1033fe56b9e6SYuval Mintz 1034fe56b9e6SYuval Mintz DP_INFO(cdev, 1035fe56b9e6SYuval Mintz "HW initialization and function start completed successfully\n"); 1036fe56b9e6SYuval Mintz 1037eaf3c0c6SChopra, Manish if (IS_PF(cdev)) { 1038eaf3c0c6SChopra, Manish cdev->tunn_feature_mask = (BIT(QED_MODE_VXLAN_TUNN) | 1039eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GENEVE_TUNN) | 1040eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGENEVE_TUNN) | 1041eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GRE_TUNN) | 1042eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGRE_TUNN)); 1043eaf3c0c6SChopra, Manish } 1044eaf3c0c6SChopra, Manish 10450a7fb11cSYuval Mintz /* Allocate LL2 interface if needed */ 10460a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->using_ll2) { 10470a7fb11cSYuval Mintz rc = qed_ll2_alloc_if(cdev); 10480a7fb11cSYuval Mintz if (rc) 10490a7fb11cSYuval Mintz goto err3; 10500a7fb11cSYuval Mintz } 10511408cc1fSYuval Mintz if (IS_PF(cdev)) { 1052fe56b9e6SYuval Mintz hwfn = QED_LEADING_HWFN(cdev); 1053fe56b9e6SYuval Mintz drv_version.version = (params->drv_major << 24) | 1054fe56b9e6SYuval Mintz (params->drv_minor << 16) | 1055fe56b9e6SYuval Mintz (params->drv_rev << 8) | 1056fe56b9e6SYuval Mintz (params->drv_eng); 1057fe56b9e6SYuval Mintz strlcpy(drv_version.name, params->name, 1058fe56b9e6SYuval Mintz MCP_DRV_VER_STR_SIZE - 4); 1059fe56b9e6SYuval Mintz rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt, 1060fe56b9e6SYuval Mintz &drv_version); 1061fe56b9e6SYuval Mintz if (rc) { 1062fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed sending drv version command\n"); 1063fe56b9e6SYuval Mintz return rc; 1064fe56b9e6SYuval Mintz } 10651408cc1fSYuval Mintz } 1066fe56b9e6SYuval Mintz 10678c925c44SYuval Mintz qed_reset_vport_stats(cdev); 10688c925c44SYuval Mintz 1069fe56b9e6SYuval Mintz return 0; 1070fe56b9e6SYuval Mintz 10710a7fb11cSYuval Mintz err3: 10720a7fb11cSYuval Mintz qed_hw_stop(cdev); 1073fe56b9e6SYuval Mintz err2: 10748c925c44SYuval Mintz qed_hw_timers_stop_all(cdev); 10751408cc1fSYuval Mintz if (IS_PF(cdev)) 10768c925c44SYuval Mintz qed_slowpath_irq_free(cdev); 10778c925c44SYuval Mintz qed_free_stream_mem(cdev); 1078fe56b9e6SYuval Mintz qed_disable_msix(cdev); 1079fe56b9e6SYuval Mintz err1: 1080fe56b9e6SYuval Mintz qed_resc_free(cdev); 1081fe56b9e6SYuval Mintz err: 10821408cc1fSYuval Mintz if (IS_PF(cdev)) 1083fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1084fe56b9e6SYuval Mintz 1085d51e4af5SChopra, Manish #ifdef CONFIG_RFS_ACCEL 1086d51e4af5SChopra, Manish if (IS_PF(cdev) && (cdev->num_hwfns == 1) && 1087d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt) 1088d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1089d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1090d51e4af5SChopra, Manish #endif 1091c78c70faSSudarsana Reddy Kalluru 109237bff2b9SYuval Mintz qed_iov_wq_stop(cdev, false); 109337bff2b9SYuval Mintz 1094fe56b9e6SYuval Mintz return rc; 1095fe56b9e6SYuval Mintz } 1096fe56b9e6SYuval Mintz 1097fe56b9e6SYuval Mintz static int qed_slowpath_stop(struct qed_dev *cdev) 1098fe56b9e6SYuval Mintz { 1099fe56b9e6SYuval Mintz if (!cdev) 1100fe56b9e6SYuval Mintz return -ENODEV; 1101fe56b9e6SYuval Mintz 11020a7fb11cSYuval Mintz qed_ll2_dealloc_if(cdev); 11030a7fb11cSYuval Mintz 11041408cc1fSYuval Mintz if (IS_PF(cdev)) { 1105d51e4af5SChopra, Manish #ifdef CONFIG_RFS_ACCEL 1106d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) 1107d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1108d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1109d51e4af5SChopra, Manish #endif 1110fe56b9e6SYuval Mintz qed_free_stream_mem(cdev); 1111c5ac9319SYuval Mintz if (IS_QED_ETH_IF(cdev)) 11120b55e27dSYuval Mintz qed_sriov_disable(cdev, true); 11135f027d7aSMintz, Yuval } 1114fe56b9e6SYuval Mintz 1115fe56b9e6SYuval Mintz qed_nic_stop(cdev); 11165f027d7aSMintz, Yuval 11175f027d7aSMintz, Yuval if (IS_PF(cdev)) 1118fe56b9e6SYuval Mintz qed_slowpath_irq_free(cdev); 1119fe56b9e6SYuval Mintz 1120fe56b9e6SYuval Mintz qed_disable_msix(cdev); 11211226337aSTomer Tayar 11221226337aSTomer Tayar qed_resc_free(cdev); 1123fe56b9e6SYuval Mintz 112437bff2b9SYuval Mintz qed_iov_wq_stop(cdev, true); 112537bff2b9SYuval Mintz 11261408cc1fSYuval Mintz if (IS_PF(cdev)) 1127fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1128fe56b9e6SYuval Mintz 1129fe56b9e6SYuval Mintz return 0; 1130fe56b9e6SYuval Mintz } 1131fe56b9e6SYuval Mintz 1132712c3cbfSMintz, Yuval static void qed_set_name(struct qed_dev *cdev, char name[NAME_SIZE]) 1133fe56b9e6SYuval Mintz { 1134fe56b9e6SYuval Mintz int i; 1135fe56b9e6SYuval Mintz 1136fe56b9e6SYuval Mintz memcpy(cdev->name, name, NAME_SIZE); 1137fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) 1138fe56b9e6SYuval Mintz snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i); 1139fe56b9e6SYuval Mintz } 1140fe56b9e6SYuval Mintz 1141fe56b9e6SYuval Mintz static u32 qed_sb_init(struct qed_dev *cdev, 1142fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 1143fe56b9e6SYuval Mintz void *sb_virt_addr, 1144fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, u16 sb_id, 1145fe56b9e6SYuval Mintz enum qed_sb_type type) 1146fe56b9e6SYuval Mintz { 1147fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 114885750d74SMintz, Yuval struct qed_ptt *p_ptt; 1149fe56b9e6SYuval Mintz int hwfn_index; 1150fe56b9e6SYuval Mintz u16 rel_sb_id; 1151fe56b9e6SYuval Mintz u8 n_hwfns; 1152fe56b9e6SYuval Mintz u32 rc; 1153fe56b9e6SYuval Mintz 1154fe56b9e6SYuval Mintz /* RoCE uses single engine and CMT uses two engines. When using both 1155fe56b9e6SYuval Mintz * we force only a single engine. Storage uses only engine 0 too. 1156fe56b9e6SYuval Mintz */ 1157fe56b9e6SYuval Mintz if (type == QED_SB_TYPE_L2_QUEUE) 1158fe56b9e6SYuval Mintz n_hwfns = cdev->num_hwfns; 1159fe56b9e6SYuval Mintz else 1160fe56b9e6SYuval Mintz n_hwfns = 1; 1161fe56b9e6SYuval Mintz 1162fe56b9e6SYuval Mintz hwfn_index = sb_id % n_hwfns; 1163fe56b9e6SYuval Mintz p_hwfn = &cdev->hwfns[hwfn_index]; 1164fe56b9e6SYuval Mintz rel_sb_id = sb_id / n_hwfns; 1165fe56b9e6SYuval Mintz 1166fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1167fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 1168fe56b9e6SYuval Mintz hwfn_index, rel_sb_id, sb_id); 1169fe56b9e6SYuval Mintz 117085750d74SMintz, Yuval if (IS_PF(p_hwfn->cdev)) { 117185750d74SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 117285750d74SMintz, Yuval if (!p_ptt) 117385750d74SMintz, Yuval return -EBUSY; 117485750d74SMintz, Yuval 117585750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, p_ptt, sb_info, sb_virt_addr, 117685750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 117785750d74SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 117885750d74SMintz, Yuval } else { 117985750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, NULL, sb_info, sb_virt_addr, 118085750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 118185750d74SMintz, Yuval } 1182fe56b9e6SYuval Mintz 1183fe56b9e6SYuval Mintz return rc; 1184fe56b9e6SYuval Mintz } 1185fe56b9e6SYuval Mintz 1186fe56b9e6SYuval Mintz static u32 qed_sb_release(struct qed_dev *cdev, 11871a635e48SYuval Mintz struct qed_sb_info *sb_info, u16 sb_id) 1188fe56b9e6SYuval Mintz { 1189fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 1190fe56b9e6SYuval Mintz int hwfn_index; 1191fe56b9e6SYuval Mintz u16 rel_sb_id; 1192fe56b9e6SYuval Mintz u32 rc; 1193fe56b9e6SYuval Mintz 1194fe56b9e6SYuval Mintz hwfn_index = sb_id % cdev->num_hwfns; 1195fe56b9e6SYuval Mintz p_hwfn = &cdev->hwfns[hwfn_index]; 1196fe56b9e6SYuval Mintz rel_sb_id = sb_id / cdev->num_hwfns; 1197fe56b9e6SYuval Mintz 1198fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1199fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 1200fe56b9e6SYuval Mintz hwfn_index, rel_sb_id, sb_id); 1201fe56b9e6SYuval Mintz 1202fe56b9e6SYuval Mintz rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id); 1203fe56b9e6SYuval Mintz 1204fe56b9e6SYuval Mintz return rc; 1205fe56b9e6SYuval Mintz } 1206fe56b9e6SYuval Mintz 1207fe7cd2bfSYuval Mintz static bool qed_can_link_change(struct qed_dev *cdev) 1208fe7cd2bfSYuval Mintz { 1209fe7cd2bfSYuval Mintz return true; 1210fe7cd2bfSYuval Mintz } 1211fe7cd2bfSYuval Mintz 1212351a4dedSYuval Mintz static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params) 1213cc875c2eSYuval Mintz { 1214cc875c2eSYuval Mintz struct qed_hwfn *hwfn; 1215cc875c2eSYuval Mintz struct qed_mcp_link_params *link_params; 1216cc875c2eSYuval Mintz struct qed_ptt *ptt; 1217cc875c2eSYuval Mintz int rc; 1218cc875c2eSYuval Mintz 1219cc875c2eSYuval Mintz if (!cdev) 1220cc875c2eSYuval Mintz return -ENODEV; 1221cc875c2eSYuval Mintz 1222cc875c2eSYuval Mintz /* The link should be set only once per PF */ 1223cc875c2eSYuval Mintz hwfn = &cdev->hwfns[0]; 1224cc875c2eSYuval Mintz 122565ed2ffdSMintz, Yuval /* When VF wants to set link, force it to read the bulletin instead. 122665ed2ffdSMintz, Yuval * This mimics the PF behavior, where a noitification [both immediate 122765ed2ffdSMintz, Yuval * and possible later] would be generated when changing properties. 122865ed2ffdSMintz, Yuval */ 122965ed2ffdSMintz, Yuval if (IS_VF(cdev)) { 123065ed2ffdSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG); 123165ed2ffdSMintz, Yuval return 0; 123265ed2ffdSMintz, Yuval } 123365ed2ffdSMintz, Yuval 1234cc875c2eSYuval Mintz ptt = qed_ptt_acquire(hwfn); 1235cc875c2eSYuval Mintz if (!ptt) 1236cc875c2eSYuval Mintz return -EBUSY; 1237cc875c2eSYuval Mintz 1238cc875c2eSYuval Mintz link_params = qed_mcp_get_link_params(hwfn); 1239cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 1240cc875c2eSYuval Mintz link_params->speed.autoneg = params->autoneg; 1241cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 1242cc875c2eSYuval Mintz link_params->speed.advertised_speeds = 0; 1243054c67d1SSudarsana Reddy Kalluru if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) || 1244054c67d1SSudarsana Reddy Kalluru (params->adv_speeds & QED_LM_1000baseT_Full_BIT)) 1245cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1246cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G; 1247054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT) 1248cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1249cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G; 1250054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_25000baseKR_Full_BIT) 1251054c67d1SSudarsana Reddy Kalluru link_params->speed.advertised_speeds |= 1252054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G; 1253054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_40000baseLR4_Full_BIT) 1254cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1255cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G; 1256054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_50000baseKR2_Full_BIT) 1257cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1258cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G; 1259054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_100000baseKR4_Full_BIT) 1260cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1261351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G; 1262cc875c2eSYuval Mintz } 1263cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) 1264cc875c2eSYuval Mintz link_params->speed.forced_speed = params->forced_speed; 1265a43f235fSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) { 1266a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 1267a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = true; 1268a43f235fSSudarsana Reddy Kalluru else 1269a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = false; 1270a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE) 1271a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = true; 1272a43f235fSSudarsana Reddy Kalluru else 1273a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = false; 1274a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE) 1275a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = true; 1276a43f235fSSudarsana Reddy Kalluru else 1277a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = false; 1278a43f235fSSudarsana Reddy Kalluru } 127903dc76caSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) { 128003dc76caSSudarsana Reddy Kalluru switch (params->loopback_mode) { 128103dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_INT_PHY: 1282351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_INT_PHY; 128303dc76caSSudarsana Reddy Kalluru break; 128403dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT_PHY: 1285351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT_PHY; 128603dc76caSSudarsana Reddy Kalluru break; 128703dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT: 1288351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT; 128903dc76caSSudarsana Reddy Kalluru break; 129003dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_MAC: 1291351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_MAC; 129203dc76caSSudarsana Reddy Kalluru break; 129303dc76caSSudarsana Reddy Kalluru default: 1294351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_NONE; 129503dc76caSSudarsana Reddy Kalluru break; 129603dc76caSSudarsana Reddy Kalluru } 129703dc76caSSudarsana Reddy Kalluru } 1298cc875c2eSYuval Mintz 1299cc875c2eSYuval Mintz rc = qed_mcp_set_link(hwfn, ptt, params->link_up); 1300cc875c2eSYuval Mintz 1301cc875c2eSYuval Mintz qed_ptt_release(hwfn, ptt); 1302cc875c2eSYuval Mintz 1303cc875c2eSYuval Mintz return rc; 1304cc875c2eSYuval Mintz } 1305cc875c2eSYuval Mintz 1306cc875c2eSYuval Mintz static int qed_get_port_type(u32 media_type) 1307cc875c2eSYuval Mintz { 1308cc875c2eSYuval Mintz int port_type; 1309cc875c2eSYuval Mintz 1310cc875c2eSYuval Mintz switch (media_type) { 1311cc875c2eSYuval Mintz case MEDIA_SFPP_10G_FIBER: 1312cc875c2eSYuval Mintz case MEDIA_SFP_1G_FIBER: 1313cc875c2eSYuval Mintz case MEDIA_XFP_FIBER: 1314b639f197SYuval Mintz case MEDIA_MODULE_FIBER: 1315cc875c2eSYuval Mintz case MEDIA_KR: 1316cc875c2eSYuval Mintz port_type = PORT_FIBRE; 1317cc875c2eSYuval Mintz break; 1318cc875c2eSYuval Mintz case MEDIA_DA_TWINAX: 1319cc875c2eSYuval Mintz port_type = PORT_DA; 1320cc875c2eSYuval Mintz break; 1321cc875c2eSYuval Mintz case MEDIA_BASE_T: 1322cc875c2eSYuval Mintz port_type = PORT_TP; 1323cc875c2eSYuval Mintz break; 1324cc875c2eSYuval Mintz case MEDIA_NOT_PRESENT: 1325cc875c2eSYuval Mintz port_type = PORT_NONE; 1326cc875c2eSYuval Mintz break; 1327cc875c2eSYuval Mintz case MEDIA_UNSPECIFIED: 1328cc875c2eSYuval Mintz default: 1329cc875c2eSYuval Mintz port_type = PORT_OTHER; 1330cc875c2eSYuval Mintz break; 1331cc875c2eSYuval Mintz } 1332cc875c2eSYuval Mintz return port_type; 1333cc875c2eSYuval Mintz } 1334cc875c2eSYuval Mintz 133514b84e86SArnd Bergmann static int qed_get_link_data(struct qed_hwfn *hwfn, 133614b84e86SArnd Bergmann struct qed_mcp_link_params *params, 133714b84e86SArnd Bergmann struct qed_mcp_link_state *link, 133814b84e86SArnd Bergmann struct qed_mcp_link_capabilities *link_caps) 133914b84e86SArnd Bergmann { 134014b84e86SArnd Bergmann void *p; 134114b84e86SArnd Bergmann 134214b84e86SArnd Bergmann if (!IS_PF(hwfn->cdev)) { 134314b84e86SArnd Bergmann qed_vf_get_link_params(hwfn, params); 134414b84e86SArnd Bergmann qed_vf_get_link_state(hwfn, link); 134514b84e86SArnd Bergmann qed_vf_get_link_caps(hwfn, link_caps); 134614b84e86SArnd Bergmann 134714b84e86SArnd Bergmann return 0; 134814b84e86SArnd Bergmann } 134914b84e86SArnd Bergmann 135014b84e86SArnd Bergmann p = qed_mcp_get_link_params(hwfn); 135114b84e86SArnd Bergmann if (!p) 135214b84e86SArnd Bergmann return -ENXIO; 135314b84e86SArnd Bergmann memcpy(params, p, sizeof(*params)); 135414b84e86SArnd Bergmann 135514b84e86SArnd Bergmann p = qed_mcp_get_link_state(hwfn); 135614b84e86SArnd Bergmann if (!p) 135714b84e86SArnd Bergmann return -ENXIO; 135814b84e86SArnd Bergmann memcpy(link, p, sizeof(*link)); 135914b84e86SArnd Bergmann 136014b84e86SArnd Bergmann p = qed_mcp_get_link_capabilities(hwfn); 136114b84e86SArnd Bergmann if (!p) 136214b84e86SArnd Bergmann return -ENXIO; 136314b84e86SArnd Bergmann memcpy(link_caps, p, sizeof(*link_caps)); 136414b84e86SArnd Bergmann 136514b84e86SArnd Bergmann return 0; 136614b84e86SArnd Bergmann } 136714b84e86SArnd Bergmann 1368cc875c2eSYuval Mintz static void qed_fill_link(struct qed_hwfn *hwfn, 1369cc875c2eSYuval Mintz struct qed_link_output *if_link) 1370cc875c2eSYuval Mintz { 1371cc875c2eSYuval Mintz struct qed_mcp_link_params params; 1372cc875c2eSYuval Mintz struct qed_mcp_link_state link; 1373cc875c2eSYuval Mintz struct qed_mcp_link_capabilities link_caps; 1374cc875c2eSYuval Mintz u32 media_type; 1375cc875c2eSYuval Mintz 1376cc875c2eSYuval Mintz memset(if_link, 0, sizeof(*if_link)); 1377cc875c2eSYuval Mintz 1378cc875c2eSYuval Mintz /* Prepare source inputs */ 137914b84e86SArnd Bergmann if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) { 138014b84e86SArnd Bergmann dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n"); 138114b84e86SArnd Bergmann return; 13821408cc1fSYuval Mintz } 1383cc875c2eSYuval Mintz 1384cc875c2eSYuval Mintz /* Set the link parameters to pass to protocol driver */ 1385cc875c2eSYuval Mintz if (link.link_up) 1386cc875c2eSYuval Mintz if_link->link_up = true; 1387cc875c2eSYuval Mintz 1388cc875c2eSYuval Mintz /* TODO - at the moment assume supported and advertised speed equal */ 1389054c67d1SSudarsana Reddy Kalluru if_link->supported_caps = QED_LM_FIBRE_BIT; 139034f9199cSsudarsana.kalluru@cavium.com if (link_caps.default_speed_autoneg) 1391054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Autoneg_BIT; 1392cc875c2eSYuval Mintz if (params.pause.autoneg || 1393cc875c2eSYuval Mintz (params.pause.forced_rx && params.pause.forced_tx)) 1394054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Asym_Pause_BIT; 1395cc875c2eSYuval Mintz if (params.pause.autoneg || params.pause.forced_rx || 1396cc875c2eSYuval Mintz params.pause.forced_tx) 1397054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Pause_BIT; 1398cc875c2eSYuval Mintz 1399cc875c2eSYuval Mintz if_link->advertised_caps = if_link->supported_caps; 140034f9199cSsudarsana.kalluru@cavium.com if (params.speed.autoneg) 140134f9199cSsudarsana.kalluru@cavium.com if_link->advertised_caps |= QED_LM_Autoneg_BIT; 140234f9199cSsudarsana.kalluru@cavium.com else 140334f9199cSsudarsana.kalluru@cavium.com if_link->advertised_caps &= ~QED_LM_Autoneg_BIT; 1404cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1405cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1406054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT | 1407054c67d1SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT; 1408cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1409cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 1410054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT; 1411054c67d1SSudarsana Reddy Kalluru if (params.speed.advertised_speeds & 1412054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 1413054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT; 1414cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1415cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 1416054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT; 1417cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1418cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 1419054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT; 1420cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1421351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 1422054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT; 1423cc875c2eSYuval Mintz 1424cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1425cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1426054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_1000baseT_Half_BIT | 1427054c67d1SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT; 1428cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1429cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 1430054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT; 1431054c67d1SSudarsana Reddy Kalluru if (link_caps.speed_capabilities & 1432054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 1433054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT; 1434cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1435cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 1436054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT; 1437cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1438cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 1439054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT; 1440cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1441351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 1442054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT; 1443cc875c2eSYuval Mintz 1444cc875c2eSYuval Mintz if (link.link_up) 1445cc875c2eSYuval Mintz if_link->speed = link.speed; 1446cc875c2eSYuval Mintz 1447cc875c2eSYuval Mintz /* TODO - fill duplex properly */ 1448cc875c2eSYuval Mintz if_link->duplex = DUPLEX_FULL; 1449cc875c2eSYuval Mintz qed_mcp_get_media_type(hwfn->cdev, &media_type); 1450cc875c2eSYuval Mintz if_link->port = qed_get_port_type(media_type); 1451cc875c2eSYuval Mintz 1452cc875c2eSYuval Mintz if_link->autoneg = params.speed.autoneg; 1453cc875c2eSYuval Mintz 1454cc875c2eSYuval Mintz if (params.pause.autoneg) 1455cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 1456cc875c2eSYuval Mintz if (params.pause.forced_rx) 1457cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE; 1458cc875c2eSYuval Mintz if (params.pause.forced_tx) 1459cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE; 1460cc875c2eSYuval Mintz 1461cc875c2eSYuval Mintz /* Link partner capabilities */ 1462054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD) 1463054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_1000baseT_Half_BIT; 1464054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD) 1465054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_1000baseT_Full_BIT; 1466054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G) 1467054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT; 1468054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_25G) 1469054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_25000baseKR_Full_BIT; 1470054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_40G) 1471054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_40000baseLR4_Full_BIT; 1472054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_50G) 1473054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_50000baseKR2_Full_BIT; 1474054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_100G) 1475054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_100000baseKR4_Full_BIT; 1476cc875c2eSYuval Mintz 1477cc875c2eSYuval Mintz if (link.an_complete) 1478054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Autoneg_BIT; 1479cc875c2eSYuval Mintz 1480cc875c2eSYuval Mintz if (link.partner_adv_pause) 1481054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Pause_BIT; 1482cc875c2eSYuval Mintz if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE || 1483cc875c2eSYuval Mintz link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE) 1484054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Asym_Pause_BIT; 1485cc875c2eSYuval Mintz } 1486cc875c2eSYuval Mintz 1487cc875c2eSYuval Mintz static void qed_get_current_link(struct qed_dev *cdev, 1488cc875c2eSYuval Mintz struct qed_link_output *if_link) 1489cc875c2eSYuval Mintz { 149036558c3dSYuval Mintz int i; 149136558c3dSYuval Mintz 1492cc875c2eSYuval Mintz qed_fill_link(&cdev->hwfns[0], if_link); 149336558c3dSYuval Mintz 149436558c3dSYuval Mintz for_each_hwfn(cdev, i) 149536558c3dSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 1496cc875c2eSYuval Mintz } 1497cc875c2eSYuval Mintz 1498cc875c2eSYuval Mintz void qed_link_update(struct qed_hwfn *hwfn) 1499cc875c2eSYuval Mintz { 1500cc875c2eSYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 1501cc875c2eSYuval Mintz struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 1502cc875c2eSYuval Mintz struct qed_link_output if_link; 1503cc875c2eSYuval Mintz 1504cc875c2eSYuval Mintz qed_fill_link(hwfn, &if_link); 150536558c3dSYuval Mintz qed_inform_vf_link_state(hwfn); 1506cc875c2eSYuval Mintz 1507cc875c2eSYuval Mintz if (IS_LEAD_HWFN(hwfn) && cookie) 1508cc875c2eSYuval Mintz op->link_update(cookie, &if_link); 1509cc875c2eSYuval Mintz } 1510cc875c2eSYuval Mintz 1511fe56b9e6SYuval Mintz static int qed_drain(struct qed_dev *cdev) 1512fe56b9e6SYuval Mintz { 1513fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 1514fe56b9e6SYuval Mintz struct qed_ptt *ptt; 1515fe56b9e6SYuval Mintz int i, rc; 1516fe56b9e6SYuval Mintz 15171408cc1fSYuval Mintz if (IS_VF(cdev)) 15181408cc1fSYuval Mintz return 0; 15191408cc1fSYuval Mintz 1520fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1521fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 1522fe56b9e6SYuval Mintz ptt = qed_ptt_acquire(hwfn); 1523fe56b9e6SYuval Mintz if (!ptt) { 1524fe56b9e6SYuval Mintz DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n"); 1525fe56b9e6SYuval Mintz return -EBUSY; 1526fe56b9e6SYuval Mintz } 1527fe56b9e6SYuval Mintz rc = qed_mcp_drain(hwfn, ptt); 1528fe56b9e6SYuval Mintz if (rc) 1529fe56b9e6SYuval Mintz return rc; 1530fe56b9e6SYuval Mintz qed_ptt_release(hwfn, ptt); 1531fe56b9e6SYuval Mintz } 1532fe56b9e6SYuval Mintz 1533fe56b9e6SYuval Mintz return 0; 1534fe56b9e6SYuval Mintz } 1535fe56b9e6SYuval Mintz 1536722003acSSudarsana Reddy Kalluru static void qed_get_coalesce(struct qed_dev *cdev, u16 *rx_coal, u16 *tx_coal) 1537722003acSSudarsana Reddy Kalluru { 1538722003acSSudarsana Reddy Kalluru *rx_coal = cdev->rx_coalesce_usecs; 1539722003acSSudarsana Reddy Kalluru *tx_coal = cdev->tx_coalesce_usecs; 1540722003acSSudarsana Reddy Kalluru } 1541722003acSSudarsana Reddy Kalluru 1542722003acSSudarsana Reddy Kalluru static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, 1543f870a3c6Ssudarsana.kalluru@cavium.com u16 qid, u16 sb_id) 1544722003acSSudarsana Reddy Kalluru { 1545722003acSSudarsana Reddy Kalluru struct qed_hwfn *hwfn; 1546722003acSSudarsana Reddy Kalluru struct qed_ptt *ptt; 1547722003acSSudarsana Reddy Kalluru int hwfn_index; 1548722003acSSudarsana Reddy Kalluru int status = 0; 1549722003acSSudarsana Reddy Kalluru 1550722003acSSudarsana Reddy Kalluru hwfn_index = qid % cdev->num_hwfns; 1551722003acSSudarsana Reddy Kalluru hwfn = &cdev->hwfns[hwfn_index]; 1552722003acSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 1553722003acSSudarsana Reddy Kalluru if (!ptt) 1554722003acSSudarsana Reddy Kalluru return -EAGAIN; 1555722003acSSudarsana Reddy Kalluru 1556722003acSSudarsana Reddy Kalluru status = qed_set_rxq_coalesce(hwfn, ptt, rx_coal, 1557722003acSSudarsana Reddy Kalluru qid / cdev->num_hwfns, sb_id); 1558722003acSSudarsana Reddy Kalluru if (status) 1559722003acSSudarsana Reddy Kalluru goto out; 1560722003acSSudarsana Reddy Kalluru status = qed_set_txq_coalesce(hwfn, ptt, tx_coal, 1561722003acSSudarsana Reddy Kalluru qid / cdev->num_hwfns, sb_id); 1562722003acSSudarsana Reddy Kalluru out: 1563722003acSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 1564722003acSSudarsana Reddy Kalluru 1565722003acSSudarsana Reddy Kalluru return status; 1566722003acSSudarsana Reddy Kalluru } 1567722003acSSudarsana Reddy Kalluru 156891420b83SSudarsana Kalluru static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) 156991420b83SSudarsana Kalluru { 157091420b83SSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 157191420b83SSudarsana Kalluru struct qed_ptt *ptt; 157291420b83SSudarsana Kalluru int status = 0; 157391420b83SSudarsana Kalluru 157491420b83SSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 157591420b83SSudarsana Kalluru if (!ptt) 157691420b83SSudarsana Kalluru return -EAGAIN; 157791420b83SSudarsana Kalluru 157891420b83SSudarsana Kalluru status = qed_mcp_set_led(hwfn, ptt, mode); 157991420b83SSudarsana Kalluru 158091420b83SSudarsana Kalluru qed_ptt_release(hwfn, ptt); 158191420b83SSudarsana Kalluru 158291420b83SSudarsana Kalluru return status; 158391420b83SSudarsana Kalluru } 158491420b83SSudarsana Kalluru 158514d39648SMintz, Yuval static int qed_update_wol(struct qed_dev *cdev, bool enabled) 158614d39648SMintz, Yuval { 158714d39648SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 158814d39648SMintz, Yuval struct qed_ptt *ptt; 158914d39648SMintz, Yuval int rc = 0; 159014d39648SMintz, Yuval 159114d39648SMintz, Yuval if (IS_VF(cdev)) 159214d39648SMintz, Yuval return 0; 159314d39648SMintz, Yuval 159414d39648SMintz, Yuval ptt = qed_ptt_acquire(hwfn); 159514d39648SMintz, Yuval if (!ptt) 159614d39648SMintz, Yuval return -EAGAIN; 159714d39648SMintz, Yuval 159814d39648SMintz, Yuval rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED 159914d39648SMintz, Yuval : QED_OV_WOL_DISABLED); 160014d39648SMintz, Yuval if (rc) 160114d39648SMintz, Yuval goto out; 160214d39648SMintz, Yuval rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 160314d39648SMintz, Yuval 160414d39648SMintz, Yuval out: 160514d39648SMintz, Yuval qed_ptt_release(hwfn, ptt); 160614d39648SMintz, Yuval return rc; 160714d39648SMintz, Yuval } 160814d39648SMintz, Yuval 16090fefbfbaSSudarsana Kalluru static int qed_update_drv_state(struct qed_dev *cdev, bool active) 16100fefbfbaSSudarsana Kalluru { 16110fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 16120fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 16130fefbfbaSSudarsana Kalluru int status = 0; 16140fefbfbaSSudarsana Kalluru 16150fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 16160fefbfbaSSudarsana Kalluru return 0; 16170fefbfbaSSudarsana Kalluru 16180fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 16190fefbfbaSSudarsana Kalluru if (!ptt) 16200fefbfbaSSudarsana Kalluru return -EAGAIN; 16210fefbfbaSSudarsana Kalluru 16220fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ? 16230fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_ACTIVE : 16240fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_DISABLED); 16250fefbfbaSSudarsana Kalluru 16260fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 16270fefbfbaSSudarsana Kalluru 16280fefbfbaSSudarsana Kalluru return status; 16290fefbfbaSSudarsana Kalluru } 16300fefbfbaSSudarsana Kalluru 16310fefbfbaSSudarsana Kalluru static int qed_update_mac(struct qed_dev *cdev, u8 *mac) 16320fefbfbaSSudarsana Kalluru { 16330fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 16340fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 16350fefbfbaSSudarsana Kalluru int status = 0; 16360fefbfbaSSudarsana Kalluru 16370fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 16380fefbfbaSSudarsana Kalluru return 0; 16390fefbfbaSSudarsana Kalluru 16400fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 16410fefbfbaSSudarsana Kalluru if (!ptt) 16420fefbfbaSSudarsana Kalluru return -EAGAIN; 16430fefbfbaSSudarsana Kalluru 16440fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mac(hwfn, ptt, mac); 16450fefbfbaSSudarsana Kalluru if (status) 16460fefbfbaSSudarsana Kalluru goto out; 16470fefbfbaSSudarsana Kalluru 16480fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 16490fefbfbaSSudarsana Kalluru 16500fefbfbaSSudarsana Kalluru out: 16510fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 16520fefbfbaSSudarsana Kalluru return status; 16530fefbfbaSSudarsana Kalluru } 16540fefbfbaSSudarsana Kalluru 16550fefbfbaSSudarsana Kalluru static int qed_update_mtu(struct qed_dev *cdev, u16 mtu) 16560fefbfbaSSudarsana Kalluru { 16570fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 16580fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 16590fefbfbaSSudarsana Kalluru int status = 0; 16600fefbfbaSSudarsana Kalluru 16610fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 16620fefbfbaSSudarsana Kalluru return 0; 16630fefbfbaSSudarsana Kalluru 16640fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 16650fefbfbaSSudarsana Kalluru if (!ptt) 16660fefbfbaSSudarsana Kalluru return -EAGAIN; 16670fefbfbaSSudarsana Kalluru 16680fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu); 16690fefbfbaSSudarsana Kalluru if (status) 16700fefbfbaSSudarsana Kalluru goto out; 16710fefbfbaSSudarsana Kalluru 16720fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 16730fefbfbaSSudarsana Kalluru 16740fefbfbaSSudarsana Kalluru out: 16750fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 16760fefbfbaSSudarsana Kalluru return status; 16770fefbfbaSSudarsana Kalluru } 16780fefbfbaSSudarsana Kalluru 16798c93beafSYuval Mintz static struct qed_selftest_ops qed_selftest_ops_pass = { 168003dc76caSSudarsana Reddy Kalluru .selftest_memory = &qed_selftest_memory, 168103dc76caSSudarsana Reddy Kalluru .selftest_interrupt = &qed_selftest_interrupt, 168203dc76caSSudarsana Reddy Kalluru .selftest_register = &qed_selftest_register, 168303dc76caSSudarsana Reddy Kalluru .selftest_clock = &qed_selftest_clock, 16847a4b21b7SMintz, Yuval .selftest_nvram = &qed_selftest_nvram, 168503dc76caSSudarsana Reddy Kalluru }; 168603dc76caSSudarsana Reddy Kalluru 1687fe56b9e6SYuval Mintz const struct qed_common_ops qed_common_ops_pass = { 168803dc76caSSudarsana Reddy Kalluru .selftest = &qed_selftest_ops_pass, 1689fe56b9e6SYuval Mintz .probe = &qed_probe, 1690fe56b9e6SYuval Mintz .remove = &qed_remove, 1691fe56b9e6SYuval Mintz .set_power_state = &qed_set_power_state, 1692712c3cbfSMintz, Yuval .set_name = &qed_set_name, 1693fe56b9e6SYuval Mintz .update_pf_params = &qed_update_pf_params, 1694fe56b9e6SYuval Mintz .slowpath_start = &qed_slowpath_start, 1695fe56b9e6SYuval Mintz .slowpath_stop = &qed_slowpath_stop, 1696fe56b9e6SYuval Mintz .set_fp_int = &qed_set_int_fp, 1697fe56b9e6SYuval Mintz .get_fp_int = &qed_get_int_fp, 1698fe56b9e6SYuval Mintz .sb_init = &qed_sb_init, 1699fe56b9e6SYuval Mintz .sb_release = &qed_sb_release, 1700fe56b9e6SYuval Mintz .simd_handler_config = &qed_simd_handler_config, 1701fe56b9e6SYuval Mintz .simd_handler_clean = &qed_simd_handler_clean, 17021e128c81SArun Easi .dbg_grc = &qed_dbg_grc, 17031e128c81SArun Easi .dbg_grc_size = &qed_dbg_grc_size, 1704fe7cd2bfSYuval Mintz .can_link_change = &qed_can_link_change, 1705cc875c2eSYuval Mintz .set_link = &qed_set_link, 1706cc875c2eSYuval Mintz .get_link = &qed_get_current_link, 1707fe56b9e6SYuval Mintz .drain = &qed_drain, 1708fe56b9e6SYuval Mintz .update_msglvl = &qed_init_dp, 1709e0971c83STomer Tayar .dbg_all_data = &qed_dbg_all_data, 1710e0971c83STomer Tayar .dbg_all_data_size = &qed_dbg_all_data_size, 1711fe56b9e6SYuval Mintz .chain_alloc = &qed_chain_alloc, 1712fe56b9e6SYuval Mintz .chain_free = &qed_chain_free, 1713722003acSSudarsana Reddy Kalluru .get_coalesce = &qed_get_coalesce, 1714722003acSSudarsana Reddy Kalluru .set_coalesce = &qed_set_coalesce, 171591420b83SSudarsana Kalluru .set_led = &qed_set_led, 17160fefbfbaSSudarsana Kalluru .update_drv_state = &qed_update_drv_state, 17170fefbfbaSSudarsana Kalluru .update_mac = &qed_update_mac, 17180fefbfbaSSudarsana Kalluru .update_mtu = &qed_update_mtu, 171914d39648SMintz, Yuval .update_wol = &qed_update_wol, 1720fe56b9e6SYuval Mintz }; 17216c754246SSudarsana Reddy Kalluru 17226c754246SSudarsana Reddy Kalluru void qed_get_protocol_stats(struct qed_dev *cdev, 17236c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type type, 17246c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats *stats) 17256c754246SSudarsana Reddy Kalluru { 17266c754246SSudarsana Reddy Kalluru struct qed_eth_stats eth_stats; 17276c754246SSudarsana Reddy Kalluru 17286c754246SSudarsana Reddy Kalluru memset(stats, 0, sizeof(*stats)); 17296c754246SSudarsana Reddy Kalluru 17306c754246SSudarsana Reddy Kalluru switch (type) { 17316c754246SSudarsana Reddy Kalluru case QED_MCP_LAN_STATS: 17326c754246SSudarsana Reddy Kalluru qed_get_vport_stats(cdev, ð_stats); 17339c79ddaaSMintz, Yuval stats->lan_stats.ucast_rx_pkts = 17349c79ddaaSMintz, Yuval eth_stats.common.rx_ucast_pkts; 17359c79ddaaSMintz, Yuval stats->lan_stats.ucast_tx_pkts = 17369c79ddaaSMintz, Yuval eth_stats.common.tx_ucast_pkts; 17376c754246SSudarsana Reddy Kalluru stats->lan_stats.fcs_err = -1; 17386c754246SSudarsana Reddy Kalluru break; 17391e128c81SArun Easi case QED_MCP_FCOE_STATS: 17401e128c81SArun Easi qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats); 17411e128c81SArun Easi break; 17422f2b2614SMintz, Yuval case QED_MCP_ISCSI_STATS: 17432f2b2614SMintz, Yuval qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); 17442f2b2614SMintz, Yuval break; 17456c754246SSudarsana Reddy Kalluru default: 17466c754246SSudarsana Reddy Kalluru DP_ERR(cdev, "Invalid protocol type = %d\n", type); 17476c754246SSudarsana Reddy Kalluru return; 17486c754246SSudarsana Reddy Kalluru } 17496c754246SSudarsana Reddy Kalluru } 1750