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 1251a850bfcSMintz, Yuval if (cdev->doorbells && cdev->db_size) 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 209fe56b9e6SYuval Mintz cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2); 210fe56b9e6SYuval Mintz cdev->db_size = pci_resource_len(cdev->pdev, 2); 2111a850bfcSMintz, Yuval if (!cdev->db_size) { 2121a850bfcSMintz, Yuval if (IS_PF(cdev)) { 2131a850bfcSMintz, Yuval DP_NOTICE(cdev, "No Doorbell bar available\n"); 2141a850bfcSMintz, Yuval return -EINVAL; 2151a850bfcSMintz, Yuval } else { 2161a850bfcSMintz, Yuval return 0; 2171a850bfcSMintz, Yuval } 2181a850bfcSMintz, Yuval } 2191a850bfcSMintz, Yuval 220fe56b9e6SYuval Mintz cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size); 2211a850bfcSMintz, Yuval 222fe56b9e6SYuval Mintz if (!cdev->doorbells) { 223fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map doorbell space\n"); 224fe56b9e6SYuval Mintz return -ENOMEM; 225fe56b9e6SYuval Mintz } 226fe56b9e6SYuval Mintz 227fe56b9e6SYuval Mintz return 0; 228fe56b9e6SYuval Mintz 229fe56b9e6SYuval Mintz err2: 230fe56b9e6SYuval Mintz pci_release_regions(pdev); 231fe56b9e6SYuval Mintz err1: 232fe56b9e6SYuval Mintz pci_disable_device(pdev); 233fe56b9e6SYuval Mintz err0: 234fe56b9e6SYuval Mintz return rc; 235fe56b9e6SYuval Mintz } 236fe56b9e6SYuval Mintz 237fe56b9e6SYuval Mintz int qed_fill_dev_info(struct qed_dev *cdev, 238fe56b9e6SYuval Mintz struct qed_dev_info *dev_info) 239fe56b9e6SYuval Mintz { 240c851a9dcSKalderon, Michal struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 241c851a9dcSKalderon, Michal struct qed_hw_info *hw_info = &p_hwfn->hw_info; 24219489c7fSChopra, Manish struct qed_tunnel_info *tun = &cdev->tunnel; 243cee4d264SManish Chopra struct qed_ptt *ptt; 244cee4d264SManish Chopra 245fe56b9e6SYuval Mintz memset(dev_info, 0, sizeof(struct qed_dev_info)); 246fe56b9e6SYuval Mintz 24719489c7fSChopra, Manish if (tun->vxlan.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 24819489c7fSChopra, Manish tun->vxlan.b_mode_enabled) 24919489c7fSChopra, Manish dev_info->vxlan_enable = true; 25019489c7fSChopra, Manish 25119489c7fSChopra, Manish if (tun->l2_gre.b_mode_enabled && tun->ip_gre.b_mode_enabled && 25219489c7fSChopra, Manish tun->l2_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 25319489c7fSChopra, Manish tun->ip_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 25419489c7fSChopra, Manish dev_info->gre_enable = true; 25519489c7fSChopra, Manish 25619489c7fSChopra, Manish if (tun->l2_geneve.b_mode_enabled && tun->ip_geneve.b_mode_enabled && 25719489c7fSChopra, Manish tun->l2_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 25819489c7fSChopra, Manish tun->ip_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 25919489c7fSChopra, Manish dev_info->geneve_enable = true; 26019489c7fSChopra, Manish 261fe56b9e6SYuval Mintz dev_info->num_hwfns = cdev->num_hwfns; 262fe56b9e6SYuval Mintz dev_info->pci_mem_start = cdev->pci_params.mem_start; 263fe56b9e6SYuval Mintz dev_info->pci_mem_end = cdev->pci_params.mem_end; 264fe56b9e6SYuval Mintz dev_info->pci_irq = cdev->pci_params.irq; 265c851a9dcSKalderon, Michal dev_info->rdma_supported = QED_IS_RDMA_PERSONALITY(p_hwfn); 266fc48b7a6SYuval Mintz dev_info->is_mf_default = IS_MF_DEFAULT(&cdev->hwfns[0]); 2679c79ddaaSMintz, Yuval dev_info->dev_type = cdev->type; 268c851a9dcSKalderon, Michal ether_addr_copy(dev_info->hw_mac, hw_info->hw_mac_addr); 269fe56b9e6SYuval Mintz 2701408cc1fSYuval Mintz if (IS_PF(cdev)) { 271fe56b9e6SYuval Mintz dev_info->fw_major = FW_MAJOR_VERSION; 272fe56b9e6SYuval Mintz dev_info->fw_minor = FW_MINOR_VERSION; 273fe56b9e6SYuval Mintz dev_info->fw_rev = FW_REVISION_VERSION; 274fe56b9e6SYuval Mintz dev_info->fw_eng = FW_ENGINEERING_VERSION; 275fe56b9e6SYuval Mintz dev_info->mf_mode = cdev->mf_mode; 276831bfb0eSYuval Mintz dev_info->tx_switching = true; 27714d39648SMintz, Yuval 278c851a9dcSKalderon, Michal if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME) 27914d39648SMintz, Yuval dev_info->wol_support = true; 2803c5da942SMintz, Yuval 2813c5da942SMintz, Yuval dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id; 2821408cc1fSYuval Mintz } else { 2831408cc1fSYuval Mintz qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, 2841408cc1fSYuval Mintz &dev_info->fw_minor, &dev_info->fw_rev, 2851408cc1fSYuval Mintz &dev_info->fw_eng); 2861408cc1fSYuval Mintz } 287fe56b9e6SYuval Mintz 2881408cc1fSYuval Mintz if (IS_PF(cdev)) { 289cee4d264SManish Chopra ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 290cee4d264SManish Chopra if (ptt) { 2911408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), ptt, 2921408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 2931408cc1fSYuval Mintz 294ae33666aSTomer Tayar qed_mcp_get_mbi_ver(QED_LEADING_HWFN(cdev), ptt, 295ae33666aSTomer Tayar &dev_info->mbi_version); 296ae33666aSTomer Tayar 297cee4d264SManish Chopra qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt, 298cee4d264SManish Chopra &dev_info->flash_size); 299cee4d264SManish Chopra 300cee4d264SManish Chopra qed_ptt_release(QED_LEADING_HWFN(cdev), ptt); 301cee4d264SManish Chopra } 3021408cc1fSYuval Mintz } else { 3031408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), NULL, 3041408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 3051408cc1fSYuval Mintz } 306cee4d264SManish Chopra 307c851a9dcSKalderon, Michal dev_info->mtu = hw_info->mtu; 3080fefbfbaSSudarsana Kalluru 309fe56b9e6SYuval Mintz return 0; 310fe56b9e6SYuval Mintz } 311fe56b9e6SYuval Mintz 312fe56b9e6SYuval Mintz static void qed_free_cdev(struct qed_dev *cdev) 313fe56b9e6SYuval Mintz { 314fe56b9e6SYuval Mintz kfree((void *)cdev); 315fe56b9e6SYuval Mintz } 316fe56b9e6SYuval Mintz 317fe56b9e6SYuval Mintz static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev) 318fe56b9e6SYuval Mintz { 319fe56b9e6SYuval Mintz struct qed_dev *cdev; 320fe56b9e6SYuval Mintz 321fe56b9e6SYuval Mintz cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 322fe56b9e6SYuval Mintz if (!cdev) 323fe56b9e6SYuval Mintz return cdev; 324fe56b9e6SYuval Mintz 325fe56b9e6SYuval Mintz qed_init_struct(cdev); 326fe56b9e6SYuval Mintz 327fe56b9e6SYuval Mintz return cdev; 328fe56b9e6SYuval Mintz } 329fe56b9e6SYuval Mintz 330fe56b9e6SYuval Mintz /* Sets the requested power state */ 3311a635e48SYuval Mintz static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state) 332fe56b9e6SYuval Mintz { 333fe56b9e6SYuval Mintz if (!cdev) 334fe56b9e6SYuval Mintz return -ENODEV; 335fe56b9e6SYuval Mintz 336fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n"); 337fe56b9e6SYuval Mintz return 0; 338fe56b9e6SYuval Mintz } 339fe56b9e6SYuval Mintz 340fe56b9e6SYuval Mintz /* probing */ 341fe56b9e6SYuval Mintz static struct qed_dev *qed_probe(struct pci_dev *pdev, 3421408cc1fSYuval Mintz struct qed_probe_params *params) 343fe56b9e6SYuval Mintz { 344fe56b9e6SYuval Mintz struct qed_dev *cdev; 345fe56b9e6SYuval Mintz int rc; 346fe56b9e6SYuval Mintz 347fe56b9e6SYuval Mintz cdev = qed_alloc_cdev(pdev); 348fe56b9e6SYuval Mintz if (!cdev) 349fe56b9e6SYuval Mintz goto err0; 350fe56b9e6SYuval Mintz 351712c3cbfSMintz, Yuval cdev->drv_type = DRV_ID_DRV_TYPE_LINUX; 3521408cc1fSYuval Mintz cdev->protocol = params->protocol; 353fe56b9e6SYuval Mintz 3541408cc1fSYuval Mintz if (params->is_vf) 3551408cc1fSYuval Mintz cdev->b_is_vf = true; 3561408cc1fSYuval Mintz 3571408cc1fSYuval Mintz qed_init_dp(cdev, params->dp_module, params->dp_level); 358fe56b9e6SYuval Mintz 359fe56b9e6SYuval Mintz rc = qed_init_pci(cdev, pdev); 360fe56b9e6SYuval Mintz if (rc) { 361fe56b9e6SYuval Mintz DP_ERR(cdev, "init pci failed\n"); 362fe56b9e6SYuval Mintz goto err1; 363fe56b9e6SYuval Mintz } 364fe56b9e6SYuval Mintz DP_INFO(cdev, "PCI init completed successfully\n"); 365fe56b9e6SYuval Mintz 366fe56b9e6SYuval Mintz rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); 367fe56b9e6SYuval Mintz if (rc) { 368fe56b9e6SYuval Mintz DP_ERR(cdev, "hw prepare failed\n"); 369fe56b9e6SYuval Mintz goto err2; 370fe56b9e6SYuval Mintz } 371fe56b9e6SYuval Mintz 372fe56b9e6SYuval Mintz DP_INFO(cdev, "qed_probe completed successffuly\n"); 373fe56b9e6SYuval Mintz 374fe56b9e6SYuval Mintz return cdev; 375fe56b9e6SYuval Mintz 376fe56b9e6SYuval Mintz err2: 377fe56b9e6SYuval Mintz qed_free_pci(cdev); 378fe56b9e6SYuval Mintz err1: 379fe56b9e6SYuval Mintz qed_free_cdev(cdev); 380fe56b9e6SYuval Mintz err0: 381fe56b9e6SYuval Mintz return NULL; 382fe56b9e6SYuval Mintz } 383fe56b9e6SYuval Mintz 384fe56b9e6SYuval Mintz static void qed_remove(struct qed_dev *cdev) 385fe56b9e6SYuval Mintz { 386fe56b9e6SYuval Mintz if (!cdev) 387fe56b9e6SYuval Mintz return; 388fe56b9e6SYuval Mintz 389fe56b9e6SYuval Mintz qed_hw_remove(cdev); 390fe56b9e6SYuval Mintz 391fe56b9e6SYuval Mintz qed_free_pci(cdev); 392fe56b9e6SYuval Mintz 393fe56b9e6SYuval Mintz qed_set_power_state(cdev, PCI_D3hot); 394fe56b9e6SYuval Mintz 395fe56b9e6SYuval Mintz qed_free_cdev(cdev); 396fe56b9e6SYuval Mintz } 397fe56b9e6SYuval Mintz 398fe56b9e6SYuval Mintz static void qed_disable_msix(struct qed_dev *cdev) 399fe56b9e6SYuval Mintz { 400fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 401fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 402fe56b9e6SYuval Mintz kfree(cdev->int_params.msix_table); 403fe56b9e6SYuval Mintz } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) { 404fe56b9e6SYuval Mintz pci_disable_msi(cdev->pdev); 405fe56b9e6SYuval Mintz } 406fe56b9e6SYuval Mintz 407fe56b9e6SYuval Mintz memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param)); 408fe56b9e6SYuval Mintz } 409fe56b9e6SYuval Mintz 410fe56b9e6SYuval Mintz static int qed_enable_msix(struct qed_dev *cdev, 411fe56b9e6SYuval Mintz struct qed_int_params *int_params) 412fe56b9e6SYuval Mintz { 413fe56b9e6SYuval Mintz int i, rc, cnt; 414fe56b9e6SYuval Mintz 415fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 416fe56b9e6SYuval Mintz 417fe56b9e6SYuval Mintz for (i = 0; i < cnt; i++) 418fe56b9e6SYuval Mintz int_params->msix_table[i].entry = i; 419fe56b9e6SYuval Mintz 420fe56b9e6SYuval Mintz rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table, 421fe56b9e6SYuval Mintz int_params->in.min_msix_cnt, cnt); 422fe56b9e6SYuval Mintz if (rc < cnt && rc >= int_params->in.min_msix_cnt && 423fe56b9e6SYuval Mintz (rc % cdev->num_hwfns)) { 424fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 425fe56b9e6SYuval Mintz 426fe56b9e6SYuval Mintz /* If fastpath is initialized, we need at least one interrupt 427fe56b9e6SYuval Mintz * per hwfn [and the slow path interrupts]. New requested number 428fe56b9e6SYuval Mintz * should be a multiple of the number of hwfns. 429fe56b9e6SYuval Mintz */ 430fe56b9e6SYuval Mintz cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns; 431fe56b9e6SYuval Mintz DP_NOTICE(cdev, 432fe56b9e6SYuval Mintz "Trying to enable MSI-X with less vectors (%d out of %d)\n", 433fe56b9e6SYuval Mintz cnt, int_params->in.num_vectors); 4341a635e48SYuval Mintz rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table, 4351a635e48SYuval Mintz cnt); 436fe56b9e6SYuval Mintz if (!rc) 437fe56b9e6SYuval Mintz rc = cnt; 438fe56b9e6SYuval Mintz } 439fe56b9e6SYuval Mintz 440fe56b9e6SYuval Mintz if (rc > 0) { 441fe56b9e6SYuval Mintz /* MSI-x configuration was achieved */ 442fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSIX; 443fe56b9e6SYuval Mintz int_params->out.num_vectors = rc; 444fe56b9e6SYuval Mintz rc = 0; 445fe56b9e6SYuval Mintz } else { 446fe56b9e6SYuval Mintz DP_NOTICE(cdev, 447fe56b9e6SYuval Mintz "Failed to enable MSI-X [Requested %d vectors][rc %d]\n", 448fe56b9e6SYuval Mintz cnt, rc); 449fe56b9e6SYuval Mintz } 450fe56b9e6SYuval Mintz 451fe56b9e6SYuval Mintz return rc; 452fe56b9e6SYuval Mintz } 453fe56b9e6SYuval Mintz 454fe56b9e6SYuval Mintz /* This function outputs the int mode and the number of enabled msix vector */ 455fe56b9e6SYuval Mintz static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) 456fe56b9e6SYuval Mintz { 457fe56b9e6SYuval Mintz struct qed_int_params *int_params = &cdev->int_params; 458fe56b9e6SYuval Mintz struct msix_entry *tbl; 459fe56b9e6SYuval Mintz int rc = 0, cnt; 460fe56b9e6SYuval Mintz 461fe56b9e6SYuval Mintz switch (int_params->in.int_mode) { 462fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 463fe56b9e6SYuval Mintz /* Allocate MSIX table */ 464fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 465fe56b9e6SYuval Mintz int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL); 466fe56b9e6SYuval Mintz if (!int_params->msix_table) { 467fe56b9e6SYuval Mintz rc = -ENOMEM; 468fe56b9e6SYuval Mintz goto out; 469fe56b9e6SYuval Mintz } 470fe56b9e6SYuval Mintz 471fe56b9e6SYuval Mintz /* Enable MSIX */ 472fe56b9e6SYuval Mintz rc = qed_enable_msix(cdev, int_params); 473fe56b9e6SYuval Mintz if (!rc) 474fe56b9e6SYuval Mintz goto out; 475fe56b9e6SYuval Mintz 476fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI-X\n"); 477fe56b9e6SYuval Mintz kfree(int_params->msix_table); 478fe56b9e6SYuval Mintz if (force_mode) 479fe56b9e6SYuval Mintz goto out; 480fe56b9e6SYuval Mintz /* Fallthrough */ 481fe56b9e6SYuval Mintz 482fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 483bb13ace7SSudarsana Reddy Kalluru if (cdev->num_hwfns == 1) { 484fe56b9e6SYuval Mintz rc = pci_enable_msi(cdev->pdev); 485fe56b9e6SYuval Mintz if (!rc) { 486fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSI; 487fe56b9e6SYuval Mintz goto out; 488fe56b9e6SYuval Mintz } 489fe56b9e6SYuval Mintz 490fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI\n"); 491fe56b9e6SYuval Mintz if (force_mode) 492fe56b9e6SYuval Mintz goto out; 493bb13ace7SSudarsana Reddy Kalluru } 494fe56b9e6SYuval Mintz /* Fallthrough */ 495fe56b9e6SYuval Mintz 496fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 497fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_INTA; 498fe56b9e6SYuval Mintz rc = 0; 499fe56b9e6SYuval Mintz goto out; 500fe56b9e6SYuval Mintz default: 501fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Unknown int_mode value %d\n", 502fe56b9e6SYuval Mintz int_params->in.int_mode); 503fe56b9e6SYuval Mintz rc = -EINVAL; 504fe56b9e6SYuval Mintz } 505fe56b9e6SYuval Mintz 506fe56b9e6SYuval Mintz out: 507525ef5c0SYuval Mintz if (!rc) 508525ef5c0SYuval Mintz DP_INFO(cdev, "Using %s interrupts\n", 509525ef5c0SYuval Mintz int_params->out.int_mode == QED_INT_MODE_INTA ? 510525ef5c0SYuval Mintz "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ? 511525ef5c0SYuval Mintz "MSI" : "MSIX"); 512fe56b9e6SYuval Mintz cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE; 513fe56b9e6SYuval Mintz 514fe56b9e6SYuval Mintz return rc; 515fe56b9e6SYuval Mintz } 516fe56b9e6SYuval Mintz 517fe56b9e6SYuval Mintz static void qed_simd_handler_config(struct qed_dev *cdev, void *token, 518fe56b9e6SYuval Mintz int index, void(*handler)(void *)) 519fe56b9e6SYuval Mintz { 520fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 521fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 522fe56b9e6SYuval Mintz 523fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].func = handler; 524fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].token = token; 525fe56b9e6SYuval Mintz } 526fe56b9e6SYuval Mintz 527fe56b9e6SYuval Mintz static void qed_simd_handler_clean(struct qed_dev *cdev, int index) 528fe56b9e6SYuval Mintz { 529fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 530fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 531fe56b9e6SYuval Mintz 532fe56b9e6SYuval Mintz memset(&hwfn->simd_proto_handler[relative_idx], 0, 533fe56b9e6SYuval Mintz sizeof(struct qed_simd_fp_handler)); 534fe56b9e6SYuval Mintz } 535fe56b9e6SYuval Mintz 536fe56b9e6SYuval Mintz static irqreturn_t qed_msix_sp_int(int irq, void *tasklet) 537fe56b9e6SYuval Mintz { 538fe56b9e6SYuval Mintz tasklet_schedule((struct tasklet_struct *)tasklet); 539fe56b9e6SYuval Mintz return IRQ_HANDLED; 540fe56b9e6SYuval Mintz } 541fe56b9e6SYuval Mintz 542fe56b9e6SYuval Mintz static irqreturn_t qed_single_int(int irq, void *dev_instance) 543fe56b9e6SYuval Mintz { 544fe56b9e6SYuval Mintz struct qed_dev *cdev = (struct qed_dev *)dev_instance; 545fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 546fe56b9e6SYuval Mintz irqreturn_t rc = IRQ_NONE; 547fe56b9e6SYuval Mintz u64 status; 548fe56b9e6SYuval Mintz int i, j; 549fe56b9e6SYuval Mintz 550fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 551fe56b9e6SYuval Mintz status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]); 552fe56b9e6SYuval Mintz 553fe56b9e6SYuval Mintz if (!status) 554fe56b9e6SYuval Mintz continue; 555fe56b9e6SYuval Mintz 556fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 557fe56b9e6SYuval Mintz 558fe56b9e6SYuval Mintz /* Slowpath interrupt */ 559fe56b9e6SYuval Mintz if (unlikely(status & 0x1)) { 560fe56b9e6SYuval Mintz tasklet_schedule(hwfn->sp_dpc); 561fe56b9e6SYuval Mintz status &= ~0x1; 562fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 563fe56b9e6SYuval Mintz } 564fe56b9e6SYuval Mintz 565fe56b9e6SYuval Mintz /* Fastpath interrupts */ 566fe56b9e6SYuval Mintz for (j = 0; j < 64; j++) { 567fe56b9e6SYuval Mintz if ((0x2ULL << j) & status) { 568fe56b9e6SYuval Mintz hwfn->simd_proto_handler[j].func( 569fe56b9e6SYuval Mintz hwfn->simd_proto_handler[j].token); 570fe56b9e6SYuval Mintz status &= ~(0x2ULL << j); 571fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 572fe56b9e6SYuval Mintz } 573fe56b9e6SYuval Mintz } 574fe56b9e6SYuval Mintz 575fe56b9e6SYuval Mintz if (unlikely(status)) 576fe56b9e6SYuval Mintz DP_VERBOSE(hwfn, NETIF_MSG_INTR, 577fe56b9e6SYuval Mintz "got an unknown interrupt status 0x%llx\n", 578fe56b9e6SYuval Mintz status); 579fe56b9e6SYuval Mintz } 580fe56b9e6SYuval Mintz 581fe56b9e6SYuval Mintz return rc; 582fe56b9e6SYuval Mintz } 583fe56b9e6SYuval Mintz 5848f16bc97SSudarsana Kalluru int qed_slowpath_irq_req(struct qed_hwfn *hwfn) 585fe56b9e6SYuval Mintz { 5868f16bc97SSudarsana Kalluru struct qed_dev *cdev = hwfn->cdev; 587525ef5c0SYuval Mintz u32 int_mode; 5888f16bc97SSudarsana Kalluru int rc = 0; 5898f16bc97SSudarsana Kalluru u8 id; 590fe56b9e6SYuval Mintz 591525ef5c0SYuval Mintz int_mode = cdev->int_params.out.int_mode; 592525ef5c0SYuval Mintz if (int_mode == QED_INT_MODE_MSIX) { 5938f16bc97SSudarsana Kalluru id = hwfn->my_id; 5948f16bc97SSudarsana Kalluru snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x", 5958f16bc97SSudarsana Kalluru id, cdev->pdev->bus->number, 5968f16bc97SSudarsana Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 5978f16bc97SSudarsana Kalluru rc = request_irq(cdev->int_params.msix_table[id].vector, 5988f16bc97SSudarsana Kalluru qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); 599fe56b9e6SYuval Mintz } else { 600fe56b9e6SYuval Mintz unsigned long flags = 0; 601fe56b9e6SYuval Mintz 602fe56b9e6SYuval Mintz snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x", 603fe56b9e6SYuval Mintz cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), 604fe56b9e6SYuval Mintz PCI_FUNC(cdev->pdev->devfn)); 605fe56b9e6SYuval Mintz 606fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA) 607fe56b9e6SYuval Mintz flags |= IRQF_SHARED; 608fe56b9e6SYuval Mintz 609fe56b9e6SYuval Mintz rc = request_irq(cdev->pdev->irq, qed_single_int, 610fe56b9e6SYuval Mintz flags, cdev->name, cdev); 611fe56b9e6SYuval Mintz } 612fe56b9e6SYuval Mintz 613525ef5c0SYuval Mintz if (rc) 614525ef5c0SYuval Mintz DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc); 615525ef5c0SYuval Mintz else 616525ef5c0SYuval Mintz DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP), 617525ef5c0SYuval Mintz "Requested slowpath %s\n", 618525ef5c0SYuval Mintz (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ"); 619525ef5c0SYuval Mintz 620fe56b9e6SYuval Mintz return rc; 621fe56b9e6SYuval Mintz } 622fe56b9e6SYuval Mintz 62306892f2eSTomer Tayar static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn) 62406892f2eSTomer Tayar { 62506892f2eSTomer Tayar /* Calling the disable function will make sure that any 62606892f2eSTomer Tayar * currently-running function is completed. The following call to the 62706892f2eSTomer Tayar * enable function makes this sequence a flush-like operation. 62806892f2eSTomer Tayar */ 62906892f2eSTomer Tayar if (p_hwfn->b_sp_dpc_enabled) { 63006892f2eSTomer Tayar tasklet_disable(p_hwfn->sp_dpc); 63106892f2eSTomer Tayar tasklet_enable(p_hwfn->sp_dpc); 63206892f2eSTomer Tayar } 63306892f2eSTomer Tayar } 63406892f2eSTomer Tayar 6351226337aSTomer Tayar void qed_slowpath_irq_sync(struct qed_hwfn *p_hwfn) 6361226337aSTomer Tayar { 6371226337aSTomer Tayar struct qed_dev *cdev = p_hwfn->cdev; 6381226337aSTomer Tayar u8 id = p_hwfn->my_id; 6391226337aSTomer Tayar u32 int_mode; 6401226337aSTomer Tayar 6411226337aSTomer Tayar int_mode = cdev->int_params.out.int_mode; 6421226337aSTomer Tayar if (int_mode == QED_INT_MODE_MSIX) 6431226337aSTomer Tayar synchronize_irq(cdev->int_params.msix_table[id].vector); 6441226337aSTomer Tayar else 6451226337aSTomer Tayar synchronize_irq(cdev->pdev->irq); 64606892f2eSTomer Tayar 64706892f2eSTomer Tayar qed_slowpath_tasklet_flush(p_hwfn); 6481226337aSTomer Tayar } 6491226337aSTomer Tayar 650fe56b9e6SYuval Mintz static void qed_slowpath_irq_free(struct qed_dev *cdev) 651fe56b9e6SYuval Mintz { 652fe56b9e6SYuval Mintz int i; 653fe56b9e6SYuval Mintz 654fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 655fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 6568f16bc97SSudarsana Kalluru if (!cdev->hwfns[i].b_int_requested) 6578f16bc97SSudarsana Kalluru break; 658fe56b9e6SYuval Mintz synchronize_irq(cdev->int_params.msix_table[i].vector); 659fe56b9e6SYuval Mintz free_irq(cdev->int_params.msix_table[i].vector, 660fe56b9e6SYuval Mintz cdev->hwfns[i].sp_dpc); 661fe56b9e6SYuval Mintz } 662fe56b9e6SYuval Mintz } else { 6638f16bc97SSudarsana Kalluru if (QED_LEADING_HWFN(cdev)->b_int_requested) 664fe56b9e6SYuval Mintz free_irq(cdev->pdev->irq, cdev); 665fe56b9e6SYuval Mintz } 6668f16bc97SSudarsana Kalluru qed_int_disable_post_isr_release(cdev); 667fe56b9e6SYuval Mintz } 668fe56b9e6SYuval Mintz 669fe56b9e6SYuval Mintz static int qed_nic_stop(struct qed_dev *cdev) 670fe56b9e6SYuval Mintz { 671fe56b9e6SYuval Mintz int i, rc; 672fe56b9e6SYuval Mintz 673fe56b9e6SYuval Mintz rc = qed_hw_stop(cdev); 674fe56b9e6SYuval Mintz 675fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 676fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 677fe56b9e6SYuval Mintz 678fe56b9e6SYuval Mintz if (p_hwfn->b_sp_dpc_enabled) { 679fe56b9e6SYuval Mintz tasklet_disable(p_hwfn->sp_dpc); 680fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = false; 681fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_IFDOWN, 682fe56b9e6SYuval Mintz "Disabled sp taskelt [hwfn %d] at %p\n", 683fe56b9e6SYuval Mintz i, p_hwfn->sp_dpc); 684fe56b9e6SYuval Mintz } 685fe56b9e6SYuval Mintz } 686fe56b9e6SYuval Mintz 687c965db44STomer Tayar qed_dbg_pf_exit(cdev); 688c965db44STomer Tayar 689fe56b9e6SYuval Mintz return rc; 690fe56b9e6SYuval Mintz } 691fe56b9e6SYuval Mintz 692fe56b9e6SYuval Mintz static int qed_nic_setup(struct qed_dev *cdev) 693fe56b9e6SYuval Mintz { 6940a7fb11cSYuval Mintz int rc, i; 6950a7fb11cSYuval Mintz 6960a7fb11cSYuval Mintz /* Determine if interface is going to require LL2 */ 6970a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) { 6980a7fb11cSYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 6990a7fb11cSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 7000a7fb11cSYuval Mintz 7010a7fb11cSYuval Mintz p_hwfn->using_ll2 = true; 7020a7fb11cSYuval Mintz } 7030a7fb11cSYuval Mintz } 704fe56b9e6SYuval Mintz 705fe56b9e6SYuval Mintz rc = qed_resc_alloc(cdev); 706fe56b9e6SYuval Mintz if (rc) 707fe56b9e6SYuval Mintz return rc; 708fe56b9e6SYuval Mintz 709fe56b9e6SYuval Mintz DP_INFO(cdev, "Allocated qed resources\n"); 710fe56b9e6SYuval Mintz 711fe56b9e6SYuval Mintz qed_resc_setup(cdev); 712fe56b9e6SYuval Mintz 713fe56b9e6SYuval Mintz return rc; 714fe56b9e6SYuval Mintz } 715fe56b9e6SYuval Mintz 716fe56b9e6SYuval Mintz static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt) 717fe56b9e6SYuval Mintz { 718fe56b9e6SYuval Mintz int limit = 0; 719fe56b9e6SYuval Mintz 720fe56b9e6SYuval Mintz /* Mark the fastpath as free/used */ 721fe56b9e6SYuval Mintz cdev->int_params.fp_initialized = cnt ? true : false; 722fe56b9e6SYuval Mintz 723fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX) 724fe56b9e6SYuval Mintz limit = cdev->num_hwfns * 63; 725fe56b9e6SYuval Mintz else if (cdev->int_params.fp_msix_cnt) 726fe56b9e6SYuval Mintz limit = cdev->int_params.fp_msix_cnt; 727fe56b9e6SYuval Mintz 728fe56b9e6SYuval Mintz if (!limit) 729fe56b9e6SYuval Mintz return -ENOMEM; 730fe56b9e6SYuval Mintz 731fe56b9e6SYuval Mintz return min_t(int, cnt, limit); 732fe56b9e6SYuval Mintz } 733fe56b9e6SYuval Mintz 734fe56b9e6SYuval Mintz static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info) 735fe56b9e6SYuval Mintz { 736fe56b9e6SYuval Mintz memset(info, 0, sizeof(struct qed_int_info)); 737fe56b9e6SYuval Mintz 738fe56b9e6SYuval Mintz if (!cdev->int_params.fp_initialized) { 739fe56b9e6SYuval Mintz DP_INFO(cdev, 740fe56b9e6SYuval Mintz "Protocol driver requested interrupt information, but its support is not yet configured\n"); 741fe56b9e6SYuval Mintz return -EINVAL; 742fe56b9e6SYuval Mintz } 743fe56b9e6SYuval Mintz 744fe56b9e6SYuval Mintz /* Need to expose only MSI-X information; Single IRQ is handled solely 745fe56b9e6SYuval Mintz * by qed. 746fe56b9e6SYuval Mintz */ 747fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 748fe56b9e6SYuval Mintz int msix_base = cdev->int_params.fp_msix_base; 749fe56b9e6SYuval Mintz 750fe56b9e6SYuval Mintz info->msix_cnt = cdev->int_params.fp_msix_cnt; 751fe56b9e6SYuval Mintz info->msix = &cdev->int_params.msix_table[msix_base]; 752fe56b9e6SYuval Mintz } 753fe56b9e6SYuval Mintz 754fe56b9e6SYuval Mintz return 0; 755fe56b9e6SYuval Mintz } 756fe56b9e6SYuval Mintz 757fe56b9e6SYuval Mintz static int qed_slowpath_setup_int(struct qed_dev *cdev, 758fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 759fe56b9e6SYuval Mintz { 7604ac801b7SYuval Mintz struct qed_sb_cnt_info sb_cnt_info; 7610189efb8SYuval Mintz int num_l2_queues = 0; 7624ac801b7SYuval Mintz int rc; 7634ac801b7SYuval Mintz int i; 764fe56b9e6SYuval Mintz 7651d2c2024SSudarsana Reddy Kalluru if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { 7661d2c2024SSudarsana Reddy Kalluru DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); 7671d2c2024SSudarsana Reddy Kalluru return -EINVAL; 7681d2c2024SSudarsana Reddy Kalluru } 7691d2c2024SSudarsana Reddy Kalluru 7701d2c2024SSudarsana Reddy Kalluru memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 771fe56b9e6SYuval Mintz cdev->int_params.in.int_mode = int_mode; 7724ac801b7SYuval Mintz for_each_hwfn(cdev, i) { 7734ac801b7SYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); 7744ac801b7SYuval Mintz qed_int_get_num_sbs(&cdev->hwfns[i], &sb_cnt_info); 775726fdbe9SMintz, Yuval cdev->int_params.in.num_vectors += sb_cnt_info.cnt; 7764ac801b7SYuval Mintz cdev->int_params.in.num_vectors++; /* slowpath */ 7774ac801b7SYuval Mintz } 778fe56b9e6SYuval Mintz 779fe56b9e6SYuval Mintz /* We want a minimum of one slowpath and one fastpath vector per hwfn */ 780fe56b9e6SYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; 781fe56b9e6SYuval Mintz 782fe56b9e6SYuval Mintz rc = qed_set_int_mode(cdev, false); 783fe56b9e6SYuval Mintz if (rc) { 784fe56b9e6SYuval Mintz DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); 785fe56b9e6SYuval Mintz return rc; 786fe56b9e6SYuval Mintz } 787fe56b9e6SYuval Mintz 788fe56b9e6SYuval Mintz cdev->int_params.fp_msix_base = cdev->num_hwfns; 789fe56b9e6SYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors - 790fe56b9e6SYuval Mintz cdev->num_hwfns; 791fe56b9e6SYuval Mintz 7922f782278SMintz, Yuval if (!IS_ENABLED(CONFIG_QED_RDMA) || 793c851a9dcSKalderon, Michal !QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) 7940189efb8SYuval Mintz return 0; 7950189efb8SYuval Mintz 79651ff1725SRam Amrani for_each_hwfn(cdev, i) 79751ff1725SRam Amrani num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE); 79851ff1725SRam Amrani 79951ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, 80051ff1725SRam Amrani "cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n", 80151ff1725SRam Amrani cdev->int_params.fp_msix_cnt, num_l2_queues); 80251ff1725SRam Amrani 80351ff1725SRam Amrani if (cdev->int_params.fp_msix_cnt > num_l2_queues) { 80451ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 80551ff1725SRam Amrani (cdev->int_params.fp_msix_cnt - num_l2_queues) 80651ff1725SRam Amrani / cdev->num_hwfns; 80751ff1725SRam Amrani cdev->int_params.rdma_msix_base = 80851ff1725SRam Amrani cdev->int_params.fp_msix_base + num_l2_queues; 80951ff1725SRam Amrani cdev->int_params.fp_msix_cnt = num_l2_queues; 81051ff1725SRam Amrani } else { 81151ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 0; 81251ff1725SRam Amrani } 81351ff1725SRam Amrani 81451ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n", 81551ff1725SRam Amrani cdev->int_params.rdma_msix_cnt, 81651ff1725SRam Amrani cdev->int_params.rdma_msix_base); 81751ff1725SRam Amrani 818fe56b9e6SYuval Mintz return 0; 819fe56b9e6SYuval Mintz } 820fe56b9e6SYuval Mintz 8211408cc1fSYuval Mintz static int qed_slowpath_vf_setup_int(struct qed_dev *cdev) 8221408cc1fSYuval Mintz { 8231408cc1fSYuval Mintz int rc; 8241408cc1fSYuval Mintz 8251408cc1fSYuval Mintz memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 8261408cc1fSYuval Mintz cdev->int_params.in.int_mode = QED_INT_MODE_MSIX; 8271408cc1fSYuval Mintz 8281408cc1fSYuval Mintz qed_vf_get_num_rxqs(QED_LEADING_HWFN(cdev), 8291408cc1fSYuval Mintz &cdev->int_params.in.num_vectors); 8301408cc1fSYuval Mintz if (cdev->num_hwfns > 1) { 8311408cc1fSYuval Mintz u8 vectors = 0; 8321408cc1fSYuval Mintz 8331408cc1fSYuval Mintz qed_vf_get_num_rxqs(&cdev->hwfns[1], &vectors); 8341408cc1fSYuval Mintz cdev->int_params.in.num_vectors += vectors; 8351408cc1fSYuval Mintz } 8361408cc1fSYuval Mintz 8371408cc1fSYuval Mintz /* We want a minimum of one fastpath vector per vf hwfn */ 8381408cc1fSYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns; 8391408cc1fSYuval Mintz 8401408cc1fSYuval Mintz rc = qed_set_int_mode(cdev, true); 8411408cc1fSYuval Mintz if (rc) 8421408cc1fSYuval Mintz return rc; 8431408cc1fSYuval Mintz 8441408cc1fSYuval Mintz cdev->int_params.fp_msix_base = 0; 8451408cc1fSYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors; 8461408cc1fSYuval Mintz 8471408cc1fSYuval Mintz return 0; 8481408cc1fSYuval Mintz } 8491408cc1fSYuval Mintz 850fe56b9e6SYuval Mintz u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, 851fe56b9e6SYuval Mintz u8 *input_buf, u32 max_size, u8 *unzip_buf) 852fe56b9e6SYuval Mintz { 853fe56b9e6SYuval Mintz int rc; 854fe56b9e6SYuval Mintz 855fe56b9e6SYuval Mintz p_hwfn->stream->next_in = input_buf; 856fe56b9e6SYuval Mintz p_hwfn->stream->avail_in = input_len; 857fe56b9e6SYuval Mintz p_hwfn->stream->next_out = unzip_buf; 858fe56b9e6SYuval Mintz p_hwfn->stream->avail_out = max_size; 859fe56b9e6SYuval Mintz 860fe56b9e6SYuval Mintz rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS); 861fe56b9e6SYuval Mintz 862fe56b9e6SYuval Mintz if (rc != Z_OK) { 863fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n", 864fe56b9e6SYuval Mintz rc); 865fe56b9e6SYuval Mintz return 0; 866fe56b9e6SYuval Mintz } 867fe56b9e6SYuval Mintz 868fe56b9e6SYuval Mintz rc = zlib_inflate(p_hwfn->stream, Z_FINISH); 869fe56b9e6SYuval Mintz zlib_inflateEnd(p_hwfn->stream); 870fe56b9e6SYuval Mintz 871fe56b9e6SYuval Mintz if (rc != Z_OK && rc != Z_STREAM_END) { 872fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n", 873fe56b9e6SYuval Mintz p_hwfn->stream->msg, rc); 874fe56b9e6SYuval Mintz return 0; 875fe56b9e6SYuval Mintz } 876fe56b9e6SYuval Mintz 877fe56b9e6SYuval Mintz return p_hwfn->stream->total_out / 4; 878fe56b9e6SYuval Mintz } 879fe56b9e6SYuval Mintz 880fe56b9e6SYuval Mintz static int qed_alloc_stream_mem(struct qed_dev *cdev) 881fe56b9e6SYuval Mintz { 882fe56b9e6SYuval Mintz int i; 883fe56b9e6SYuval Mintz void *workspace; 884fe56b9e6SYuval Mintz 885fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 886fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 887fe56b9e6SYuval Mintz 888fe56b9e6SYuval Mintz p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL); 889fe56b9e6SYuval Mintz if (!p_hwfn->stream) 890fe56b9e6SYuval Mintz return -ENOMEM; 891fe56b9e6SYuval Mintz 892fe56b9e6SYuval Mintz workspace = vzalloc(zlib_inflate_workspacesize()); 893fe56b9e6SYuval Mintz if (!workspace) 894fe56b9e6SYuval Mintz return -ENOMEM; 895fe56b9e6SYuval Mintz p_hwfn->stream->workspace = workspace; 896fe56b9e6SYuval Mintz } 897fe56b9e6SYuval Mintz 898fe56b9e6SYuval Mintz return 0; 899fe56b9e6SYuval Mintz } 900fe56b9e6SYuval Mintz 901fe56b9e6SYuval Mintz static void qed_free_stream_mem(struct qed_dev *cdev) 902fe56b9e6SYuval Mintz { 903fe56b9e6SYuval Mintz int i; 904fe56b9e6SYuval Mintz 905fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 906fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 907fe56b9e6SYuval Mintz 908fe56b9e6SYuval Mintz if (!p_hwfn->stream) 909fe56b9e6SYuval Mintz return; 910fe56b9e6SYuval Mintz 911fe56b9e6SYuval Mintz vfree(p_hwfn->stream->workspace); 912fe56b9e6SYuval Mintz kfree(p_hwfn->stream); 913fe56b9e6SYuval Mintz } 914fe56b9e6SYuval Mintz } 915fe56b9e6SYuval Mintz 916fe56b9e6SYuval Mintz static void qed_update_pf_params(struct qed_dev *cdev, 917fe56b9e6SYuval Mintz struct qed_pf_params *params) 918fe56b9e6SYuval Mintz { 919fe56b9e6SYuval Mintz int i; 920fe56b9e6SYuval Mintz 9215c5f2609SRam Amrani if (IS_ENABLED(CONFIG_QED_RDMA)) { 9220189efb8SYuval Mintz params->rdma_pf_params.num_qps = QED_ROCE_QPS; 9230189efb8SYuval Mintz params->rdma_pf_params.min_dpis = QED_ROCE_DPIS; 9240189efb8SYuval Mintz /* divide by 3 the MRs to avoid MF ILT overflow */ 9250189efb8SYuval Mintz params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX; 926fe56b9e6SYuval Mintz } 927fe56b9e6SYuval Mintz 928d51e4af5SChopra, Manish if (cdev->num_hwfns > 1 || IS_VF(cdev)) 929d51e4af5SChopra, Manish params->eth_pf_params.num_arfs_filters = 0; 930d51e4af5SChopra, Manish 931e1d32acbSMintz, Yuval /* In case we might support RDMA, don't allow qede to be greedy 932e1d32acbSMintz, Yuval * with the L2 contexts. Allow for 64 queues [rx, tx, xdp] per hwfn. 933e1d32acbSMintz, Yuval */ 934c851a9dcSKalderon, Michal if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) { 935e1d32acbSMintz, Yuval u16 *num_cons; 936e1d32acbSMintz, Yuval 937e1d32acbSMintz, Yuval num_cons = ¶ms->eth_pf_params.num_cons; 938e1d32acbSMintz, Yuval *num_cons = min_t(u16, *num_cons, 192); 939e1d32acbSMintz, Yuval } 940e1d32acbSMintz, Yuval 9415c5f2609SRam Amrani for (i = 0; i < cdev->num_hwfns; i++) { 9425c5f2609SRam Amrani struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 9435c5f2609SRam Amrani 9445c5f2609SRam Amrani p_hwfn->pf_params = *params; 9455c5f2609SRam Amrani } 9465c5f2609SRam Amrani } 9475c5f2609SRam Amrani 948fe56b9e6SYuval Mintz static int qed_slowpath_start(struct qed_dev *cdev, 949fe56b9e6SYuval Mintz struct qed_slowpath_params *params) 950fe56b9e6SYuval Mintz { 9515d24bcf1STomer Tayar struct qed_drv_load_params drv_load_params; 952c0c2d0b4SMintz, Yuval struct qed_hw_init_params hw_init_params; 953fe56b9e6SYuval Mintz struct qed_mcp_drv_version drv_version; 95419968430SChopra, Manish struct qed_tunnel_info tunn_info; 955fe56b9e6SYuval Mintz const u8 *data = NULL; 956fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 957c78c70faSSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 95837bff2b9SYuval Mintz int rc = -EINVAL; 95937bff2b9SYuval Mintz 96037bff2b9SYuval Mintz if (qed_iov_wq_start(cdev)) 96137bff2b9SYuval Mintz goto err; 962fe56b9e6SYuval Mintz 9631408cc1fSYuval Mintz if (IS_PF(cdev)) { 964fe56b9e6SYuval Mintz rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME, 965fe56b9e6SYuval Mintz &cdev->pdev->dev); 966fe56b9e6SYuval Mintz if (rc) { 967fe56b9e6SYuval Mintz DP_NOTICE(cdev, 968fe56b9e6SYuval Mintz "Failed to find fw file - /lib/firmware/%s\n", 969fe56b9e6SYuval Mintz QED_FW_FILE_NAME); 970fe56b9e6SYuval Mintz goto err; 971fe56b9e6SYuval Mintz } 972c78c70faSSudarsana Reddy Kalluru 973d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) { 974d51e4af5SChopra, Manish p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 975d51e4af5SChopra, Manish if (p_ptt) { 976d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt = p_ptt; 977d51e4af5SChopra, Manish } else { 978d51e4af5SChopra, Manish DP_NOTICE(cdev, 979d51e4af5SChopra, Manish "Failed to acquire PTT for aRFS\n"); 980d51e4af5SChopra, Manish goto err; 981d51e4af5SChopra, Manish } 982d51e4af5SChopra, Manish } 9831408cc1fSYuval Mintz } 984fe56b9e6SYuval Mintz 9850e191827SSudarsana Reddy Kalluru cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS; 986fe56b9e6SYuval Mintz rc = qed_nic_setup(cdev); 987fe56b9e6SYuval Mintz if (rc) 988fe56b9e6SYuval Mintz goto err; 989fe56b9e6SYuval Mintz 9901408cc1fSYuval Mintz if (IS_PF(cdev)) 991fe56b9e6SYuval Mintz rc = qed_slowpath_setup_int(cdev, params->int_mode); 9921408cc1fSYuval Mintz else 9931408cc1fSYuval Mintz rc = qed_slowpath_vf_setup_int(cdev); 994fe56b9e6SYuval Mintz if (rc) 995fe56b9e6SYuval Mintz goto err1; 996fe56b9e6SYuval Mintz 9971408cc1fSYuval Mintz if (IS_PF(cdev)) { 998fe56b9e6SYuval Mintz /* Allocate stream for unzipping */ 999fe56b9e6SYuval Mintz rc = qed_alloc_stream_mem(cdev); 10002591c280SJoe Perches if (rc) 10018f16bc97SSudarsana Kalluru goto err2; 1002fe56b9e6SYuval Mintz 10038ac1ed79SJoe Perches /* First Dword used to differentiate between various sources */ 1004351a4dedSYuval Mintz data = cdev->firmware->data + sizeof(u32); 1005c965db44STomer Tayar 1006c965db44STomer Tayar qed_dbg_pf_init(cdev); 10071408cc1fSYuval Mintz } 1008fe56b9e6SYuval Mintz 10091408cc1fSYuval Mintz /* Start the slowpath */ 1010c0c2d0b4SMintz, Yuval memset(&hw_init_params, 0, sizeof(hw_init_params)); 101119968430SChopra, Manish memset(&tunn_info, 0, sizeof(tunn_info)); 101219968430SChopra, Manish tunn_info.vxlan.b_mode_enabled = true; 101319968430SChopra, Manish tunn_info.l2_gre.b_mode_enabled = true; 101419968430SChopra, Manish tunn_info.ip_gre.b_mode_enabled = true; 101519968430SChopra, Manish tunn_info.l2_geneve.b_mode_enabled = true; 101619968430SChopra, Manish tunn_info.ip_geneve.b_mode_enabled = true; 101719968430SChopra, Manish tunn_info.vxlan.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101819968430SChopra, Manish tunn_info.l2_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101919968430SChopra, Manish tunn_info.ip_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 102019968430SChopra, Manish tunn_info.l2_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 102119968430SChopra, Manish tunn_info.ip_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 1022c0c2d0b4SMintz, Yuval hw_init_params.p_tunn = &tunn_info; 1023c0c2d0b4SMintz, Yuval hw_init_params.b_hw_start = true; 1024c0c2d0b4SMintz, Yuval hw_init_params.int_mode = cdev->int_params.out.int_mode; 1025c0c2d0b4SMintz, Yuval hw_init_params.allow_npar_tx_switch = true; 1026c0c2d0b4SMintz, Yuval hw_init_params.bin_fw_data = data; 1027c0c2d0b4SMintz, Yuval 10285d24bcf1STomer Tayar memset(&drv_load_params, 0, sizeof(drv_load_params)); 10295d24bcf1STomer Tayar drv_load_params.is_crash_kernel = is_kdump_kernel(); 10305d24bcf1STomer Tayar drv_load_params.mfw_timeout_val = QED_LOAD_REQ_LOCK_TO_DEFAULT; 10315d24bcf1STomer Tayar drv_load_params.avoid_eng_reset = false; 10325d24bcf1STomer Tayar drv_load_params.override_force_load = QED_OVERRIDE_FORCE_LOAD_NONE; 10335d24bcf1STomer Tayar hw_init_params.p_drv_load_params = &drv_load_params; 10345d24bcf1STomer Tayar 1035c0c2d0b4SMintz, Yuval rc = qed_hw_init(cdev, &hw_init_params); 1036fe56b9e6SYuval Mintz if (rc) 10378c925c44SYuval Mintz goto err2; 1038fe56b9e6SYuval Mintz 1039fe56b9e6SYuval Mintz DP_INFO(cdev, 1040fe56b9e6SYuval Mintz "HW initialization and function start completed successfully\n"); 1041fe56b9e6SYuval Mintz 1042eaf3c0c6SChopra, Manish if (IS_PF(cdev)) { 1043eaf3c0c6SChopra, Manish cdev->tunn_feature_mask = (BIT(QED_MODE_VXLAN_TUNN) | 1044eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GENEVE_TUNN) | 1045eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGENEVE_TUNN) | 1046eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GRE_TUNN) | 1047eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGRE_TUNN)); 1048eaf3c0c6SChopra, Manish } 1049eaf3c0c6SChopra, Manish 10500a7fb11cSYuval Mintz /* Allocate LL2 interface if needed */ 10510a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->using_ll2) { 10520a7fb11cSYuval Mintz rc = qed_ll2_alloc_if(cdev); 10530a7fb11cSYuval Mintz if (rc) 10540a7fb11cSYuval Mintz goto err3; 10550a7fb11cSYuval Mintz } 10561408cc1fSYuval Mintz if (IS_PF(cdev)) { 1057fe56b9e6SYuval Mintz hwfn = QED_LEADING_HWFN(cdev); 1058fe56b9e6SYuval Mintz drv_version.version = (params->drv_major << 24) | 1059fe56b9e6SYuval Mintz (params->drv_minor << 16) | 1060fe56b9e6SYuval Mintz (params->drv_rev << 8) | 1061fe56b9e6SYuval Mintz (params->drv_eng); 1062fe56b9e6SYuval Mintz strlcpy(drv_version.name, params->name, 1063fe56b9e6SYuval Mintz MCP_DRV_VER_STR_SIZE - 4); 1064fe56b9e6SYuval Mintz rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt, 1065fe56b9e6SYuval Mintz &drv_version); 1066fe56b9e6SYuval Mintz if (rc) { 1067fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed sending drv version command\n"); 1068fe56b9e6SYuval Mintz return rc; 1069fe56b9e6SYuval Mintz } 10701408cc1fSYuval Mintz } 1071fe56b9e6SYuval Mintz 10728c925c44SYuval Mintz qed_reset_vport_stats(cdev); 10738c925c44SYuval Mintz 1074fe56b9e6SYuval Mintz return 0; 1075fe56b9e6SYuval Mintz 10760a7fb11cSYuval Mintz err3: 10770a7fb11cSYuval Mintz qed_hw_stop(cdev); 1078fe56b9e6SYuval Mintz err2: 10798c925c44SYuval Mintz qed_hw_timers_stop_all(cdev); 10801408cc1fSYuval Mintz if (IS_PF(cdev)) 10818c925c44SYuval Mintz qed_slowpath_irq_free(cdev); 10828c925c44SYuval Mintz qed_free_stream_mem(cdev); 1083fe56b9e6SYuval Mintz qed_disable_msix(cdev); 1084fe56b9e6SYuval Mintz err1: 1085fe56b9e6SYuval Mintz qed_resc_free(cdev); 1086fe56b9e6SYuval Mintz err: 10871408cc1fSYuval Mintz if (IS_PF(cdev)) 1088fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1089fe56b9e6SYuval Mintz 1090d51e4af5SChopra, Manish if (IS_PF(cdev) && (cdev->num_hwfns == 1) && 1091d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt) 1092d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1093d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1094c78c70faSSudarsana Reddy Kalluru 109537bff2b9SYuval Mintz qed_iov_wq_stop(cdev, false); 109637bff2b9SYuval Mintz 1097fe56b9e6SYuval Mintz return rc; 1098fe56b9e6SYuval Mintz } 1099fe56b9e6SYuval Mintz 1100fe56b9e6SYuval Mintz static int qed_slowpath_stop(struct qed_dev *cdev) 1101fe56b9e6SYuval Mintz { 1102fe56b9e6SYuval Mintz if (!cdev) 1103fe56b9e6SYuval Mintz return -ENODEV; 1104fe56b9e6SYuval Mintz 11050a7fb11cSYuval Mintz qed_ll2_dealloc_if(cdev); 11060a7fb11cSYuval Mintz 11071408cc1fSYuval Mintz if (IS_PF(cdev)) { 1108d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) 1109d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1110d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1111fe56b9e6SYuval Mintz qed_free_stream_mem(cdev); 1112c5ac9319SYuval Mintz if (IS_QED_ETH_IF(cdev)) 11130b55e27dSYuval Mintz qed_sriov_disable(cdev, true); 11145f027d7aSMintz, Yuval } 1115fe56b9e6SYuval Mintz 1116fe56b9e6SYuval Mintz qed_nic_stop(cdev); 11175f027d7aSMintz, Yuval 11185f027d7aSMintz, Yuval if (IS_PF(cdev)) 1119fe56b9e6SYuval Mintz qed_slowpath_irq_free(cdev); 1120fe56b9e6SYuval Mintz 1121fe56b9e6SYuval Mintz qed_disable_msix(cdev); 11221226337aSTomer Tayar 11231226337aSTomer Tayar qed_resc_free(cdev); 1124fe56b9e6SYuval Mintz 112537bff2b9SYuval Mintz qed_iov_wq_stop(cdev, true); 112637bff2b9SYuval Mintz 11271408cc1fSYuval Mintz if (IS_PF(cdev)) 1128fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1129fe56b9e6SYuval Mintz 1130fe56b9e6SYuval Mintz return 0; 1131fe56b9e6SYuval Mintz } 1132fe56b9e6SYuval Mintz 1133712c3cbfSMintz, Yuval static void qed_set_name(struct qed_dev *cdev, char name[NAME_SIZE]) 1134fe56b9e6SYuval Mintz { 1135fe56b9e6SYuval Mintz int i; 1136fe56b9e6SYuval Mintz 1137fe56b9e6SYuval Mintz memcpy(cdev->name, name, NAME_SIZE); 1138fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) 1139fe56b9e6SYuval Mintz snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i); 1140fe56b9e6SYuval Mintz } 1141fe56b9e6SYuval Mintz 1142fe56b9e6SYuval Mintz static u32 qed_sb_init(struct qed_dev *cdev, 1143fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 1144fe56b9e6SYuval Mintz void *sb_virt_addr, 1145fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, u16 sb_id, 1146fe56b9e6SYuval Mintz enum qed_sb_type type) 1147fe56b9e6SYuval Mintz { 1148fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 114985750d74SMintz, Yuval struct qed_ptt *p_ptt; 1150fe56b9e6SYuval Mintz int hwfn_index; 1151fe56b9e6SYuval Mintz u16 rel_sb_id; 1152fe56b9e6SYuval Mintz u8 n_hwfns; 1153fe56b9e6SYuval Mintz u32 rc; 1154fe56b9e6SYuval Mintz 1155fe56b9e6SYuval Mintz /* RoCE uses single engine and CMT uses two engines. When using both 1156fe56b9e6SYuval Mintz * we force only a single engine. Storage uses only engine 0 too. 1157fe56b9e6SYuval Mintz */ 1158fe56b9e6SYuval Mintz if (type == QED_SB_TYPE_L2_QUEUE) 1159fe56b9e6SYuval Mintz n_hwfns = cdev->num_hwfns; 1160fe56b9e6SYuval Mintz else 1161fe56b9e6SYuval Mintz n_hwfns = 1; 1162fe56b9e6SYuval Mintz 1163fe56b9e6SYuval Mintz hwfn_index = sb_id % n_hwfns; 1164fe56b9e6SYuval Mintz p_hwfn = &cdev->hwfns[hwfn_index]; 1165fe56b9e6SYuval Mintz rel_sb_id = sb_id / n_hwfns; 1166fe56b9e6SYuval Mintz 1167fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1168fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 1169fe56b9e6SYuval Mintz hwfn_index, rel_sb_id, sb_id); 1170fe56b9e6SYuval Mintz 117185750d74SMintz, Yuval if (IS_PF(p_hwfn->cdev)) { 117285750d74SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 117385750d74SMintz, Yuval if (!p_ptt) 117485750d74SMintz, Yuval return -EBUSY; 117585750d74SMintz, Yuval 117685750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, p_ptt, sb_info, sb_virt_addr, 117785750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 117885750d74SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 117985750d74SMintz, Yuval } else { 118085750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, NULL, sb_info, sb_virt_addr, 118185750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 118285750d74SMintz, Yuval } 1183fe56b9e6SYuval Mintz 1184fe56b9e6SYuval Mintz return rc; 1185fe56b9e6SYuval Mintz } 1186fe56b9e6SYuval Mintz 1187fe56b9e6SYuval Mintz static u32 qed_sb_release(struct qed_dev *cdev, 11881a635e48SYuval Mintz struct qed_sb_info *sb_info, u16 sb_id) 1189fe56b9e6SYuval Mintz { 1190fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 1191fe56b9e6SYuval Mintz int hwfn_index; 1192fe56b9e6SYuval Mintz u16 rel_sb_id; 1193fe56b9e6SYuval Mintz u32 rc; 1194fe56b9e6SYuval Mintz 1195fe56b9e6SYuval Mintz hwfn_index = sb_id % cdev->num_hwfns; 1196fe56b9e6SYuval Mintz p_hwfn = &cdev->hwfns[hwfn_index]; 1197fe56b9e6SYuval Mintz rel_sb_id = sb_id / cdev->num_hwfns; 1198fe56b9e6SYuval Mintz 1199fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1200fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 1201fe56b9e6SYuval Mintz hwfn_index, rel_sb_id, sb_id); 1202fe56b9e6SYuval Mintz 1203fe56b9e6SYuval Mintz rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id); 1204fe56b9e6SYuval Mintz 1205fe56b9e6SYuval Mintz return rc; 1206fe56b9e6SYuval Mintz } 1207fe56b9e6SYuval Mintz 1208fe7cd2bfSYuval Mintz static bool qed_can_link_change(struct qed_dev *cdev) 1209fe7cd2bfSYuval Mintz { 1210fe7cd2bfSYuval Mintz return true; 1211fe7cd2bfSYuval Mintz } 1212fe7cd2bfSYuval Mintz 1213351a4dedSYuval Mintz static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params) 1214cc875c2eSYuval Mintz { 1215cc875c2eSYuval Mintz struct qed_hwfn *hwfn; 1216cc875c2eSYuval Mintz struct qed_mcp_link_params *link_params; 1217cc875c2eSYuval Mintz struct qed_ptt *ptt; 1218cc875c2eSYuval Mintz int rc; 1219cc875c2eSYuval Mintz 1220cc875c2eSYuval Mintz if (!cdev) 1221cc875c2eSYuval Mintz return -ENODEV; 1222cc875c2eSYuval Mintz 1223cc875c2eSYuval Mintz /* The link should be set only once per PF */ 1224cc875c2eSYuval Mintz hwfn = &cdev->hwfns[0]; 1225cc875c2eSYuval Mintz 122665ed2ffdSMintz, Yuval /* When VF wants to set link, force it to read the bulletin instead. 122765ed2ffdSMintz, Yuval * This mimics the PF behavior, where a noitification [both immediate 122865ed2ffdSMintz, Yuval * and possible later] would be generated when changing properties. 122965ed2ffdSMintz, Yuval */ 123065ed2ffdSMintz, Yuval if (IS_VF(cdev)) { 123165ed2ffdSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG); 123265ed2ffdSMintz, Yuval return 0; 123365ed2ffdSMintz, Yuval } 123465ed2ffdSMintz, Yuval 1235cc875c2eSYuval Mintz ptt = qed_ptt_acquire(hwfn); 1236cc875c2eSYuval Mintz if (!ptt) 1237cc875c2eSYuval Mintz return -EBUSY; 1238cc875c2eSYuval Mintz 1239cc875c2eSYuval Mintz link_params = qed_mcp_get_link_params(hwfn); 1240cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 1241cc875c2eSYuval Mintz link_params->speed.autoneg = params->autoneg; 1242cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 1243cc875c2eSYuval Mintz link_params->speed.advertised_speeds = 0; 1244054c67d1SSudarsana Reddy Kalluru if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) || 1245054c67d1SSudarsana Reddy Kalluru (params->adv_speeds & QED_LM_1000baseT_Full_BIT)) 1246cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1247cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G; 1248054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT) 1249cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1250cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G; 1251054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_25000baseKR_Full_BIT) 1252054c67d1SSudarsana Reddy Kalluru link_params->speed.advertised_speeds |= 1253054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G; 1254054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_40000baseLR4_Full_BIT) 1255cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1256cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G; 1257054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_50000baseKR2_Full_BIT) 1258cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1259cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G; 1260054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_100000baseKR4_Full_BIT) 1261cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1262351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G; 1263cc875c2eSYuval Mintz } 1264cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) 1265cc875c2eSYuval Mintz link_params->speed.forced_speed = params->forced_speed; 1266a43f235fSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) { 1267a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 1268a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = true; 1269a43f235fSSudarsana Reddy Kalluru else 1270a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = false; 1271a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE) 1272a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = true; 1273a43f235fSSudarsana Reddy Kalluru else 1274a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = false; 1275a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE) 1276a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = true; 1277a43f235fSSudarsana Reddy Kalluru else 1278a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = false; 1279a43f235fSSudarsana Reddy Kalluru } 128003dc76caSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) { 128103dc76caSSudarsana Reddy Kalluru switch (params->loopback_mode) { 128203dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_INT_PHY: 1283351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_INT_PHY; 128403dc76caSSudarsana Reddy Kalluru break; 128503dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT_PHY: 1286351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT_PHY; 128703dc76caSSudarsana Reddy Kalluru break; 128803dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT: 1289351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT; 129003dc76caSSudarsana Reddy Kalluru break; 129103dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_MAC: 1292351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_MAC; 129303dc76caSSudarsana Reddy Kalluru break; 129403dc76caSSudarsana Reddy Kalluru default: 1295351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_NONE; 129603dc76caSSudarsana Reddy Kalluru break; 129703dc76caSSudarsana Reddy Kalluru } 129803dc76caSSudarsana Reddy Kalluru } 1299cc875c2eSYuval Mintz 1300645874e5SSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG) 1301645874e5SSudarsana Reddy Kalluru memcpy(&link_params->eee, ¶ms->eee, 1302645874e5SSudarsana Reddy Kalluru sizeof(link_params->eee)); 1303645874e5SSudarsana Reddy Kalluru 1304cc875c2eSYuval Mintz rc = qed_mcp_set_link(hwfn, ptt, params->link_up); 1305cc875c2eSYuval Mintz 1306cc875c2eSYuval Mintz qed_ptt_release(hwfn, ptt); 1307cc875c2eSYuval Mintz 1308cc875c2eSYuval Mintz return rc; 1309cc875c2eSYuval Mintz } 1310cc875c2eSYuval Mintz 1311cc875c2eSYuval Mintz static int qed_get_port_type(u32 media_type) 1312cc875c2eSYuval Mintz { 1313cc875c2eSYuval Mintz int port_type; 1314cc875c2eSYuval Mintz 1315cc875c2eSYuval Mintz switch (media_type) { 1316cc875c2eSYuval Mintz case MEDIA_SFPP_10G_FIBER: 1317cc875c2eSYuval Mintz case MEDIA_SFP_1G_FIBER: 1318cc875c2eSYuval Mintz case MEDIA_XFP_FIBER: 1319b639f197SYuval Mintz case MEDIA_MODULE_FIBER: 1320cc875c2eSYuval Mintz case MEDIA_KR: 1321cc875c2eSYuval Mintz port_type = PORT_FIBRE; 1322cc875c2eSYuval Mintz break; 1323cc875c2eSYuval Mintz case MEDIA_DA_TWINAX: 1324cc875c2eSYuval Mintz port_type = PORT_DA; 1325cc875c2eSYuval Mintz break; 1326cc875c2eSYuval Mintz case MEDIA_BASE_T: 1327cc875c2eSYuval Mintz port_type = PORT_TP; 1328cc875c2eSYuval Mintz break; 1329cc875c2eSYuval Mintz case MEDIA_NOT_PRESENT: 1330cc875c2eSYuval Mintz port_type = PORT_NONE; 1331cc875c2eSYuval Mintz break; 1332cc875c2eSYuval Mintz case MEDIA_UNSPECIFIED: 1333cc875c2eSYuval Mintz default: 1334cc875c2eSYuval Mintz port_type = PORT_OTHER; 1335cc875c2eSYuval Mintz break; 1336cc875c2eSYuval Mintz } 1337cc875c2eSYuval Mintz return port_type; 1338cc875c2eSYuval Mintz } 1339cc875c2eSYuval Mintz 134014b84e86SArnd Bergmann static int qed_get_link_data(struct qed_hwfn *hwfn, 134114b84e86SArnd Bergmann struct qed_mcp_link_params *params, 134214b84e86SArnd Bergmann struct qed_mcp_link_state *link, 134314b84e86SArnd Bergmann struct qed_mcp_link_capabilities *link_caps) 134414b84e86SArnd Bergmann { 134514b84e86SArnd Bergmann void *p; 134614b84e86SArnd Bergmann 134714b84e86SArnd Bergmann if (!IS_PF(hwfn->cdev)) { 134814b84e86SArnd Bergmann qed_vf_get_link_params(hwfn, params); 134914b84e86SArnd Bergmann qed_vf_get_link_state(hwfn, link); 135014b84e86SArnd Bergmann qed_vf_get_link_caps(hwfn, link_caps); 135114b84e86SArnd Bergmann 135214b84e86SArnd Bergmann return 0; 135314b84e86SArnd Bergmann } 135414b84e86SArnd Bergmann 135514b84e86SArnd Bergmann p = qed_mcp_get_link_params(hwfn); 135614b84e86SArnd Bergmann if (!p) 135714b84e86SArnd Bergmann return -ENXIO; 135814b84e86SArnd Bergmann memcpy(params, p, sizeof(*params)); 135914b84e86SArnd Bergmann 136014b84e86SArnd Bergmann p = qed_mcp_get_link_state(hwfn); 136114b84e86SArnd Bergmann if (!p) 136214b84e86SArnd Bergmann return -ENXIO; 136314b84e86SArnd Bergmann memcpy(link, p, sizeof(*link)); 136414b84e86SArnd Bergmann 136514b84e86SArnd Bergmann p = qed_mcp_get_link_capabilities(hwfn); 136614b84e86SArnd Bergmann if (!p) 136714b84e86SArnd Bergmann return -ENXIO; 136814b84e86SArnd Bergmann memcpy(link_caps, p, sizeof(*link_caps)); 136914b84e86SArnd Bergmann 137014b84e86SArnd Bergmann return 0; 137114b84e86SArnd Bergmann } 137214b84e86SArnd Bergmann 1373cc875c2eSYuval Mintz static void qed_fill_link(struct qed_hwfn *hwfn, 1374cc875c2eSYuval Mintz struct qed_link_output *if_link) 1375cc875c2eSYuval Mintz { 1376cc875c2eSYuval Mintz struct qed_mcp_link_params params; 1377cc875c2eSYuval Mintz struct qed_mcp_link_state link; 1378cc875c2eSYuval Mintz struct qed_mcp_link_capabilities link_caps; 1379cc875c2eSYuval Mintz u32 media_type; 1380cc875c2eSYuval Mintz 1381cc875c2eSYuval Mintz memset(if_link, 0, sizeof(*if_link)); 1382cc875c2eSYuval Mintz 1383cc875c2eSYuval Mintz /* Prepare source inputs */ 138414b84e86SArnd Bergmann if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) { 138514b84e86SArnd Bergmann dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n"); 138614b84e86SArnd Bergmann return; 13871408cc1fSYuval Mintz } 1388cc875c2eSYuval Mintz 1389cc875c2eSYuval Mintz /* Set the link parameters to pass to protocol driver */ 1390cc875c2eSYuval Mintz if (link.link_up) 1391cc875c2eSYuval Mintz if_link->link_up = true; 1392cc875c2eSYuval Mintz 1393cc875c2eSYuval Mintz /* TODO - at the moment assume supported and advertised speed equal */ 1394054c67d1SSudarsana Reddy Kalluru if_link->supported_caps = QED_LM_FIBRE_BIT; 139534f9199cSsudarsana.kalluru@cavium.com if (link_caps.default_speed_autoneg) 1396054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Autoneg_BIT; 1397cc875c2eSYuval Mintz if (params.pause.autoneg || 1398cc875c2eSYuval Mintz (params.pause.forced_rx && params.pause.forced_tx)) 1399054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Asym_Pause_BIT; 1400cc875c2eSYuval Mintz if (params.pause.autoneg || params.pause.forced_rx || 1401cc875c2eSYuval Mintz params.pause.forced_tx) 1402054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Pause_BIT; 1403cc875c2eSYuval Mintz 1404cc875c2eSYuval Mintz if_link->advertised_caps = if_link->supported_caps; 140534f9199cSsudarsana.kalluru@cavium.com if (params.speed.autoneg) 140634f9199cSsudarsana.kalluru@cavium.com if_link->advertised_caps |= QED_LM_Autoneg_BIT; 140734f9199cSsudarsana.kalluru@cavium.com else 140834f9199cSsudarsana.kalluru@cavium.com if_link->advertised_caps &= ~QED_LM_Autoneg_BIT; 1409cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1410cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1411054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT | 1412054c67d1SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT; 1413cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1414cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 1415054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT; 1416054c67d1SSudarsana Reddy Kalluru if (params.speed.advertised_speeds & 1417054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 1418054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT; 1419cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1420cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 1421054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT; 1422cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1423cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 1424054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT; 1425cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1426351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 1427054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT; 1428cc875c2eSYuval Mintz 1429cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1430cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1431054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_1000baseT_Half_BIT | 1432054c67d1SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT; 1433cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1434cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 1435054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT; 1436054c67d1SSudarsana Reddy Kalluru if (link_caps.speed_capabilities & 1437054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 1438054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT; 1439cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1440cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 1441054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT; 1442cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1443cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 1444054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT; 1445cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1446351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 1447054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT; 1448cc875c2eSYuval Mintz 1449cc875c2eSYuval Mintz if (link.link_up) 1450cc875c2eSYuval Mintz if_link->speed = link.speed; 1451cc875c2eSYuval Mintz 1452cc875c2eSYuval Mintz /* TODO - fill duplex properly */ 1453cc875c2eSYuval Mintz if_link->duplex = DUPLEX_FULL; 1454cc875c2eSYuval Mintz qed_mcp_get_media_type(hwfn->cdev, &media_type); 1455cc875c2eSYuval Mintz if_link->port = qed_get_port_type(media_type); 1456cc875c2eSYuval Mintz 1457cc875c2eSYuval Mintz if_link->autoneg = params.speed.autoneg; 1458cc875c2eSYuval Mintz 1459cc875c2eSYuval Mintz if (params.pause.autoneg) 1460cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 1461cc875c2eSYuval Mintz if (params.pause.forced_rx) 1462cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE; 1463cc875c2eSYuval Mintz if (params.pause.forced_tx) 1464cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE; 1465cc875c2eSYuval Mintz 1466cc875c2eSYuval Mintz /* Link partner capabilities */ 1467054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD) 1468054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_1000baseT_Half_BIT; 1469054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD) 1470054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_1000baseT_Full_BIT; 1471054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G) 1472054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT; 1473054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_25G) 1474054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_25000baseKR_Full_BIT; 1475054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_40G) 1476054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_40000baseLR4_Full_BIT; 1477054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_50G) 1478054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_50000baseKR2_Full_BIT; 1479054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_100G) 1480054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_100000baseKR4_Full_BIT; 1481cc875c2eSYuval Mintz 1482cc875c2eSYuval Mintz if (link.an_complete) 1483054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Autoneg_BIT; 1484cc875c2eSYuval Mintz 1485cc875c2eSYuval Mintz if (link.partner_adv_pause) 1486054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Pause_BIT; 1487cc875c2eSYuval Mintz if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE || 1488cc875c2eSYuval Mintz link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE) 1489054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Asym_Pause_BIT; 1490645874e5SSudarsana Reddy Kalluru 1491645874e5SSudarsana Reddy Kalluru if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) { 1492645874e5SSudarsana Reddy Kalluru if_link->eee_supported = false; 1493645874e5SSudarsana Reddy Kalluru } else { 1494645874e5SSudarsana Reddy Kalluru if_link->eee_supported = true; 1495645874e5SSudarsana Reddy Kalluru if_link->eee_active = link.eee_active; 1496645874e5SSudarsana Reddy Kalluru if_link->sup_caps = link_caps.eee_speed_caps; 1497645874e5SSudarsana Reddy Kalluru /* MFW clears adv_caps on eee disable; use configured value */ 1498645874e5SSudarsana Reddy Kalluru if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps : 1499645874e5SSudarsana Reddy Kalluru params.eee.adv_caps; 1500645874e5SSudarsana Reddy Kalluru if_link->eee.lp_adv_caps = link.eee_lp_adv_caps; 1501645874e5SSudarsana Reddy Kalluru if_link->eee.enable = params.eee.enable; 1502645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable; 1503645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer; 1504645874e5SSudarsana Reddy Kalluru } 1505cc875c2eSYuval Mintz } 1506cc875c2eSYuval Mintz 1507cc875c2eSYuval Mintz static void qed_get_current_link(struct qed_dev *cdev, 1508cc875c2eSYuval Mintz struct qed_link_output *if_link) 1509cc875c2eSYuval Mintz { 151036558c3dSYuval Mintz int i; 151136558c3dSYuval Mintz 1512cc875c2eSYuval Mintz qed_fill_link(&cdev->hwfns[0], if_link); 151336558c3dSYuval Mintz 151436558c3dSYuval Mintz for_each_hwfn(cdev, i) 151536558c3dSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 1516cc875c2eSYuval Mintz } 1517cc875c2eSYuval Mintz 1518cc875c2eSYuval Mintz void qed_link_update(struct qed_hwfn *hwfn) 1519cc875c2eSYuval Mintz { 1520cc875c2eSYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 1521cc875c2eSYuval Mintz struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 1522cc875c2eSYuval Mintz struct qed_link_output if_link; 1523cc875c2eSYuval Mintz 1524cc875c2eSYuval Mintz qed_fill_link(hwfn, &if_link); 152536558c3dSYuval Mintz qed_inform_vf_link_state(hwfn); 1526cc875c2eSYuval Mintz 1527cc875c2eSYuval Mintz if (IS_LEAD_HWFN(hwfn) && cookie) 1528cc875c2eSYuval Mintz op->link_update(cookie, &if_link); 1529cc875c2eSYuval Mintz } 1530cc875c2eSYuval Mintz 1531fe56b9e6SYuval Mintz static int qed_drain(struct qed_dev *cdev) 1532fe56b9e6SYuval Mintz { 1533fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 1534fe56b9e6SYuval Mintz struct qed_ptt *ptt; 1535fe56b9e6SYuval Mintz int i, rc; 1536fe56b9e6SYuval Mintz 15371408cc1fSYuval Mintz if (IS_VF(cdev)) 15381408cc1fSYuval Mintz return 0; 15391408cc1fSYuval Mintz 1540fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1541fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 1542fe56b9e6SYuval Mintz ptt = qed_ptt_acquire(hwfn); 1543fe56b9e6SYuval Mintz if (!ptt) { 1544fe56b9e6SYuval Mintz DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n"); 1545fe56b9e6SYuval Mintz return -EBUSY; 1546fe56b9e6SYuval Mintz } 1547fe56b9e6SYuval Mintz rc = qed_mcp_drain(hwfn, ptt); 1548fe56b9e6SYuval Mintz if (rc) 1549fe56b9e6SYuval Mintz return rc; 1550fe56b9e6SYuval Mintz qed_ptt_release(hwfn, ptt); 1551fe56b9e6SYuval Mintz } 1552fe56b9e6SYuval Mintz 1553fe56b9e6SYuval Mintz return 0; 1554fe56b9e6SYuval Mintz } 1555fe56b9e6SYuval Mintz 155620675b37SMintz, Yuval static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type, 155720675b37SMintz, Yuval u8 *buf, u16 len) 155820675b37SMintz, Yuval { 155920675b37SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 156020675b37SMintz, Yuval struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 156120675b37SMintz, Yuval int rc; 156220675b37SMintz, Yuval 156320675b37SMintz, Yuval if (!ptt) 156420675b37SMintz, Yuval return -EAGAIN; 156520675b37SMintz, Yuval 156620675b37SMintz, Yuval rc = qed_mcp_get_nvm_image(hwfn, ptt, type, buf, len); 156720675b37SMintz, Yuval qed_ptt_release(hwfn, ptt); 156820675b37SMintz, Yuval return rc; 156920675b37SMintz, Yuval } 157020675b37SMintz, Yuval 1571722003acSSudarsana Reddy Kalluru static void qed_get_coalesce(struct qed_dev *cdev, u16 *rx_coal, u16 *tx_coal) 1572722003acSSudarsana Reddy Kalluru { 1573722003acSSudarsana Reddy Kalluru *rx_coal = cdev->rx_coalesce_usecs; 1574722003acSSudarsana Reddy Kalluru *tx_coal = cdev->tx_coalesce_usecs; 1575722003acSSudarsana Reddy Kalluru } 1576722003acSSudarsana Reddy Kalluru 1577722003acSSudarsana Reddy Kalluru static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, 1578477f2d14SRahul Verma void *handle) 1579722003acSSudarsana Reddy Kalluru { 1580477f2d14SRahul Verma return qed_set_queue_coalesce(rx_coal, tx_coal, handle); 1581722003acSSudarsana Reddy Kalluru } 1582722003acSSudarsana Reddy Kalluru 158391420b83SSudarsana Kalluru static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) 158491420b83SSudarsana Kalluru { 158591420b83SSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 158691420b83SSudarsana Kalluru struct qed_ptt *ptt; 158791420b83SSudarsana Kalluru int status = 0; 158891420b83SSudarsana Kalluru 158991420b83SSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 159091420b83SSudarsana Kalluru if (!ptt) 159191420b83SSudarsana Kalluru return -EAGAIN; 159291420b83SSudarsana Kalluru 159391420b83SSudarsana Kalluru status = qed_mcp_set_led(hwfn, ptt, mode); 159491420b83SSudarsana Kalluru 159591420b83SSudarsana Kalluru qed_ptt_release(hwfn, ptt); 159691420b83SSudarsana Kalluru 159791420b83SSudarsana Kalluru return status; 159891420b83SSudarsana Kalluru } 159991420b83SSudarsana Kalluru 160014d39648SMintz, Yuval static int qed_update_wol(struct qed_dev *cdev, bool enabled) 160114d39648SMintz, Yuval { 160214d39648SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 160314d39648SMintz, Yuval struct qed_ptt *ptt; 160414d39648SMintz, Yuval int rc = 0; 160514d39648SMintz, Yuval 160614d39648SMintz, Yuval if (IS_VF(cdev)) 160714d39648SMintz, Yuval return 0; 160814d39648SMintz, Yuval 160914d39648SMintz, Yuval ptt = qed_ptt_acquire(hwfn); 161014d39648SMintz, Yuval if (!ptt) 161114d39648SMintz, Yuval return -EAGAIN; 161214d39648SMintz, Yuval 161314d39648SMintz, Yuval rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED 161414d39648SMintz, Yuval : QED_OV_WOL_DISABLED); 161514d39648SMintz, Yuval if (rc) 161614d39648SMintz, Yuval goto out; 161714d39648SMintz, Yuval rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 161814d39648SMintz, Yuval 161914d39648SMintz, Yuval out: 162014d39648SMintz, Yuval qed_ptt_release(hwfn, ptt); 162114d39648SMintz, Yuval return rc; 162214d39648SMintz, Yuval } 162314d39648SMintz, Yuval 16240fefbfbaSSudarsana Kalluru static int qed_update_drv_state(struct qed_dev *cdev, bool active) 16250fefbfbaSSudarsana Kalluru { 16260fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 16270fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 16280fefbfbaSSudarsana Kalluru int status = 0; 16290fefbfbaSSudarsana Kalluru 16300fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 16310fefbfbaSSudarsana Kalluru return 0; 16320fefbfbaSSudarsana Kalluru 16330fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 16340fefbfbaSSudarsana Kalluru if (!ptt) 16350fefbfbaSSudarsana Kalluru return -EAGAIN; 16360fefbfbaSSudarsana Kalluru 16370fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ? 16380fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_ACTIVE : 16390fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_DISABLED); 16400fefbfbaSSudarsana Kalluru 16410fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 16420fefbfbaSSudarsana Kalluru 16430fefbfbaSSudarsana Kalluru return status; 16440fefbfbaSSudarsana Kalluru } 16450fefbfbaSSudarsana Kalluru 16460fefbfbaSSudarsana Kalluru static int qed_update_mac(struct qed_dev *cdev, u8 *mac) 16470fefbfbaSSudarsana Kalluru { 16480fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 16490fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 16500fefbfbaSSudarsana Kalluru int status = 0; 16510fefbfbaSSudarsana Kalluru 16520fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 16530fefbfbaSSudarsana Kalluru return 0; 16540fefbfbaSSudarsana Kalluru 16550fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 16560fefbfbaSSudarsana Kalluru if (!ptt) 16570fefbfbaSSudarsana Kalluru return -EAGAIN; 16580fefbfbaSSudarsana Kalluru 16590fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mac(hwfn, ptt, mac); 16600fefbfbaSSudarsana Kalluru if (status) 16610fefbfbaSSudarsana Kalluru goto out; 16620fefbfbaSSudarsana Kalluru 16630fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 16640fefbfbaSSudarsana Kalluru 16650fefbfbaSSudarsana Kalluru out: 16660fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 16670fefbfbaSSudarsana Kalluru return status; 16680fefbfbaSSudarsana Kalluru } 16690fefbfbaSSudarsana Kalluru 16700fefbfbaSSudarsana Kalluru static int qed_update_mtu(struct qed_dev *cdev, u16 mtu) 16710fefbfbaSSudarsana Kalluru { 16720fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 16730fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 16740fefbfbaSSudarsana Kalluru int status = 0; 16750fefbfbaSSudarsana Kalluru 16760fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 16770fefbfbaSSudarsana Kalluru return 0; 16780fefbfbaSSudarsana Kalluru 16790fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 16800fefbfbaSSudarsana Kalluru if (!ptt) 16810fefbfbaSSudarsana Kalluru return -EAGAIN; 16820fefbfbaSSudarsana Kalluru 16830fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu); 16840fefbfbaSSudarsana Kalluru if (status) 16850fefbfbaSSudarsana Kalluru goto out; 16860fefbfbaSSudarsana Kalluru 16870fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 16880fefbfbaSSudarsana Kalluru 16890fefbfbaSSudarsana Kalluru out: 16900fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 16910fefbfbaSSudarsana Kalluru return status; 16920fefbfbaSSudarsana Kalluru } 16930fefbfbaSSudarsana Kalluru 16948c93beafSYuval Mintz static struct qed_selftest_ops qed_selftest_ops_pass = { 169503dc76caSSudarsana Reddy Kalluru .selftest_memory = &qed_selftest_memory, 169603dc76caSSudarsana Reddy Kalluru .selftest_interrupt = &qed_selftest_interrupt, 169703dc76caSSudarsana Reddy Kalluru .selftest_register = &qed_selftest_register, 169803dc76caSSudarsana Reddy Kalluru .selftest_clock = &qed_selftest_clock, 16997a4b21b7SMintz, Yuval .selftest_nvram = &qed_selftest_nvram, 170003dc76caSSudarsana Reddy Kalluru }; 170103dc76caSSudarsana Reddy Kalluru 1702fe56b9e6SYuval Mintz const struct qed_common_ops qed_common_ops_pass = { 170303dc76caSSudarsana Reddy Kalluru .selftest = &qed_selftest_ops_pass, 1704fe56b9e6SYuval Mintz .probe = &qed_probe, 1705fe56b9e6SYuval Mintz .remove = &qed_remove, 1706fe56b9e6SYuval Mintz .set_power_state = &qed_set_power_state, 1707712c3cbfSMintz, Yuval .set_name = &qed_set_name, 1708fe56b9e6SYuval Mintz .update_pf_params = &qed_update_pf_params, 1709fe56b9e6SYuval Mintz .slowpath_start = &qed_slowpath_start, 1710fe56b9e6SYuval Mintz .slowpath_stop = &qed_slowpath_stop, 1711fe56b9e6SYuval Mintz .set_fp_int = &qed_set_int_fp, 1712fe56b9e6SYuval Mintz .get_fp_int = &qed_get_int_fp, 1713fe56b9e6SYuval Mintz .sb_init = &qed_sb_init, 1714fe56b9e6SYuval Mintz .sb_release = &qed_sb_release, 1715fe56b9e6SYuval Mintz .simd_handler_config = &qed_simd_handler_config, 1716fe56b9e6SYuval Mintz .simd_handler_clean = &qed_simd_handler_clean, 17171e128c81SArun Easi .dbg_grc = &qed_dbg_grc, 17181e128c81SArun Easi .dbg_grc_size = &qed_dbg_grc_size, 1719fe7cd2bfSYuval Mintz .can_link_change = &qed_can_link_change, 1720cc875c2eSYuval Mintz .set_link = &qed_set_link, 1721cc875c2eSYuval Mintz .get_link = &qed_get_current_link, 1722fe56b9e6SYuval Mintz .drain = &qed_drain, 1723fe56b9e6SYuval Mintz .update_msglvl = &qed_init_dp, 1724e0971c83STomer Tayar .dbg_all_data = &qed_dbg_all_data, 1725e0971c83STomer Tayar .dbg_all_data_size = &qed_dbg_all_data_size, 1726fe56b9e6SYuval Mintz .chain_alloc = &qed_chain_alloc, 1727fe56b9e6SYuval Mintz .chain_free = &qed_chain_free, 172820675b37SMintz, Yuval .nvm_get_image = &qed_nvm_get_image, 1729722003acSSudarsana Reddy Kalluru .get_coalesce = &qed_get_coalesce, 1730722003acSSudarsana Reddy Kalluru .set_coalesce = &qed_set_coalesce, 173191420b83SSudarsana Kalluru .set_led = &qed_set_led, 17320fefbfbaSSudarsana Kalluru .update_drv_state = &qed_update_drv_state, 17330fefbfbaSSudarsana Kalluru .update_mac = &qed_update_mac, 17340fefbfbaSSudarsana Kalluru .update_mtu = &qed_update_mtu, 173514d39648SMintz, Yuval .update_wol = &qed_update_wol, 1736fe56b9e6SYuval Mintz }; 17376c754246SSudarsana Reddy Kalluru 17386c754246SSudarsana Reddy Kalluru void qed_get_protocol_stats(struct qed_dev *cdev, 17396c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type type, 17406c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats *stats) 17416c754246SSudarsana Reddy Kalluru { 17426c754246SSudarsana Reddy Kalluru struct qed_eth_stats eth_stats; 17436c754246SSudarsana Reddy Kalluru 17446c754246SSudarsana Reddy Kalluru memset(stats, 0, sizeof(*stats)); 17456c754246SSudarsana Reddy Kalluru 17466c754246SSudarsana Reddy Kalluru switch (type) { 17476c754246SSudarsana Reddy Kalluru case QED_MCP_LAN_STATS: 17486c754246SSudarsana Reddy Kalluru qed_get_vport_stats(cdev, ð_stats); 17499c79ddaaSMintz, Yuval stats->lan_stats.ucast_rx_pkts = 17509c79ddaaSMintz, Yuval eth_stats.common.rx_ucast_pkts; 17519c79ddaaSMintz, Yuval stats->lan_stats.ucast_tx_pkts = 17529c79ddaaSMintz, Yuval eth_stats.common.tx_ucast_pkts; 17536c754246SSudarsana Reddy Kalluru stats->lan_stats.fcs_err = -1; 17546c754246SSudarsana Reddy Kalluru break; 17551e128c81SArun Easi case QED_MCP_FCOE_STATS: 17561e128c81SArun Easi qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats); 17571e128c81SArun Easi break; 17582f2b2614SMintz, Yuval case QED_MCP_ISCSI_STATS: 17592f2b2614SMintz, Yuval qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); 17602f2b2614SMintz, Yuval break; 17616c754246SSudarsana Reddy Kalluru default: 1762512c7840SMintz, Yuval DP_VERBOSE(cdev, QED_MSG_SP, 1763512c7840SMintz, Yuval "Invalid protocol type = %d\n", type); 17646c754246SSudarsana Reddy Kalluru return; 17656c754246SSudarsana Reddy Kalluru } 17666c754246SSudarsana Reddy Kalluru } 1767