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> 483a69cae8SSudarsana Reddy Kalluru #include <linux/crc32.h> 49fe56b9e6SYuval Mintz #include <linux/qed/qed_if.h> 500a7fb11cSYuval Mintz #include <linux/qed/qed_ll2_if.h> 51fe56b9e6SYuval Mintz 52fe56b9e6SYuval Mintz #include "qed.h" 5337bff2b9SYuval Mintz #include "qed_sriov.h" 54fe56b9e6SYuval Mintz #include "qed_sp.h" 55fe56b9e6SYuval Mintz #include "qed_dev_api.h" 560a7fb11cSYuval Mintz #include "qed_ll2.h" 571e128c81SArun Easi #include "qed_fcoe.h" 582f2b2614SMintz, Yuval #include "qed_iscsi.h" 592f2b2614SMintz, Yuval 60fe56b9e6SYuval Mintz #include "qed_mcp.h" 61fe56b9e6SYuval Mintz #include "qed_hw.h" 6203dc76caSSudarsana Reddy Kalluru #include "qed_selftest.h" 631e128c81SArun Easi #include "qed_debug.h" 64fe56b9e6SYuval Mintz 6551ff1725SRam Amrani #define QED_ROCE_QPS (8192) 6651ff1725SRam Amrani #define QED_ROCE_DPIS (8) 6751ff1725SRam Amrani 685abd7e92SYuval Mintz static char version[] = 695abd7e92SYuval Mintz "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n"; 70fe56b9e6SYuval Mintz 715abd7e92SYuval Mintz MODULE_DESCRIPTION("QLogic FastLinQ 4xxxx Core Module"); 72fe56b9e6SYuval Mintz MODULE_LICENSE("GPL"); 73fe56b9e6SYuval Mintz MODULE_VERSION(DRV_MODULE_VERSION); 74fe56b9e6SYuval Mintz 75fe56b9e6SYuval Mintz #define FW_FILE_VERSION \ 76fe56b9e6SYuval Mintz __stringify(FW_MAJOR_VERSION) "." \ 77fe56b9e6SYuval Mintz __stringify(FW_MINOR_VERSION) "." \ 78fe56b9e6SYuval Mintz __stringify(FW_REVISION_VERSION) "." \ 79fe56b9e6SYuval Mintz __stringify(FW_ENGINEERING_VERSION) 80fe56b9e6SYuval Mintz 81fe56b9e6SYuval Mintz #define QED_FW_FILE_NAME \ 82fe56b9e6SYuval Mintz "qed/qed_init_values_zipped-" FW_FILE_VERSION ".bin" 83fe56b9e6SYuval Mintz 84d43d3f0fSYuval Mintz MODULE_FIRMWARE(QED_FW_FILE_NAME); 85d43d3f0fSYuval Mintz 86fe56b9e6SYuval Mintz static int __init qed_init(void) 87fe56b9e6SYuval Mintz { 88fe56b9e6SYuval Mintz pr_info("%s", version); 89fe56b9e6SYuval Mintz 90fe56b9e6SYuval Mintz return 0; 91fe56b9e6SYuval Mintz } 92fe56b9e6SYuval Mintz 93fe56b9e6SYuval Mintz static void __exit qed_cleanup(void) 94fe56b9e6SYuval Mintz { 95fe56b9e6SYuval Mintz pr_notice("qed_cleanup called\n"); 96fe56b9e6SYuval Mintz } 97fe56b9e6SYuval Mintz 98fe56b9e6SYuval Mintz module_init(qed_init); 99fe56b9e6SYuval Mintz module_exit(qed_cleanup); 100fe56b9e6SYuval Mintz 101fe56b9e6SYuval Mintz /* Check if the DMA controller on the machine can properly handle the DMA 102fe56b9e6SYuval Mintz * addressing required by the device. 103fe56b9e6SYuval Mintz */ 104fe56b9e6SYuval Mintz static int qed_set_coherency_mask(struct qed_dev *cdev) 105fe56b9e6SYuval Mintz { 106fe56b9e6SYuval Mintz struct device *dev = &cdev->pdev->dev; 107fe56b9e6SYuval Mintz 108fe56b9e6SYuval Mintz if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) { 109fe56b9e6SYuval Mintz if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) { 110fe56b9e6SYuval Mintz DP_NOTICE(cdev, 111fe56b9e6SYuval Mintz "Can't request 64-bit consistent allocations\n"); 112fe56b9e6SYuval Mintz return -EIO; 113fe56b9e6SYuval Mintz } 114fe56b9e6SYuval Mintz } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) { 115fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Can't request 64b/32b DMA addresses\n"); 116fe56b9e6SYuval Mintz return -EIO; 117fe56b9e6SYuval Mintz } 118fe56b9e6SYuval Mintz 119fe56b9e6SYuval Mintz return 0; 120fe56b9e6SYuval Mintz } 121fe56b9e6SYuval Mintz 122fe56b9e6SYuval Mintz static void qed_free_pci(struct qed_dev *cdev) 123fe56b9e6SYuval Mintz { 124fe56b9e6SYuval Mintz struct pci_dev *pdev = cdev->pdev; 125fe56b9e6SYuval Mintz 1261a850bfcSMintz, Yuval if (cdev->doorbells && cdev->db_size) 127fe56b9e6SYuval Mintz iounmap(cdev->doorbells); 128fe56b9e6SYuval Mintz if (cdev->regview) 129fe56b9e6SYuval Mintz iounmap(cdev->regview); 130fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) 131fe56b9e6SYuval Mintz pci_release_regions(pdev); 132fe56b9e6SYuval Mintz 133fe56b9e6SYuval Mintz pci_disable_device(pdev); 134fe56b9e6SYuval Mintz } 135fe56b9e6SYuval Mintz 1360dfaba6dSYuval Mintz #define PCI_REVISION_ID_ERROR_VAL 0xff 1370dfaba6dSYuval Mintz 138fe56b9e6SYuval Mintz /* Performs PCI initializations as well as initializing PCI-related parameters 139fe56b9e6SYuval Mintz * in the device structrue. Returns 0 in case of success. 140fe56b9e6SYuval Mintz */ 1411a635e48SYuval Mintz static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev) 142fe56b9e6SYuval Mintz { 1430dfaba6dSYuval Mintz u8 rev_id; 144fe56b9e6SYuval Mintz int rc; 145fe56b9e6SYuval Mintz 146fe56b9e6SYuval Mintz cdev->pdev = pdev; 147fe56b9e6SYuval Mintz 148fe56b9e6SYuval Mintz rc = pci_enable_device(pdev); 149fe56b9e6SYuval Mintz if (rc) { 150fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot enable PCI device\n"); 151fe56b9e6SYuval Mintz goto err0; 152fe56b9e6SYuval Mintz } 153fe56b9e6SYuval Mintz 154fe56b9e6SYuval Mintz if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 155fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #0\n"); 156fe56b9e6SYuval Mintz rc = -EIO; 157fe56b9e6SYuval Mintz goto err1; 158fe56b9e6SYuval Mintz } 159fe56b9e6SYuval Mintz 1601408cc1fSYuval Mintz if (IS_PF(cdev) && !(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { 161fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #2\n"); 162fe56b9e6SYuval Mintz rc = -EIO; 163fe56b9e6SYuval Mintz goto err1; 164fe56b9e6SYuval Mintz } 165fe56b9e6SYuval Mintz 166fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) { 167fe56b9e6SYuval Mintz rc = pci_request_regions(pdev, "qed"); 168fe56b9e6SYuval Mintz if (rc) { 169fe56b9e6SYuval Mintz DP_NOTICE(cdev, 170fe56b9e6SYuval Mintz "Failed to request PCI memory resources\n"); 171fe56b9e6SYuval Mintz goto err1; 172fe56b9e6SYuval Mintz } 173fe56b9e6SYuval Mintz pci_set_master(pdev); 174fe56b9e6SYuval Mintz pci_save_state(pdev); 175fe56b9e6SYuval Mintz } 176fe56b9e6SYuval Mintz 1770dfaba6dSYuval Mintz pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); 1780dfaba6dSYuval Mintz if (rev_id == PCI_REVISION_ID_ERROR_VAL) { 1790dfaba6dSYuval Mintz DP_NOTICE(cdev, 1800dfaba6dSYuval Mintz "Detected PCI device error [rev_id 0x%x]. Probably due to prior indication. Aborting.\n", 1810dfaba6dSYuval Mintz rev_id); 1820dfaba6dSYuval Mintz rc = -ENODEV; 1830dfaba6dSYuval Mintz goto err2; 1840dfaba6dSYuval Mintz } 185fe56b9e6SYuval Mintz if (!pci_is_pcie(pdev)) { 186fe56b9e6SYuval Mintz DP_NOTICE(cdev, "The bus is not PCI Express\n"); 187fe56b9e6SYuval Mintz rc = -EIO; 188fe56b9e6SYuval Mintz goto err2; 189fe56b9e6SYuval Mintz } 190fe56b9e6SYuval Mintz 191fe56b9e6SYuval Mintz cdev->pci_params.pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); 192416cdf06SYuval Mintz if (IS_PF(cdev) && !cdev->pci_params.pm_cap) 193fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot find power management capability\n"); 194fe56b9e6SYuval Mintz 195fe56b9e6SYuval Mintz rc = qed_set_coherency_mask(cdev); 196fe56b9e6SYuval Mintz if (rc) 197fe56b9e6SYuval Mintz goto err2; 198fe56b9e6SYuval Mintz 199fe56b9e6SYuval Mintz cdev->pci_params.mem_start = pci_resource_start(pdev, 0); 200fe56b9e6SYuval Mintz cdev->pci_params.mem_end = pci_resource_end(pdev, 0); 201fe56b9e6SYuval Mintz cdev->pci_params.irq = pdev->irq; 202fe56b9e6SYuval Mintz 203fe56b9e6SYuval Mintz cdev->regview = pci_ioremap_bar(pdev, 0); 204fe56b9e6SYuval Mintz if (!cdev->regview) { 205fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map register space, aborting\n"); 206fe56b9e6SYuval Mintz rc = -ENOMEM; 207fe56b9e6SYuval Mintz goto err2; 208fe56b9e6SYuval Mintz } 209fe56b9e6SYuval Mintz 210fe56b9e6SYuval Mintz cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2); 211fe56b9e6SYuval Mintz cdev->db_size = pci_resource_len(cdev->pdev, 2); 2121a850bfcSMintz, Yuval if (!cdev->db_size) { 2131a850bfcSMintz, Yuval if (IS_PF(cdev)) { 2141a850bfcSMintz, Yuval DP_NOTICE(cdev, "No Doorbell bar available\n"); 2151a850bfcSMintz, Yuval return -EINVAL; 2161a850bfcSMintz, Yuval } else { 2171a850bfcSMintz, Yuval return 0; 2181a850bfcSMintz, Yuval } 2191a850bfcSMintz, Yuval } 2201a850bfcSMintz, Yuval 221fe56b9e6SYuval Mintz cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size); 2221a850bfcSMintz, Yuval 223fe56b9e6SYuval Mintz if (!cdev->doorbells) { 224fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map doorbell space\n"); 225fe56b9e6SYuval Mintz return -ENOMEM; 226fe56b9e6SYuval Mintz } 227fe56b9e6SYuval Mintz 228fe56b9e6SYuval Mintz return 0; 229fe56b9e6SYuval Mintz 230fe56b9e6SYuval Mintz err2: 231fe56b9e6SYuval Mintz pci_release_regions(pdev); 232fe56b9e6SYuval Mintz err1: 233fe56b9e6SYuval Mintz pci_disable_device(pdev); 234fe56b9e6SYuval Mintz err0: 235fe56b9e6SYuval Mintz return rc; 236fe56b9e6SYuval Mintz } 237fe56b9e6SYuval Mintz 238fe56b9e6SYuval Mintz int qed_fill_dev_info(struct qed_dev *cdev, 239fe56b9e6SYuval Mintz struct qed_dev_info *dev_info) 240fe56b9e6SYuval Mintz { 241c851a9dcSKalderon, Michal struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 242c851a9dcSKalderon, Michal struct qed_hw_info *hw_info = &p_hwfn->hw_info; 24319489c7fSChopra, Manish struct qed_tunnel_info *tun = &cdev->tunnel; 244cee4d264SManish Chopra struct qed_ptt *ptt; 245cee4d264SManish Chopra 246fe56b9e6SYuval Mintz memset(dev_info, 0, sizeof(struct qed_dev_info)); 247fe56b9e6SYuval Mintz 24819489c7fSChopra, Manish if (tun->vxlan.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 24919489c7fSChopra, Manish tun->vxlan.b_mode_enabled) 25019489c7fSChopra, Manish dev_info->vxlan_enable = true; 25119489c7fSChopra, Manish 25219489c7fSChopra, Manish if (tun->l2_gre.b_mode_enabled && tun->ip_gre.b_mode_enabled && 25319489c7fSChopra, Manish tun->l2_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 25419489c7fSChopra, Manish tun->ip_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 25519489c7fSChopra, Manish dev_info->gre_enable = true; 25619489c7fSChopra, Manish 25719489c7fSChopra, Manish if (tun->l2_geneve.b_mode_enabled && tun->ip_geneve.b_mode_enabled && 25819489c7fSChopra, Manish tun->l2_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 25919489c7fSChopra, Manish tun->ip_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 26019489c7fSChopra, Manish dev_info->geneve_enable = true; 26119489c7fSChopra, Manish 262fe56b9e6SYuval Mintz dev_info->num_hwfns = cdev->num_hwfns; 263fe56b9e6SYuval Mintz dev_info->pci_mem_start = cdev->pci_params.mem_start; 264fe56b9e6SYuval Mintz dev_info->pci_mem_end = cdev->pci_params.mem_end; 265fe56b9e6SYuval Mintz dev_info->pci_irq = cdev->pci_params.irq; 266c851a9dcSKalderon, Michal dev_info->rdma_supported = QED_IS_RDMA_PERSONALITY(p_hwfn); 267fc48b7a6SYuval Mintz dev_info->is_mf_default = IS_MF_DEFAULT(&cdev->hwfns[0]); 2689c79ddaaSMintz, Yuval dev_info->dev_type = cdev->type; 269c851a9dcSKalderon, Michal ether_addr_copy(dev_info->hw_mac, hw_info->hw_mac_addr); 270fe56b9e6SYuval Mintz 2711408cc1fSYuval Mintz if (IS_PF(cdev)) { 272fe56b9e6SYuval Mintz dev_info->fw_major = FW_MAJOR_VERSION; 273fe56b9e6SYuval Mintz dev_info->fw_minor = FW_MINOR_VERSION; 274fe56b9e6SYuval Mintz dev_info->fw_rev = FW_REVISION_VERSION; 275fe56b9e6SYuval Mintz dev_info->fw_eng = FW_ENGINEERING_VERSION; 276fe56b9e6SYuval Mintz dev_info->mf_mode = cdev->mf_mode; 277831bfb0eSYuval Mintz dev_info->tx_switching = true; 27814d39648SMintz, Yuval 279c851a9dcSKalderon, Michal if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME) 28014d39648SMintz, Yuval dev_info->wol_support = true; 2813c5da942SMintz, Yuval 2823c5da942SMintz, Yuval dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id; 2831408cc1fSYuval Mintz } else { 2841408cc1fSYuval Mintz qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, 2851408cc1fSYuval Mintz &dev_info->fw_minor, &dev_info->fw_rev, 2861408cc1fSYuval Mintz &dev_info->fw_eng); 2871408cc1fSYuval Mintz } 288fe56b9e6SYuval Mintz 2891408cc1fSYuval Mintz if (IS_PF(cdev)) { 290cee4d264SManish Chopra ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 291cee4d264SManish Chopra if (ptt) { 2921408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), ptt, 2931408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 2941408cc1fSYuval Mintz 295ae33666aSTomer Tayar qed_mcp_get_mbi_ver(QED_LEADING_HWFN(cdev), ptt, 296ae33666aSTomer Tayar &dev_info->mbi_version); 297ae33666aSTomer Tayar 298cee4d264SManish Chopra qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt, 299cee4d264SManish Chopra &dev_info->flash_size); 300cee4d264SManish Chopra 301cee4d264SManish Chopra qed_ptt_release(QED_LEADING_HWFN(cdev), ptt); 302cee4d264SManish Chopra } 3031408cc1fSYuval Mintz } else { 3041408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), NULL, 3051408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 3061408cc1fSYuval Mintz } 307cee4d264SManish Chopra 308c851a9dcSKalderon, Michal dev_info->mtu = hw_info->mtu; 3090fefbfbaSSudarsana Kalluru 310fe56b9e6SYuval Mintz return 0; 311fe56b9e6SYuval Mintz } 312fe56b9e6SYuval Mintz 313fe56b9e6SYuval Mintz static void qed_free_cdev(struct qed_dev *cdev) 314fe56b9e6SYuval Mintz { 315fe56b9e6SYuval Mintz kfree((void *)cdev); 316fe56b9e6SYuval Mintz } 317fe56b9e6SYuval Mintz 318fe56b9e6SYuval Mintz static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev) 319fe56b9e6SYuval Mintz { 320fe56b9e6SYuval Mintz struct qed_dev *cdev; 321fe56b9e6SYuval Mintz 322fe56b9e6SYuval Mintz cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 323fe56b9e6SYuval Mintz if (!cdev) 324fe56b9e6SYuval Mintz return cdev; 325fe56b9e6SYuval Mintz 326fe56b9e6SYuval Mintz qed_init_struct(cdev); 327fe56b9e6SYuval Mintz 328fe56b9e6SYuval Mintz return cdev; 329fe56b9e6SYuval Mintz } 330fe56b9e6SYuval Mintz 331fe56b9e6SYuval Mintz /* Sets the requested power state */ 3321a635e48SYuval Mintz static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state) 333fe56b9e6SYuval Mintz { 334fe56b9e6SYuval Mintz if (!cdev) 335fe56b9e6SYuval Mintz return -ENODEV; 336fe56b9e6SYuval Mintz 337fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n"); 338fe56b9e6SYuval Mintz return 0; 339fe56b9e6SYuval Mintz } 340fe56b9e6SYuval Mintz 341fe56b9e6SYuval Mintz /* probing */ 342fe56b9e6SYuval Mintz static struct qed_dev *qed_probe(struct pci_dev *pdev, 3431408cc1fSYuval Mintz struct qed_probe_params *params) 344fe56b9e6SYuval Mintz { 345fe56b9e6SYuval Mintz struct qed_dev *cdev; 346fe56b9e6SYuval Mintz int rc; 347fe56b9e6SYuval Mintz 348fe56b9e6SYuval Mintz cdev = qed_alloc_cdev(pdev); 349fe56b9e6SYuval Mintz if (!cdev) 350fe56b9e6SYuval Mintz goto err0; 351fe56b9e6SYuval Mintz 352712c3cbfSMintz, Yuval cdev->drv_type = DRV_ID_DRV_TYPE_LINUX; 3531408cc1fSYuval Mintz cdev->protocol = params->protocol; 354fe56b9e6SYuval Mintz 3551408cc1fSYuval Mintz if (params->is_vf) 3561408cc1fSYuval Mintz cdev->b_is_vf = true; 3571408cc1fSYuval Mintz 3581408cc1fSYuval Mintz qed_init_dp(cdev, params->dp_module, params->dp_level); 359fe56b9e6SYuval Mintz 360fe56b9e6SYuval Mintz rc = qed_init_pci(cdev, pdev); 361fe56b9e6SYuval Mintz if (rc) { 362fe56b9e6SYuval Mintz DP_ERR(cdev, "init pci failed\n"); 363fe56b9e6SYuval Mintz goto err1; 364fe56b9e6SYuval Mintz } 365fe56b9e6SYuval Mintz DP_INFO(cdev, "PCI init completed successfully\n"); 366fe56b9e6SYuval Mintz 367fe56b9e6SYuval Mintz rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); 368fe56b9e6SYuval Mintz if (rc) { 369fe56b9e6SYuval Mintz DP_ERR(cdev, "hw prepare failed\n"); 370fe56b9e6SYuval Mintz goto err2; 371fe56b9e6SYuval Mintz } 372fe56b9e6SYuval Mintz 373fe56b9e6SYuval Mintz DP_INFO(cdev, "qed_probe completed successffuly\n"); 374fe56b9e6SYuval Mintz 375fe56b9e6SYuval Mintz return cdev; 376fe56b9e6SYuval Mintz 377fe56b9e6SYuval Mintz err2: 378fe56b9e6SYuval Mintz qed_free_pci(cdev); 379fe56b9e6SYuval Mintz err1: 380fe56b9e6SYuval Mintz qed_free_cdev(cdev); 381fe56b9e6SYuval Mintz err0: 382fe56b9e6SYuval Mintz return NULL; 383fe56b9e6SYuval Mintz } 384fe56b9e6SYuval Mintz 385fe56b9e6SYuval Mintz static void qed_remove(struct qed_dev *cdev) 386fe56b9e6SYuval Mintz { 387fe56b9e6SYuval Mintz if (!cdev) 388fe56b9e6SYuval Mintz return; 389fe56b9e6SYuval Mintz 390fe56b9e6SYuval Mintz qed_hw_remove(cdev); 391fe56b9e6SYuval Mintz 392fe56b9e6SYuval Mintz qed_free_pci(cdev); 393fe56b9e6SYuval Mintz 394fe56b9e6SYuval Mintz qed_set_power_state(cdev, PCI_D3hot); 395fe56b9e6SYuval Mintz 396fe56b9e6SYuval Mintz qed_free_cdev(cdev); 397fe56b9e6SYuval Mintz } 398fe56b9e6SYuval Mintz 399fe56b9e6SYuval Mintz static void qed_disable_msix(struct qed_dev *cdev) 400fe56b9e6SYuval Mintz { 401fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 402fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 403fe56b9e6SYuval Mintz kfree(cdev->int_params.msix_table); 404fe56b9e6SYuval Mintz } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) { 405fe56b9e6SYuval Mintz pci_disable_msi(cdev->pdev); 406fe56b9e6SYuval Mintz } 407fe56b9e6SYuval Mintz 408fe56b9e6SYuval Mintz memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param)); 409fe56b9e6SYuval Mintz } 410fe56b9e6SYuval Mintz 411fe56b9e6SYuval Mintz static int qed_enable_msix(struct qed_dev *cdev, 412fe56b9e6SYuval Mintz struct qed_int_params *int_params) 413fe56b9e6SYuval Mintz { 414fe56b9e6SYuval Mintz int i, rc, cnt; 415fe56b9e6SYuval Mintz 416fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 417fe56b9e6SYuval Mintz 418fe56b9e6SYuval Mintz for (i = 0; i < cnt; i++) 419fe56b9e6SYuval Mintz int_params->msix_table[i].entry = i; 420fe56b9e6SYuval Mintz 421fe56b9e6SYuval Mintz rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table, 422fe56b9e6SYuval Mintz int_params->in.min_msix_cnt, cnt); 423fe56b9e6SYuval Mintz if (rc < cnt && rc >= int_params->in.min_msix_cnt && 424fe56b9e6SYuval Mintz (rc % cdev->num_hwfns)) { 425fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 426fe56b9e6SYuval Mintz 427fe56b9e6SYuval Mintz /* If fastpath is initialized, we need at least one interrupt 428fe56b9e6SYuval Mintz * per hwfn [and the slow path interrupts]. New requested number 429fe56b9e6SYuval Mintz * should be a multiple of the number of hwfns. 430fe56b9e6SYuval Mintz */ 431fe56b9e6SYuval Mintz cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns; 432fe56b9e6SYuval Mintz DP_NOTICE(cdev, 433fe56b9e6SYuval Mintz "Trying to enable MSI-X with less vectors (%d out of %d)\n", 434fe56b9e6SYuval Mintz cnt, int_params->in.num_vectors); 4351a635e48SYuval Mintz rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table, 4361a635e48SYuval Mintz cnt); 437fe56b9e6SYuval Mintz if (!rc) 438fe56b9e6SYuval Mintz rc = cnt; 439fe56b9e6SYuval Mintz } 440fe56b9e6SYuval Mintz 441fe56b9e6SYuval Mintz if (rc > 0) { 442fe56b9e6SYuval Mintz /* MSI-x configuration was achieved */ 443fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSIX; 444fe56b9e6SYuval Mintz int_params->out.num_vectors = rc; 445fe56b9e6SYuval Mintz rc = 0; 446fe56b9e6SYuval Mintz } else { 447fe56b9e6SYuval Mintz DP_NOTICE(cdev, 448fe56b9e6SYuval Mintz "Failed to enable MSI-X [Requested %d vectors][rc %d]\n", 449fe56b9e6SYuval Mintz cnt, rc); 450fe56b9e6SYuval Mintz } 451fe56b9e6SYuval Mintz 452fe56b9e6SYuval Mintz return rc; 453fe56b9e6SYuval Mintz } 454fe56b9e6SYuval Mintz 455fe56b9e6SYuval Mintz /* This function outputs the int mode and the number of enabled msix vector */ 456fe56b9e6SYuval Mintz static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) 457fe56b9e6SYuval Mintz { 458fe56b9e6SYuval Mintz struct qed_int_params *int_params = &cdev->int_params; 459fe56b9e6SYuval Mintz struct msix_entry *tbl; 460fe56b9e6SYuval Mintz int rc = 0, cnt; 461fe56b9e6SYuval Mintz 462fe56b9e6SYuval Mintz switch (int_params->in.int_mode) { 463fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 464fe56b9e6SYuval Mintz /* Allocate MSIX table */ 465fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 466fe56b9e6SYuval Mintz int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL); 467fe56b9e6SYuval Mintz if (!int_params->msix_table) { 468fe56b9e6SYuval Mintz rc = -ENOMEM; 469fe56b9e6SYuval Mintz goto out; 470fe56b9e6SYuval Mintz } 471fe56b9e6SYuval Mintz 472fe56b9e6SYuval Mintz /* Enable MSIX */ 473fe56b9e6SYuval Mintz rc = qed_enable_msix(cdev, int_params); 474fe56b9e6SYuval Mintz if (!rc) 475fe56b9e6SYuval Mintz goto out; 476fe56b9e6SYuval Mintz 477fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI-X\n"); 478fe56b9e6SYuval Mintz kfree(int_params->msix_table); 479fe56b9e6SYuval Mintz if (force_mode) 480fe56b9e6SYuval Mintz goto out; 481fe56b9e6SYuval Mintz /* Fallthrough */ 482fe56b9e6SYuval Mintz 483fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 484bb13ace7SSudarsana Reddy Kalluru if (cdev->num_hwfns == 1) { 485fe56b9e6SYuval Mintz rc = pci_enable_msi(cdev->pdev); 486fe56b9e6SYuval Mintz if (!rc) { 487fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSI; 488fe56b9e6SYuval Mintz goto out; 489fe56b9e6SYuval Mintz } 490fe56b9e6SYuval Mintz 491fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI\n"); 492fe56b9e6SYuval Mintz if (force_mode) 493fe56b9e6SYuval Mintz goto out; 494bb13ace7SSudarsana Reddy Kalluru } 495fe56b9e6SYuval Mintz /* Fallthrough */ 496fe56b9e6SYuval Mintz 497fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 498fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_INTA; 499fe56b9e6SYuval Mintz rc = 0; 500fe56b9e6SYuval Mintz goto out; 501fe56b9e6SYuval Mintz default: 502fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Unknown int_mode value %d\n", 503fe56b9e6SYuval Mintz int_params->in.int_mode); 504fe56b9e6SYuval Mintz rc = -EINVAL; 505fe56b9e6SYuval Mintz } 506fe56b9e6SYuval Mintz 507fe56b9e6SYuval Mintz out: 508525ef5c0SYuval Mintz if (!rc) 509525ef5c0SYuval Mintz DP_INFO(cdev, "Using %s interrupts\n", 510525ef5c0SYuval Mintz int_params->out.int_mode == QED_INT_MODE_INTA ? 511525ef5c0SYuval Mintz "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ? 512525ef5c0SYuval Mintz "MSI" : "MSIX"); 513fe56b9e6SYuval Mintz cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE; 514fe56b9e6SYuval Mintz 515fe56b9e6SYuval Mintz return rc; 516fe56b9e6SYuval Mintz } 517fe56b9e6SYuval Mintz 518fe56b9e6SYuval Mintz static void qed_simd_handler_config(struct qed_dev *cdev, void *token, 519fe56b9e6SYuval Mintz int index, void(*handler)(void *)) 520fe56b9e6SYuval Mintz { 521fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 522fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 523fe56b9e6SYuval Mintz 524fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].func = handler; 525fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].token = token; 526fe56b9e6SYuval Mintz } 527fe56b9e6SYuval Mintz 528fe56b9e6SYuval Mintz static void qed_simd_handler_clean(struct qed_dev *cdev, int index) 529fe56b9e6SYuval Mintz { 530fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 531fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 532fe56b9e6SYuval Mintz 533fe56b9e6SYuval Mintz memset(&hwfn->simd_proto_handler[relative_idx], 0, 534fe56b9e6SYuval Mintz sizeof(struct qed_simd_fp_handler)); 535fe56b9e6SYuval Mintz } 536fe56b9e6SYuval Mintz 537fe56b9e6SYuval Mintz static irqreturn_t qed_msix_sp_int(int irq, void *tasklet) 538fe56b9e6SYuval Mintz { 539fe56b9e6SYuval Mintz tasklet_schedule((struct tasklet_struct *)tasklet); 540fe56b9e6SYuval Mintz return IRQ_HANDLED; 541fe56b9e6SYuval Mintz } 542fe56b9e6SYuval Mintz 543fe56b9e6SYuval Mintz static irqreturn_t qed_single_int(int irq, void *dev_instance) 544fe56b9e6SYuval Mintz { 545fe56b9e6SYuval Mintz struct qed_dev *cdev = (struct qed_dev *)dev_instance; 546fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 547fe56b9e6SYuval Mintz irqreturn_t rc = IRQ_NONE; 548fe56b9e6SYuval Mintz u64 status; 549fe56b9e6SYuval Mintz int i, j; 550fe56b9e6SYuval Mintz 551fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 552fe56b9e6SYuval Mintz status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]); 553fe56b9e6SYuval Mintz 554fe56b9e6SYuval Mintz if (!status) 555fe56b9e6SYuval Mintz continue; 556fe56b9e6SYuval Mintz 557fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 558fe56b9e6SYuval Mintz 559fe56b9e6SYuval Mintz /* Slowpath interrupt */ 560fe56b9e6SYuval Mintz if (unlikely(status & 0x1)) { 561fe56b9e6SYuval Mintz tasklet_schedule(hwfn->sp_dpc); 562fe56b9e6SYuval Mintz status &= ~0x1; 563fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 564fe56b9e6SYuval Mintz } 565fe56b9e6SYuval Mintz 566fe56b9e6SYuval Mintz /* Fastpath interrupts */ 567fe56b9e6SYuval Mintz for (j = 0; j < 64; j++) { 568fe56b9e6SYuval Mintz if ((0x2ULL << j) & status) { 569fe56b9e6SYuval Mintz hwfn->simd_proto_handler[j].func( 570fe56b9e6SYuval Mintz hwfn->simd_proto_handler[j].token); 571fe56b9e6SYuval Mintz status &= ~(0x2ULL << j); 572fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 573fe56b9e6SYuval Mintz } 574fe56b9e6SYuval Mintz } 575fe56b9e6SYuval Mintz 576fe56b9e6SYuval Mintz if (unlikely(status)) 577fe56b9e6SYuval Mintz DP_VERBOSE(hwfn, NETIF_MSG_INTR, 578fe56b9e6SYuval Mintz "got an unknown interrupt status 0x%llx\n", 579fe56b9e6SYuval Mintz status); 580fe56b9e6SYuval Mintz } 581fe56b9e6SYuval Mintz 582fe56b9e6SYuval Mintz return rc; 583fe56b9e6SYuval Mintz } 584fe56b9e6SYuval Mintz 5858f16bc97SSudarsana Kalluru int qed_slowpath_irq_req(struct qed_hwfn *hwfn) 586fe56b9e6SYuval Mintz { 5878f16bc97SSudarsana Kalluru struct qed_dev *cdev = hwfn->cdev; 588525ef5c0SYuval Mintz u32 int_mode; 5898f16bc97SSudarsana Kalluru int rc = 0; 5908f16bc97SSudarsana Kalluru u8 id; 591fe56b9e6SYuval Mintz 592525ef5c0SYuval Mintz int_mode = cdev->int_params.out.int_mode; 593525ef5c0SYuval Mintz if (int_mode == QED_INT_MODE_MSIX) { 5948f16bc97SSudarsana Kalluru id = hwfn->my_id; 5958f16bc97SSudarsana Kalluru snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x", 5968f16bc97SSudarsana Kalluru id, cdev->pdev->bus->number, 5978f16bc97SSudarsana Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 5988f16bc97SSudarsana Kalluru rc = request_irq(cdev->int_params.msix_table[id].vector, 5998f16bc97SSudarsana Kalluru qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); 600fe56b9e6SYuval Mintz } else { 601fe56b9e6SYuval Mintz unsigned long flags = 0; 602fe56b9e6SYuval Mintz 603fe56b9e6SYuval Mintz snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x", 604fe56b9e6SYuval Mintz cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), 605fe56b9e6SYuval Mintz PCI_FUNC(cdev->pdev->devfn)); 606fe56b9e6SYuval Mintz 607fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA) 608fe56b9e6SYuval Mintz flags |= IRQF_SHARED; 609fe56b9e6SYuval Mintz 610fe56b9e6SYuval Mintz rc = request_irq(cdev->pdev->irq, qed_single_int, 611fe56b9e6SYuval Mintz flags, cdev->name, cdev); 612fe56b9e6SYuval Mintz } 613fe56b9e6SYuval Mintz 614525ef5c0SYuval Mintz if (rc) 615525ef5c0SYuval Mintz DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc); 616525ef5c0SYuval Mintz else 617525ef5c0SYuval Mintz DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP), 618525ef5c0SYuval Mintz "Requested slowpath %s\n", 619525ef5c0SYuval Mintz (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ"); 620525ef5c0SYuval Mintz 621fe56b9e6SYuval Mintz return rc; 622fe56b9e6SYuval Mintz } 623fe56b9e6SYuval Mintz 62406892f2eSTomer Tayar static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn) 62506892f2eSTomer Tayar { 62606892f2eSTomer Tayar /* Calling the disable function will make sure that any 62706892f2eSTomer Tayar * currently-running function is completed. The following call to the 62806892f2eSTomer Tayar * enable function makes this sequence a flush-like operation. 62906892f2eSTomer Tayar */ 63006892f2eSTomer Tayar if (p_hwfn->b_sp_dpc_enabled) { 63106892f2eSTomer Tayar tasklet_disable(p_hwfn->sp_dpc); 63206892f2eSTomer Tayar tasklet_enable(p_hwfn->sp_dpc); 63306892f2eSTomer Tayar } 63406892f2eSTomer Tayar } 63506892f2eSTomer Tayar 6361226337aSTomer Tayar void qed_slowpath_irq_sync(struct qed_hwfn *p_hwfn) 6371226337aSTomer Tayar { 6381226337aSTomer Tayar struct qed_dev *cdev = p_hwfn->cdev; 6391226337aSTomer Tayar u8 id = p_hwfn->my_id; 6401226337aSTomer Tayar u32 int_mode; 6411226337aSTomer Tayar 6421226337aSTomer Tayar int_mode = cdev->int_params.out.int_mode; 6431226337aSTomer Tayar if (int_mode == QED_INT_MODE_MSIX) 6441226337aSTomer Tayar synchronize_irq(cdev->int_params.msix_table[id].vector); 6451226337aSTomer Tayar else 6461226337aSTomer Tayar synchronize_irq(cdev->pdev->irq); 64706892f2eSTomer Tayar 64806892f2eSTomer Tayar qed_slowpath_tasklet_flush(p_hwfn); 6491226337aSTomer Tayar } 6501226337aSTomer Tayar 651fe56b9e6SYuval Mintz static void qed_slowpath_irq_free(struct qed_dev *cdev) 652fe56b9e6SYuval Mintz { 653fe56b9e6SYuval Mintz int i; 654fe56b9e6SYuval Mintz 655fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 656fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 6578f16bc97SSudarsana Kalluru if (!cdev->hwfns[i].b_int_requested) 6588f16bc97SSudarsana Kalluru break; 659fe56b9e6SYuval Mintz synchronize_irq(cdev->int_params.msix_table[i].vector); 660fe56b9e6SYuval Mintz free_irq(cdev->int_params.msix_table[i].vector, 661fe56b9e6SYuval Mintz cdev->hwfns[i].sp_dpc); 662fe56b9e6SYuval Mintz } 663fe56b9e6SYuval Mintz } else { 6648f16bc97SSudarsana Kalluru if (QED_LEADING_HWFN(cdev)->b_int_requested) 665fe56b9e6SYuval Mintz free_irq(cdev->pdev->irq, cdev); 666fe56b9e6SYuval Mintz } 6678f16bc97SSudarsana Kalluru qed_int_disable_post_isr_release(cdev); 668fe56b9e6SYuval Mintz } 669fe56b9e6SYuval Mintz 670fe56b9e6SYuval Mintz static int qed_nic_stop(struct qed_dev *cdev) 671fe56b9e6SYuval Mintz { 672fe56b9e6SYuval Mintz int i, rc; 673fe56b9e6SYuval Mintz 674fe56b9e6SYuval Mintz rc = qed_hw_stop(cdev); 675fe56b9e6SYuval Mintz 676fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 677fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 678fe56b9e6SYuval Mintz 679fe56b9e6SYuval Mintz if (p_hwfn->b_sp_dpc_enabled) { 680fe56b9e6SYuval Mintz tasklet_disable(p_hwfn->sp_dpc); 681fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = false; 682fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_IFDOWN, 683fe56b9e6SYuval Mintz "Disabled sp taskelt [hwfn %d] at %p\n", 684fe56b9e6SYuval Mintz i, p_hwfn->sp_dpc); 685fe56b9e6SYuval Mintz } 686fe56b9e6SYuval Mintz } 687fe56b9e6SYuval Mintz 688c965db44STomer Tayar qed_dbg_pf_exit(cdev); 689c965db44STomer Tayar 690fe56b9e6SYuval Mintz return rc; 691fe56b9e6SYuval Mintz } 692fe56b9e6SYuval Mintz 693fe56b9e6SYuval Mintz static int qed_nic_setup(struct qed_dev *cdev) 694fe56b9e6SYuval Mintz { 6950a7fb11cSYuval Mintz int rc, i; 6960a7fb11cSYuval Mintz 6970a7fb11cSYuval Mintz /* Determine if interface is going to require LL2 */ 6980a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) { 6990a7fb11cSYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 7000a7fb11cSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 7010a7fb11cSYuval Mintz 7020a7fb11cSYuval Mintz p_hwfn->using_ll2 = true; 7030a7fb11cSYuval Mintz } 7040a7fb11cSYuval Mintz } 705fe56b9e6SYuval Mintz 706fe56b9e6SYuval Mintz rc = qed_resc_alloc(cdev); 707fe56b9e6SYuval Mintz if (rc) 708fe56b9e6SYuval Mintz return rc; 709fe56b9e6SYuval Mintz 710fe56b9e6SYuval Mintz DP_INFO(cdev, "Allocated qed resources\n"); 711fe56b9e6SYuval Mintz 712fe56b9e6SYuval Mintz qed_resc_setup(cdev); 713fe56b9e6SYuval Mintz 714fe56b9e6SYuval Mintz return rc; 715fe56b9e6SYuval Mintz } 716fe56b9e6SYuval Mintz 717fe56b9e6SYuval Mintz static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt) 718fe56b9e6SYuval Mintz { 719fe56b9e6SYuval Mintz int limit = 0; 720fe56b9e6SYuval Mintz 721fe56b9e6SYuval Mintz /* Mark the fastpath as free/used */ 722fe56b9e6SYuval Mintz cdev->int_params.fp_initialized = cnt ? true : false; 723fe56b9e6SYuval Mintz 724fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX) 725fe56b9e6SYuval Mintz limit = cdev->num_hwfns * 63; 726fe56b9e6SYuval Mintz else if (cdev->int_params.fp_msix_cnt) 727fe56b9e6SYuval Mintz limit = cdev->int_params.fp_msix_cnt; 728fe56b9e6SYuval Mintz 729fe56b9e6SYuval Mintz if (!limit) 730fe56b9e6SYuval Mintz return -ENOMEM; 731fe56b9e6SYuval Mintz 732fe56b9e6SYuval Mintz return min_t(int, cnt, limit); 733fe56b9e6SYuval Mintz } 734fe56b9e6SYuval Mintz 735fe56b9e6SYuval Mintz static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info) 736fe56b9e6SYuval Mintz { 737fe56b9e6SYuval Mintz memset(info, 0, sizeof(struct qed_int_info)); 738fe56b9e6SYuval Mintz 739fe56b9e6SYuval Mintz if (!cdev->int_params.fp_initialized) { 740fe56b9e6SYuval Mintz DP_INFO(cdev, 741fe56b9e6SYuval Mintz "Protocol driver requested interrupt information, but its support is not yet configured\n"); 742fe56b9e6SYuval Mintz return -EINVAL; 743fe56b9e6SYuval Mintz } 744fe56b9e6SYuval Mintz 745fe56b9e6SYuval Mintz /* Need to expose only MSI-X information; Single IRQ is handled solely 746fe56b9e6SYuval Mintz * by qed. 747fe56b9e6SYuval Mintz */ 748fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 749fe56b9e6SYuval Mintz int msix_base = cdev->int_params.fp_msix_base; 750fe56b9e6SYuval Mintz 751fe56b9e6SYuval Mintz info->msix_cnt = cdev->int_params.fp_msix_cnt; 752fe56b9e6SYuval Mintz info->msix = &cdev->int_params.msix_table[msix_base]; 753fe56b9e6SYuval Mintz } 754fe56b9e6SYuval Mintz 755fe56b9e6SYuval Mintz return 0; 756fe56b9e6SYuval Mintz } 757fe56b9e6SYuval Mintz 758fe56b9e6SYuval Mintz static int qed_slowpath_setup_int(struct qed_dev *cdev, 759fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 760fe56b9e6SYuval Mintz { 7614ac801b7SYuval Mintz struct qed_sb_cnt_info sb_cnt_info; 7620189efb8SYuval Mintz int num_l2_queues = 0; 7634ac801b7SYuval Mintz int rc; 7644ac801b7SYuval Mintz int i; 765fe56b9e6SYuval Mintz 7661d2c2024SSudarsana Reddy Kalluru if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { 7671d2c2024SSudarsana Reddy Kalluru DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); 7681d2c2024SSudarsana Reddy Kalluru return -EINVAL; 7691d2c2024SSudarsana Reddy Kalluru } 7701d2c2024SSudarsana Reddy Kalluru 7711d2c2024SSudarsana Reddy Kalluru memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 772fe56b9e6SYuval Mintz cdev->int_params.in.int_mode = int_mode; 7734ac801b7SYuval Mintz for_each_hwfn(cdev, i) { 7744ac801b7SYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); 7754ac801b7SYuval Mintz qed_int_get_num_sbs(&cdev->hwfns[i], &sb_cnt_info); 776726fdbe9SMintz, Yuval cdev->int_params.in.num_vectors += sb_cnt_info.cnt; 7774ac801b7SYuval Mintz cdev->int_params.in.num_vectors++; /* slowpath */ 7784ac801b7SYuval Mintz } 779fe56b9e6SYuval Mintz 780fe56b9e6SYuval Mintz /* We want a minimum of one slowpath and one fastpath vector per hwfn */ 781fe56b9e6SYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; 782fe56b9e6SYuval Mintz 783fe56b9e6SYuval Mintz rc = qed_set_int_mode(cdev, false); 784fe56b9e6SYuval Mintz if (rc) { 785fe56b9e6SYuval Mintz DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); 786fe56b9e6SYuval Mintz return rc; 787fe56b9e6SYuval Mintz } 788fe56b9e6SYuval Mintz 789fe56b9e6SYuval Mintz cdev->int_params.fp_msix_base = cdev->num_hwfns; 790fe56b9e6SYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors - 791fe56b9e6SYuval Mintz cdev->num_hwfns; 792fe56b9e6SYuval Mintz 7932f782278SMintz, Yuval if (!IS_ENABLED(CONFIG_QED_RDMA) || 794c851a9dcSKalderon, Michal !QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) 7950189efb8SYuval Mintz return 0; 7960189efb8SYuval Mintz 79751ff1725SRam Amrani for_each_hwfn(cdev, i) 79851ff1725SRam Amrani num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE); 79951ff1725SRam Amrani 80051ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, 80151ff1725SRam Amrani "cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n", 80251ff1725SRam Amrani cdev->int_params.fp_msix_cnt, num_l2_queues); 80351ff1725SRam Amrani 80451ff1725SRam Amrani if (cdev->int_params.fp_msix_cnt > num_l2_queues) { 80551ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 80651ff1725SRam Amrani (cdev->int_params.fp_msix_cnt - num_l2_queues) 80751ff1725SRam Amrani / cdev->num_hwfns; 80851ff1725SRam Amrani cdev->int_params.rdma_msix_base = 80951ff1725SRam Amrani cdev->int_params.fp_msix_base + num_l2_queues; 81051ff1725SRam Amrani cdev->int_params.fp_msix_cnt = num_l2_queues; 81151ff1725SRam Amrani } else { 81251ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 0; 81351ff1725SRam Amrani } 81451ff1725SRam Amrani 81551ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n", 81651ff1725SRam Amrani cdev->int_params.rdma_msix_cnt, 81751ff1725SRam Amrani cdev->int_params.rdma_msix_base); 81851ff1725SRam Amrani 819fe56b9e6SYuval Mintz return 0; 820fe56b9e6SYuval Mintz } 821fe56b9e6SYuval Mintz 8221408cc1fSYuval Mintz static int qed_slowpath_vf_setup_int(struct qed_dev *cdev) 8231408cc1fSYuval Mintz { 8241408cc1fSYuval Mintz int rc; 8251408cc1fSYuval Mintz 8261408cc1fSYuval Mintz memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 8271408cc1fSYuval Mintz cdev->int_params.in.int_mode = QED_INT_MODE_MSIX; 8281408cc1fSYuval Mintz 8291408cc1fSYuval Mintz qed_vf_get_num_rxqs(QED_LEADING_HWFN(cdev), 8301408cc1fSYuval Mintz &cdev->int_params.in.num_vectors); 8311408cc1fSYuval Mintz if (cdev->num_hwfns > 1) { 8321408cc1fSYuval Mintz u8 vectors = 0; 8331408cc1fSYuval Mintz 8341408cc1fSYuval Mintz qed_vf_get_num_rxqs(&cdev->hwfns[1], &vectors); 8351408cc1fSYuval Mintz cdev->int_params.in.num_vectors += vectors; 8361408cc1fSYuval Mintz } 8371408cc1fSYuval Mintz 8381408cc1fSYuval Mintz /* We want a minimum of one fastpath vector per vf hwfn */ 8391408cc1fSYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns; 8401408cc1fSYuval Mintz 8411408cc1fSYuval Mintz rc = qed_set_int_mode(cdev, true); 8421408cc1fSYuval Mintz if (rc) 8431408cc1fSYuval Mintz return rc; 8441408cc1fSYuval Mintz 8451408cc1fSYuval Mintz cdev->int_params.fp_msix_base = 0; 8461408cc1fSYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors; 8471408cc1fSYuval Mintz 8481408cc1fSYuval Mintz return 0; 8491408cc1fSYuval Mintz } 8501408cc1fSYuval Mintz 851fe56b9e6SYuval Mintz u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, 852fe56b9e6SYuval Mintz u8 *input_buf, u32 max_size, u8 *unzip_buf) 853fe56b9e6SYuval Mintz { 854fe56b9e6SYuval Mintz int rc; 855fe56b9e6SYuval Mintz 856fe56b9e6SYuval Mintz p_hwfn->stream->next_in = input_buf; 857fe56b9e6SYuval Mintz p_hwfn->stream->avail_in = input_len; 858fe56b9e6SYuval Mintz p_hwfn->stream->next_out = unzip_buf; 859fe56b9e6SYuval Mintz p_hwfn->stream->avail_out = max_size; 860fe56b9e6SYuval Mintz 861fe56b9e6SYuval Mintz rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS); 862fe56b9e6SYuval Mintz 863fe56b9e6SYuval Mintz if (rc != Z_OK) { 864fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n", 865fe56b9e6SYuval Mintz rc); 866fe56b9e6SYuval Mintz return 0; 867fe56b9e6SYuval Mintz } 868fe56b9e6SYuval Mintz 869fe56b9e6SYuval Mintz rc = zlib_inflate(p_hwfn->stream, Z_FINISH); 870fe56b9e6SYuval Mintz zlib_inflateEnd(p_hwfn->stream); 871fe56b9e6SYuval Mintz 872fe56b9e6SYuval Mintz if (rc != Z_OK && rc != Z_STREAM_END) { 873fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n", 874fe56b9e6SYuval Mintz p_hwfn->stream->msg, rc); 875fe56b9e6SYuval Mintz return 0; 876fe56b9e6SYuval Mintz } 877fe56b9e6SYuval Mintz 878fe56b9e6SYuval Mintz return p_hwfn->stream->total_out / 4; 879fe56b9e6SYuval Mintz } 880fe56b9e6SYuval Mintz 881fe56b9e6SYuval Mintz static int qed_alloc_stream_mem(struct qed_dev *cdev) 882fe56b9e6SYuval Mintz { 883fe56b9e6SYuval Mintz int i; 884fe56b9e6SYuval Mintz void *workspace; 885fe56b9e6SYuval Mintz 886fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 887fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 888fe56b9e6SYuval Mintz 889fe56b9e6SYuval Mintz p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL); 890fe56b9e6SYuval Mintz if (!p_hwfn->stream) 891fe56b9e6SYuval Mintz return -ENOMEM; 892fe56b9e6SYuval Mintz 893fe56b9e6SYuval Mintz workspace = vzalloc(zlib_inflate_workspacesize()); 894fe56b9e6SYuval Mintz if (!workspace) 895fe56b9e6SYuval Mintz return -ENOMEM; 896fe56b9e6SYuval Mintz p_hwfn->stream->workspace = workspace; 897fe56b9e6SYuval Mintz } 898fe56b9e6SYuval Mintz 899fe56b9e6SYuval Mintz return 0; 900fe56b9e6SYuval Mintz } 901fe56b9e6SYuval Mintz 902fe56b9e6SYuval Mintz static void qed_free_stream_mem(struct qed_dev *cdev) 903fe56b9e6SYuval Mintz { 904fe56b9e6SYuval Mintz int i; 905fe56b9e6SYuval Mintz 906fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 907fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 908fe56b9e6SYuval Mintz 909fe56b9e6SYuval Mintz if (!p_hwfn->stream) 910fe56b9e6SYuval Mintz return; 911fe56b9e6SYuval Mintz 912fe56b9e6SYuval Mintz vfree(p_hwfn->stream->workspace); 913fe56b9e6SYuval Mintz kfree(p_hwfn->stream); 914fe56b9e6SYuval Mintz } 915fe56b9e6SYuval Mintz } 916fe56b9e6SYuval Mintz 917fe56b9e6SYuval Mintz static void qed_update_pf_params(struct qed_dev *cdev, 918fe56b9e6SYuval Mintz struct qed_pf_params *params) 919fe56b9e6SYuval Mintz { 920fe56b9e6SYuval Mintz int i; 921fe56b9e6SYuval Mintz 9225c5f2609SRam Amrani if (IS_ENABLED(CONFIG_QED_RDMA)) { 9230189efb8SYuval Mintz params->rdma_pf_params.num_qps = QED_ROCE_QPS; 9240189efb8SYuval Mintz params->rdma_pf_params.min_dpis = QED_ROCE_DPIS; 9250189efb8SYuval Mintz /* divide by 3 the MRs to avoid MF ILT overflow */ 9260189efb8SYuval Mintz params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX; 927fe56b9e6SYuval Mintz } 928fe56b9e6SYuval Mintz 929d51e4af5SChopra, Manish if (cdev->num_hwfns > 1 || IS_VF(cdev)) 930d51e4af5SChopra, Manish params->eth_pf_params.num_arfs_filters = 0; 931d51e4af5SChopra, Manish 932e1d32acbSMintz, Yuval /* In case we might support RDMA, don't allow qede to be greedy 933e1d32acbSMintz, Yuval * with the L2 contexts. Allow for 64 queues [rx, tx, xdp] per hwfn. 934e1d32acbSMintz, Yuval */ 935c851a9dcSKalderon, Michal if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) { 936e1d32acbSMintz, Yuval u16 *num_cons; 937e1d32acbSMintz, Yuval 938e1d32acbSMintz, Yuval num_cons = ¶ms->eth_pf_params.num_cons; 939e1d32acbSMintz, Yuval *num_cons = min_t(u16, *num_cons, 192); 940e1d32acbSMintz, Yuval } 941e1d32acbSMintz, Yuval 9425c5f2609SRam Amrani for (i = 0; i < cdev->num_hwfns; i++) { 9435c5f2609SRam Amrani struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 9445c5f2609SRam Amrani 9455c5f2609SRam Amrani p_hwfn->pf_params = *params; 9465c5f2609SRam Amrani } 9475c5f2609SRam Amrani } 9485c5f2609SRam Amrani 949fe56b9e6SYuval Mintz static int qed_slowpath_start(struct qed_dev *cdev, 950fe56b9e6SYuval Mintz struct qed_slowpath_params *params) 951fe56b9e6SYuval Mintz { 9525d24bcf1STomer Tayar struct qed_drv_load_params drv_load_params; 953c0c2d0b4SMintz, Yuval struct qed_hw_init_params hw_init_params; 954fe56b9e6SYuval Mintz struct qed_mcp_drv_version drv_version; 95519968430SChopra, Manish struct qed_tunnel_info tunn_info; 956fe56b9e6SYuval Mintz const u8 *data = NULL; 957fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 958c78c70faSSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 95937bff2b9SYuval Mintz int rc = -EINVAL; 96037bff2b9SYuval Mintz 96137bff2b9SYuval Mintz if (qed_iov_wq_start(cdev)) 96237bff2b9SYuval Mintz goto err; 963fe56b9e6SYuval Mintz 9641408cc1fSYuval Mintz if (IS_PF(cdev)) { 965fe56b9e6SYuval Mintz rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME, 966fe56b9e6SYuval Mintz &cdev->pdev->dev); 967fe56b9e6SYuval Mintz if (rc) { 968fe56b9e6SYuval Mintz DP_NOTICE(cdev, 969fe56b9e6SYuval Mintz "Failed to find fw file - /lib/firmware/%s\n", 970fe56b9e6SYuval Mintz QED_FW_FILE_NAME); 971fe56b9e6SYuval Mintz goto err; 972fe56b9e6SYuval Mintz } 973c78c70faSSudarsana Reddy Kalluru 974d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) { 975d51e4af5SChopra, Manish p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 976d51e4af5SChopra, Manish if (p_ptt) { 977d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt = p_ptt; 978d51e4af5SChopra, Manish } else { 979d51e4af5SChopra, Manish DP_NOTICE(cdev, 980d51e4af5SChopra, Manish "Failed to acquire PTT for aRFS\n"); 981d51e4af5SChopra, Manish goto err; 982d51e4af5SChopra, Manish } 983d51e4af5SChopra, Manish } 9841408cc1fSYuval Mintz } 985fe56b9e6SYuval Mintz 9860e191827SSudarsana Reddy Kalluru cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS; 987fe56b9e6SYuval Mintz rc = qed_nic_setup(cdev); 988fe56b9e6SYuval Mintz if (rc) 989fe56b9e6SYuval Mintz goto err; 990fe56b9e6SYuval Mintz 9911408cc1fSYuval Mintz if (IS_PF(cdev)) 992fe56b9e6SYuval Mintz rc = qed_slowpath_setup_int(cdev, params->int_mode); 9931408cc1fSYuval Mintz else 9941408cc1fSYuval Mintz rc = qed_slowpath_vf_setup_int(cdev); 995fe56b9e6SYuval Mintz if (rc) 996fe56b9e6SYuval Mintz goto err1; 997fe56b9e6SYuval Mintz 9981408cc1fSYuval Mintz if (IS_PF(cdev)) { 999fe56b9e6SYuval Mintz /* Allocate stream for unzipping */ 1000fe56b9e6SYuval Mintz rc = qed_alloc_stream_mem(cdev); 10012591c280SJoe Perches if (rc) 10028f16bc97SSudarsana Kalluru goto err2; 1003fe56b9e6SYuval Mintz 10048ac1ed79SJoe Perches /* First Dword used to differentiate between various sources */ 1005351a4dedSYuval Mintz data = cdev->firmware->data + sizeof(u32); 1006c965db44STomer Tayar 1007c965db44STomer Tayar qed_dbg_pf_init(cdev); 10081408cc1fSYuval Mintz } 1009fe56b9e6SYuval Mintz 10101408cc1fSYuval Mintz /* Start the slowpath */ 1011c0c2d0b4SMintz, Yuval memset(&hw_init_params, 0, sizeof(hw_init_params)); 101219968430SChopra, Manish memset(&tunn_info, 0, sizeof(tunn_info)); 101319968430SChopra, Manish tunn_info.vxlan.b_mode_enabled = true; 101419968430SChopra, Manish tunn_info.l2_gre.b_mode_enabled = true; 101519968430SChopra, Manish tunn_info.ip_gre.b_mode_enabled = true; 101619968430SChopra, Manish tunn_info.l2_geneve.b_mode_enabled = true; 101719968430SChopra, Manish tunn_info.ip_geneve.b_mode_enabled = true; 101819968430SChopra, Manish tunn_info.vxlan.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 101919968430SChopra, Manish tunn_info.l2_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 102019968430SChopra, Manish tunn_info.ip_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 102119968430SChopra, Manish tunn_info.l2_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 102219968430SChopra, Manish tunn_info.ip_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 1023c0c2d0b4SMintz, Yuval hw_init_params.p_tunn = &tunn_info; 1024c0c2d0b4SMintz, Yuval hw_init_params.b_hw_start = true; 1025c0c2d0b4SMintz, Yuval hw_init_params.int_mode = cdev->int_params.out.int_mode; 1026c0c2d0b4SMintz, Yuval hw_init_params.allow_npar_tx_switch = true; 1027c0c2d0b4SMintz, Yuval hw_init_params.bin_fw_data = data; 1028c0c2d0b4SMintz, Yuval 10295d24bcf1STomer Tayar memset(&drv_load_params, 0, sizeof(drv_load_params)); 10305d24bcf1STomer Tayar drv_load_params.is_crash_kernel = is_kdump_kernel(); 10315d24bcf1STomer Tayar drv_load_params.mfw_timeout_val = QED_LOAD_REQ_LOCK_TO_DEFAULT; 10325d24bcf1STomer Tayar drv_load_params.avoid_eng_reset = false; 10335d24bcf1STomer Tayar drv_load_params.override_force_load = QED_OVERRIDE_FORCE_LOAD_NONE; 10345d24bcf1STomer Tayar hw_init_params.p_drv_load_params = &drv_load_params; 10355d24bcf1STomer Tayar 1036c0c2d0b4SMintz, Yuval rc = qed_hw_init(cdev, &hw_init_params); 1037fe56b9e6SYuval Mintz if (rc) 10388c925c44SYuval Mintz goto err2; 1039fe56b9e6SYuval Mintz 1040fe56b9e6SYuval Mintz DP_INFO(cdev, 1041fe56b9e6SYuval Mintz "HW initialization and function start completed successfully\n"); 1042fe56b9e6SYuval Mintz 1043eaf3c0c6SChopra, Manish if (IS_PF(cdev)) { 1044eaf3c0c6SChopra, Manish cdev->tunn_feature_mask = (BIT(QED_MODE_VXLAN_TUNN) | 1045eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GENEVE_TUNN) | 1046eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGENEVE_TUNN) | 1047eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GRE_TUNN) | 1048eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGRE_TUNN)); 1049eaf3c0c6SChopra, Manish } 1050eaf3c0c6SChopra, Manish 10510a7fb11cSYuval Mintz /* Allocate LL2 interface if needed */ 10520a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->using_ll2) { 10530a7fb11cSYuval Mintz rc = qed_ll2_alloc_if(cdev); 10540a7fb11cSYuval Mintz if (rc) 10550a7fb11cSYuval Mintz goto err3; 10560a7fb11cSYuval Mintz } 10571408cc1fSYuval Mintz if (IS_PF(cdev)) { 1058fe56b9e6SYuval Mintz hwfn = QED_LEADING_HWFN(cdev); 1059fe56b9e6SYuval Mintz drv_version.version = (params->drv_major << 24) | 1060fe56b9e6SYuval Mintz (params->drv_minor << 16) | 1061fe56b9e6SYuval Mintz (params->drv_rev << 8) | 1062fe56b9e6SYuval Mintz (params->drv_eng); 1063fe56b9e6SYuval Mintz strlcpy(drv_version.name, params->name, 1064fe56b9e6SYuval Mintz MCP_DRV_VER_STR_SIZE - 4); 1065fe56b9e6SYuval Mintz rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt, 1066fe56b9e6SYuval Mintz &drv_version); 1067fe56b9e6SYuval Mintz if (rc) { 1068fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed sending drv version command\n"); 1069fe56b9e6SYuval Mintz return rc; 1070fe56b9e6SYuval Mintz } 10711408cc1fSYuval Mintz } 1072fe56b9e6SYuval Mintz 10738c925c44SYuval Mintz qed_reset_vport_stats(cdev); 10748c925c44SYuval Mintz 1075fe56b9e6SYuval Mintz return 0; 1076fe56b9e6SYuval Mintz 10770a7fb11cSYuval Mintz err3: 10780a7fb11cSYuval Mintz qed_hw_stop(cdev); 1079fe56b9e6SYuval Mintz err2: 10808c925c44SYuval Mintz qed_hw_timers_stop_all(cdev); 10811408cc1fSYuval Mintz if (IS_PF(cdev)) 10828c925c44SYuval Mintz qed_slowpath_irq_free(cdev); 10838c925c44SYuval Mintz qed_free_stream_mem(cdev); 1084fe56b9e6SYuval Mintz qed_disable_msix(cdev); 1085fe56b9e6SYuval Mintz err1: 1086fe56b9e6SYuval Mintz qed_resc_free(cdev); 1087fe56b9e6SYuval Mintz err: 10881408cc1fSYuval Mintz if (IS_PF(cdev)) 1089fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1090fe56b9e6SYuval Mintz 1091d51e4af5SChopra, Manish if (IS_PF(cdev) && (cdev->num_hwfns == 1) && 1092d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt) 1093d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1094d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1095c78c70faSSudarsana Reddy Kalluru 109637bff2b9SYuval Mintz qed_iov_wq_stop(cdev, false); 109737bff2b9SYuval Mintz 1098fe56b9e6SYuval Mintz return rc; 1099fe56b9e6SYuval Mintz } 1100fe56b9e6SYuval Mintz 1101fe56b9e6SYuval Mintz static int qed_slowpath_stop(struct qed_dev *cdev) 1102fe56b9e6SYuval Mintz { 1103fe56b9e6SYuval Mintz if (!cdev) 1104fe56b9e6SYuval Mintz return -ENODEV; 1105fe56b9e6SYuval Mintz 11060a7fb11cSYuval Mintz qed_ll2_dealloc_if(cdev); 11070a7fb11cSYuval Mintz 11081408cc1fSYuval Mintz if (IS_PF(cdev)) { 1109d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) 1110d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1111d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1112fe56b9e6SYuval Mintz qed_free_stream_mem(cdev); 1113c5ac9319SYuval Mintz if (IS_QED_ETH_IF(cdev)) 11140b55e27dSYuval Mintz qed_sriov_disable(cdev, true); 11155f027d7aSMintz, Yuval } 1116fe56b9e6SYuval Mintz 1117fe56b9e6SYuval Mintz qed_nic_stop(cdev); 11185f027d7aSMintz, Yuval 11195f027d7aSMintz, Yuval if (IS_PF(cdev)) 1120fe56b9e6SYuval Mintz qed_slowpath_irq_free(cdev); 1121fe56b9e6SYuval Mintz 1122fe56b9e6SYuval Mintz qed_disable_msix(cdev); 11231226337aSTomer Tayar 11241226337aSTomer Tayar qed_resc_free(cdev); 1125fe56b9e6SYuval Mintz 112637bff2b9SYuval Mintz qed_iov_wq_stop(cdev, true); 112737bff2b9SYuval Mintz 11281408cc1fSYuval Mintz if (IS_PF(cdev)) 1129fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1130fe56b9e6SYuval Mintz 1131fe56b9e6SYuval Mintz return 0; 1132fe56b9e6SYuval Mintz } 1133fe56b9e6SYuval Mintz 1134712c3cbfSMintz, Yuval static void qed_set_name(struct qed_dev *cdev, char name[NAME_SIZE]) 1135fe56b9e6SYuval Mintz { 1136fe56b9e6SYuval Mintz int i; 1137fe56b9e6SYuval Mintz 1138fe56b9e6SYuval Mintz memcpy(cdev->name, name, NAME_SIZE); 1139fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) 1140fe56b9e6SYuval Mintz snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i); 1141fe56b9e6SYuval Mintz } 1142fe56b9e6SYuval Mintz 1143fe56b9e6SYuval Mintz static u32 qed_sb_init(struct qed_dev *cdev, 1144fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 1145fe56b9e6SYuval Mintz void *sb_virt_addr, 1146fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, u16 sb_id, 1147fe56b9e6SYuval Mintz enum qed_sb_type type) 1148fe56b9e6SYuval Mintz { 1149fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 115085750d74SMintz, Yuval struct qed_ptt *p_ptt; 1151fe56b9e6SYuval Mintz int hwfn_index; 1152fe56b9e6SYuval Mintz u16 rel_sb_id; 1153fe56b9e6SYuval Mintz u8 n_hwfns; 1154fe56b9e6SYuval Mintz u32 rc; 1155fe56b9e6SYuval Mintz 1156fe56b9e6SYuval Mintz /* RoCE uses single engine and CMT uses two engines. When using both 1157fe56b9e6SYuval Mintz * we force only a single engine. Storage uses only engine 0 too. 1158fe56b9e6SYuval Mintz */ 1159fe56b9e6SYuval Mintz if (type == QED_SB_TYPE_L2_QUEUE) 1160fe56b9e6SYuval Mintz n_hwfns = cdev->num_hwfns; 1161fe56b9e6SYuval Mintz else 1162fe56b9e6SYuval Mintz n_hwfns = 1; 1163fe56b9e6SYuval Mintz 1164fe56b9e6SYuval Mintz hwfn_index = sb_id % n_hwfns; 1165fe56b9e6SYuval Mintz p_hwfn = &cdev->hwfns[hwfn_index]; 1166fe56b9e6SYuval Mintz rel_sb_id = sb_id / n_hwfns; 1167fe56b9e6SYuval Mintz 1168fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1169fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 1170fe56b9e6SYuval Mintz hwfn_index, rel_sb_id, sb_id); 1171fe56b9e6SYuval Mintz 117285750d74SMintz, Yuval if (IS_PF(p_hwfn->cdev)) { 117385750d74SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 117485750d74SMintz, Yuval if (!p_ptt) 117585750d74SMintz, Yuval return -EBUSY; 117685750d74SMintz, Yuval 117785750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, p_ptt, sb_info, sb_virt_addr, 117885750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 117985750d74SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 118085750d74SMintz, Yuval } else { 118185750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, NULL, sb_info, sb_virt_addr, 118285750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 118385750d74SMintz, Yuval } 1184fe56b9e6SYuval Mintz 1185fe56b9e6SYuval Mintz return rc; 1186fe56b9e6SYuval Mintz } 1187fe56b9e6SYuval Mintz 1188fe56b9e6SYuval Mintz static u32 qed_sb_release(struct qed_dev *cdev, 11891a635e48SYuval Mintz struct qed_sb_info *sb_info, u16 sb_id) 1190fe56b9e6SYuval Mintz { 1191fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 1192fe56b9e6SYuval Mintz int hwfn_index; 1193fe56b9e6SYuval Mintz u16 rel_sb_id; 1194fe56b9e6SYuval Mintz u32 rc; 1195fe56b9e6SYuval Mintz 1196fe56b9e6SYuval Mintz hwfn_index = sb_id % cdev->num_hwfns; 1197fe56b9e6SYuval Mintz p_hwfn = &cdev->hwfns[hwfn_index]; 1198fe56b9e6SYuval Mintz rel_sb_id = sb_id / cdev->num_hwfns; 1199fe56b9e6SYuval Mintz 1200fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1201fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 1202fe56b9e6SYuval Mintz hwfn_index, rel_sb_id, sb_id); 1203fe56b9e6SYuval Mintz 1204fe56b9e6SYuval Mintz rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id); 1205fe56b9e6SYuval Mintz 1206fe56b9e6SYuval Mintz return rc; 1207fe56b9e6SYuval Mintz } 1208fe56b9e6SYuval Mintz 1209fe7cd2bfSYuval Mintz static bool qed_can_link_change(struct qed_dev *cdev) 1210fe7cd2bfSYuval Mintz { 1211fe7cd2bfSYuval Mintz return true; 1212fe7cd2bfSYuval Mintz } 1213fe7cd2bfSYuval Mintz 1214351a4dedSYuval Mintz static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params) 1215cc875c2eSYuval Mintz { 1216cc875c2eSYuval Mintz struct qed_hwfn *hwfn; 1217cc875c2eSYuval Mintz struct qed_mcp_link_params *link_params; 1218cc875c2eSYuval Mintz struct qed_ptt *ptt; 1219cc875c2eSYuval Mintz int rc; 1220cc875c2eSYuval Mintz 1221cc875c2eSYuval Mintz if (!cdev) 1222cc875c2eSYuval Mintz return -ENODEV; 1223cc875c2eSYuval Mintz 1224cc875c2eSYuval Mintz /* The link should be set only once per PF */ 1225cc875c2eSYuval Mintz hwfn = &cdev->hwfns[0]; 1226cc875c2eSYuval Mintz 122765ed2ffdSMintz, Yuval /* When VF wants to set link, force it to read the bulletin instead. 122865ed2ffdSMintz, Yuval * This mimics the PF behavior, where a noitification [both immediate 122965ed2ffdSMintz, Yuval * and possible later] would be generated when changing properties. 123065ed2ffdSMintz, Yuval */ 123165ed2ffdSMintz, Yuval if (IS_VF(cdev)) { 123265ed2ffdSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG); 123365ed2ffdSMintz, Yuval return 0; 123465ed2ffdSMintz, Yuval } 123565ed2ffdSMintz, Yuval 1236cc875c2eSYuval Mintz ptt = qed_ptt_acquire(hwfn); 1237cc875c2eSYuval Mintz if (!ptt) 1238cc875c2eSYuval Mintz return -EBUSY; 1239cc875c2eSYuval Mintz 1240cc875c2eSYuval Mintz link_params = qed_mcp_get_link_params(hwfn); 1241cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 1242cc875c2eSYuval Mintz link_params->speed.autoneg = params->autoneg; 1243cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 1244cc875c2eSYuval Mintz link_params->speed.advertised_speeds = 0; 1245054c67d1SSudarsana Reddy Kalluru if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) || 1246054c67d1SSudarsana Reddy Kalluru (params->adv_speeds & QED_LM_1000baseT_Full_BIT)) 1247cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1248cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G; 1249054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT) 1250cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1251cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G; 1252054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_25000baseKR_Full_BIT) 1253054c67d1SSudarsana Reddy Kalluru link_params->speed.advertised_speeds |= 1254054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G; 1255054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_40000baseLR4_Full_BIT) 1256cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1257cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G; 1258054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_50000baseKR2_Full_BIT) 1259cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1260cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G; 1261054c67d1SSudarsana Reddy Kalluru if (params->adv_speeds & QED_LM_100000baseKR4_Full_BIT) 1262cc875c2eSYuval Mintz link_params->speed.advertised_speeds |= 1263351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G; 1264cc875c2eSYuval Mintz } 1265cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) 1266cc875c2eSYuval Mintz link_params->speed.forced_speed = params->forced_speed; 1267a43f235fSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) { 1268a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 1269a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = true; 1270a43f235fSSudarsana Reddy Kalluru else 1271a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = false; 1272a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE) 1273a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = true; 1274a43f235fSSudarsana Reddy Kalluru else 1275a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = false; 1276a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE) 1277a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = true; 1278a43f235fSSudarsana Reddy Kalluru else 1279a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = false; 1280a43f235fSSudarsana Reddy Kalluru } 128103dc76caSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) { 128203dc76caSSudarsana Reddy Kalluru switch (params->loopback_mode) { 128303dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_INT_PHY: 1284351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_INT_PHY; 128503dc76caSSudarsana Reddy Kalluru break; 128603dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT_PHY: 1287351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT_PHY; 128803dc76caSSudarsana Reddy Kalluru break; 128903dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT: 1290351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT; 129103dc76caSSudarsana Reddy Kalluru break; 129203dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_MAC: 1293351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_MAC; 129403dc76caSSudarsana Reddy Kalluru break; 129503dc76caSSudarsana Reddy Kalluru default: 1296351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_NONE; 129703dc76caSSudarsana Reddy Kalluru break; 129803dc76caSSudarsana Reddy Kalluru } 129903dc76caSSudarsana Reddy Kalluru } 1300cc875c2eSYuval Mintz 1301645874e5SSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG) 1302645874e5SSudarsana Reddy Kalluru memcpy(&link_params->eee, ¶ms->eee, 1303645874e5SSudarsana Reddy Kalluru sizeof(link_params->eee)); 1304645874e5SSudarsana Reddy Kalluru 1305cc875c2eSYuval Mintz rc = qed_mcp_set_link(hwfn, ptt, params->link_up); 1306cc875c2eSYuval Mintz 1307cc875c2eSYuval Mintz qed_ptt_release(hwfn, ptt); 1308cc875c2eSYuval Mintz 1309cc875c2eSYuval Mintz return rc; 1310cc875c2eSYuval Mintz } 1311cc875c2eSYuval Mintz 1312cc875c2eSYuval Mintz static int qed_get_port_type(u32 media_type) 1313cc875c2eSYuval Mintz { 1314cc875c2eSYuval Mintz int port_type; 1315cc875c2eSYuval Mintz 1316cc875c2eSYuval Mintz switch (media_type) { 1317cc875c2eSYuval Mintz case MEDIA_SFPP_10G_FIBER: 1318cc875c2eSYuval Mintz case MEDIA_SFP_1G_FIBER: 1319cc875c2eSYuval Mintz case MEDIA_XFP_FIBER: 1320b639f197SYuval Mintz case MEDIA_MODULE_FIBER: 1321cc875c2eSYuval Mintz case MEDIA_KR: 1322cc875c2eSYuval Mintz port_type = PORT_FIBRE; 1323cc875c2eSYuval Mintz break; 1324cc875c2eSYuval Mintz case MEDIA_DA_TWINAX: 1325cc875c2eSYuval Mintz port_type = PORT_DA; 1326cc875c2eSYuval Mintz break; 1327cc875c2eSYuval Mintz case MEDIA_BASE_T: 1328cc875c2eSYuval Mintz port_type = PORT_TP; 1329cc875c2eSYuval Mintz break; 1330cc875c2eSYuval Mintz case MEDIA_NOT_PRESENT: 1331cc875c2eSYuval Mintz port_type = PORT_NONE; 1332cc875c2eSYuval Mintz break; 1333cc875c2eSYuval Mintz case MEDIA_UNSPECIFIED: 1334cc875c2eSYuval Mintz default: 1335cc875c2eSYuval Mintz port_type = PORT_OTHER; 1336cc875c2eSYuval Mintz break; 1337cc875c2eSYuval Mintz } 1338cc875c2eSYuval Mintz return port_type; 1339cc875c2eSYuval Mintz } 1340cc875c2eSYuval Mintz 134114b84e86SArnd Bergmann static int qed_get_link_data(struct qed_hwfn *hwfn, 134214b84e86SArnd Bergmann struct qed_mcp_link_params *params, 134314b84e86SArnd Bergmann struct qed_mcp_link_state *link, 134414b84e86SArnd Bergmann struct qed_mcp_link_capabilities *link_caps) 134514b84e86SArnd Bergmann { 134614b84e86SArnd Bergmann void *p; 134714b84e86SArnd Bergmann 134814b84e86SArnd Bergmann if (!IS_PF(hwfn->cdev)) { 134914b84e86SArnd Bergmann qed_vf_get_link_params(hwfn, params); 135014b84e86SArnd Bergmann qed_vf_get_link_state(hwfn, link); 135114b84e86SArnd Bergmann qed_vf_get_link_caps(hwfn, link_caps); 135214b84e86SArnd Bergmann 135314b84e86SArnd Bergmann return 0; 135414b84e86SArnd Bergmann } 135514b84e86SArnd Bergmann 135614b84e86SArnd Bergmann p = qed_mcp_get_link_params(hwfn); 135714b84e86SArnd Bergmann if (!p) 135814b84e86SArnd Bergmann return -ENXIO; 135914b84e86SArnd Bergmann memcpy(params, p, sizeof(*params)); 136014b84e86SArnd Bergmann 136114b84e86SArnd Bergmann p = qed_mcp_get_link_state(hwfn); 136214b84e86SArnd Bergmann if (!p) 136314b84e86SArnd Bergmann return -ENXIO; 136414b84e86SArnd Bergmann memcpy(link, p, sizeof(*link)); 136514b84e86SArnd Bergmann 136614b84e86SArnd Bergmann p = qed_mcp_get_link_capabilities(hwfn); 136714b84e86SArnd Bergmann if (!p) 136814b84e86SArnd Bergmann return -ENXIO; 136914b84e86SArnd Bergmann memcpy(link_caps, p, sizeof(*link_caps)); 137014b84e86SArnd Bergmann 137114b84e86SArnd Bergmann return 0; 137214b84e86SArnd Bergmann } 137314b84e86SArnd Bergmann 1374cc875c2eSYuval Mintz static void qed_fill_link(struct qed_hwfn *hwfn, 1375cc875c2eSYuval Mintz struct qed_link_output *if_link) 1376cc875c2eSYuval Mintz { 1377cc875c2eSYuval Mintz struct qed_mcp_link_params params; 1378cc875c2eSYuval Mintz struct qed_mcp_link_state link; 1379cc875c2eSYuval Mintz struct qed_mcp_link_capabilities link_caps; 1380cc875c2eSYuval Mintz u32 media_type; 1381cc875c2eSYuval Mintz 1382cc875c2eSYuval Mintz memset(if_link, 0, sizeof(*if_link)); 1383cc875c2eSYuval Mintz 1384cc875c2eSYuval Mintz /* Prepare source inputs */ 138514b84e86SArnd Bergmann if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) { 138614b84e86SArnd Bergmann dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n"); 138714b84e86SArnd Bergmann return; 13881408cc1fSYuval Mintz } 1389cc875c2eSYuval Mintz 1390cc875c2eSYuval Mintz /* Set the link parameters to pass to protocol driver */ 1391cc875c2eSYuval Mintz if (link.link_up) 1392cc875c2eSYuval Mintz if_link->link_up = true; 1393cc875c2eSYuval Mintz 1394cc875c2eSYuval Mintz /* TODO - at the moment assume supported and advertised speed equal */ 1395054c67d1SSudarsana Reddy Kalluru if_link->supported_caps = QED_LM_FIBRE_BIT; 139634f9199cSsudarsana.kalluru@cavium.com if (link_caps.default_speed_autoneg) 1397054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Autoneg_BIT; 1398cc875c2eSYuval Mintz if (params.pause.autoneg || 1399cc875c2eSYuval Mintz (params.pause.forced_rx && params.pause.forced_tx)) 1400054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Asym_Pause_BIT; 1401cc875c2eSYuval Mintz if (params.pause.autoneg || params.pause.forced_rx || 1402cc875c2eSYuval Mintz params.pause.forced_tx) 1403054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_Pause_BIT; 1404cc875c2eSYuval Mintz 1405cc875c2eSYuval Mintz if_link->advertised_caps = if_link->supported_caps; 140634f9199cSsudarsana.kalluru@cavium.com if (params.speed.autoneg) 140734f9199cSsudarsana.kalluru@cavium.com if_link->advertised_caps |= QED_LM_Autoneg_BIT; 140834f9199cSsudarsana.kalluru@cavium.com else 140934f9199cSsudarsana.kalluru@cavium.com if_link->advertised_caps &= ~QED_LM_Autoneg_BIT; 1410cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1411cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1412054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT | 1413054c67d1SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT; 1414cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1415cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 1416054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT; 1417054c67d1SSudarsana Reddy Kalluru if (params.speed.advertised_speeds & 1418054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 1419054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT; 1420cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1421cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 1422054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT; 1423cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1424cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 1425054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT; 1426cc875c2eSYuval Mintz if (params.speed.advertised_speeds & 1427351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 1428054c67d1SSudarsana Reddy Kalluru if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT; 1429cc875c2eSYuval Mintz 1430cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1431cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1432054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_1000baseT_Half_BIT | 1433054c67d1SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT; 1434cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1435cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 1436054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT; 1437054c67d1SSudarsana Reddy Kalluru if (link_caps.speed_capabilities & 1438054c67d1SSudarsana Reddy Kalluru NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 1439054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT; 1440cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1441cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 1442054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT; 1443cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1444cc875c2eSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 1445054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT; 1446cc875c2eSYuval Mintz if (link_caps.speed_capabilities & 1447351a4dedSYuval Mintz NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 1448054c67d1SSudarsana Reddy Kalluru if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT; 1449cc875c2eSYuval Mintz 1450cc875c2eSYuval Mintz if (link.link_up) 1451cc875c2eSYuval Mintz if_link->speed = link.speed; 1452cc875c2eSYuval Mintz 1453cc875c2eSYuval Mintz /* TODO - fill duplex properly */ 1454cc875c2eSYuval Mintz if_link->duplex = DUPLEX_FULL; 1455cc875c2eSYuval Mintz qed_mcp_get_media_type(hwfn->cdev, &media_type); 1456cc875c2eSYuval Mintz if_link->port = qed_get_port_type(media_type); 1457cc875c2eSYuval Mintz 1458cc875c2eSYuval Mintz if_link->autoneg = params.speed.autoneg; 1459cc875c2eSYuval Mintz 1460cc875c2eSYuval Mintz if (params.pause.autoneg) 1461cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 1462cc875c2eSYuval Mintz if (params.pause.forced_rx) 1463cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE; 1464cc875c2eSYuval Mintz if (params.pause.forced_tx) 1465cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE; 1466cc875c2eSYuval Mintz 1467cc875c2eSYuval Mintz /* Link partner capabilities */ 1468054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD) 1469054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_1000baseT_Half_BIT; 1470054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD) 1471054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_1000baseT_Full_BIT; 1472054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G) 1473054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT; 1474054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_25G) 1475054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_25000baseKR_Full_BIT; 1476054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_40G) 1477054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_40000baseLR4_Full_BIT; 1478054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_50G) 1479054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_50000baseKR2_Full_BIT; 1480054c67d1SSudarsana Reddy Kalluru if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_100G) 1481054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_100000baseKR4_Full_BIT; 1482cc875c2eSYuval Mintz 1483cc875c2eSYuval Mintz if (link.an_complete) 1484054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Autoneg_BIT; 1485cc875c2eSYuval Mintz 1486cc875c2eSYuval Mintz if (link.partner_adv_pause) 1487054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Pause_BIT; 1488cc875c2eSYuval Mintz if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE || 1489cc875c2eSYuval Mintz link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE) 1490054c67d1SSudarsana Reddy Kalluru if_link->lp_caps |= QED_LM_Asym_Pause_BIT; 1491645874e5SSudarsana Reddy Kalluru 1492645874e5SSudarsana Reddy Kalluru if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) { 1493645874e5SSudarsana Reddy Kalluru if_link->eee_supported = false; 1494645874e5SSudarsana Reddy Kalluru } else { 1495645874e5SSudarsana Reddy Kalluru if_link->eee_supported = true; 1496645874e5SSudarsana Reddy Kalluru if_link->eee_active = link.eee_active; 1497645874e5SSudarsana Reddy Kalluru if_link->sup_caps = link_caps.eee_speed_caps; 1498645874e5SSudarsana Reddy Kalluru /* MFW clears adv_caps on eee disable; use configured value */ 1499645874e5SSudarsana Reddy Kalluru if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps : 1500645874e5SSudarsana Reddy Kalluru params.eee.adv_caps; 1501645874e5SSudarsana Reddy Kalluru if_link->eee.lp_adv_caps = link.eee_lp_adv_caps; 1502645874e5SSudarsana Reddy Kalluru if_link->eee.enable = params.eee.enable; 1503645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable; 1504645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer; 1505645874e5SSudarsana Reddy Kalluru } 1506cc875c2eSYuval Mintz } 1507cc875c2eSYuval Mintz 1508cc875c2eSYuval Mintz static void qed_get_current_link(struct qed_dev *cdev, 1509cc875c2eSYuval Mintz struct qed_link_output *if_link) 1510cc875c2eSYuval Mintz { 151136558c3dSYuval Mintz int i; 151236558c3dSYuval Mintz 1513cc875c2eSYuval Mintz qed_fill_link(&cdev->hwfns[0], if_link); 151436558c3dSYuval Mintz 151536558c3dSYuval Mintz for_each_hwfn(cdev, i) 151636558c3dSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 1517cc875c2eSYuval Mintz } 1518cc875c2eSYuval Mintz 1519cc875c2eSYuval Mintz void qed_link_update(struct qed_hwfn *hwfn) 1520cc875c2eSYuval Mintz { 1521cc875c2eSYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 1522cc875c2eSYuval Mintz struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 1523cc875c2eSYuval Mintz struct qed_link_output if_link; 1524cc875c2eSYuval Mintz 1525cc875c2eSYuval Mintz qed_fill_link(hwfn, &if_link); 152636558c3dSYuval Mintz qed_inform_vf_link_state(hwfn); 1527cc875c2eSYuval Mintz 1528cc875c2eSYuval Mintz if (IS_LEAD_HWFN(hwfn) && cookie) 1529cc875c2eSYuval Mintz op->link_update(cookie, &if_link); 1530cc875c2eSYuval Mintz } 1531cc875c2eSYuval Mintz 1532fe56b9e6SYuval Mintz static int qed_drain(struct qed_dev *cdev) 1533fe56b9e6SYuval Mintz { 1534fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 1535fe56b9e6SYuval Mintz struct qed_ptt *ptt; 1536fe56b9e6SYuval Mintz int i, rc; 1537fe56b9e6SYuval Mintz 15381408cc1fSYuval Mintz if (IS_VF(cdev)) 15391408cc1fSYuval Mintz return 0; 15401408cc1fSYuval Mintz 1541fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1542fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 1543fe56b9e6SYuval Mintz ptt = qed_ptt_acquire(hwfn); 1544fe56b9e6SYuval Mintz if (!ptt) { 1545fe56b9e6SYuval Mintz DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n"); 1546fe56b9e6SYuval Mintz return -EBUSY; 1547fe56b9e6SYuval Mintz } 1548fe56b9e6SYuval Mintz rc = qed_mcp_drain(hwfn, ptt); 1549fe56b9e6SYuval Mintz if (rc) 1550fe56b9e6SYuval Mintz return rc; 1551fe56b9e6SYuval Mintz qed_ptt_release(hwfn, ptt); 1552fe56b9e6SYuval Mintz } 1553fe56b9e6SYuval Mintz 1554fe56b9e6SYuval Mintz return 0; 1555fe56b9e6SYuval Mintz } 1556fe56b9e6SYuval Mintz 15573a69cae8SSudarsana Reddy Kalluru static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev, 15583a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att *nvm_image, 15593a69cae8SSudarsana Reddy Kalluru u32 *crc) 15603a69cae8SSudarsana Reddy Kalluru { 15613a69cae8SSudarsana Reddy Kalluru u8 *buf = NULL; 15623a69cae8SSudarsana Reddy Kalluru int rc, j; 15633a69cae8SSudarsana Reddy Kalluru u32 val; 15643a69cae8SSudarsana Reddy Kalluru 15653a69cae8SSudarsana Reddy Kalluru /* Allocate a buffer for holding the nvram image */ 15663a69cae8SSudarsana Reddy Kalluru buf = kzalloc(nvm_image->length, GFP_KERNEL); 15673a69cae8SSudarsana Reddy Kalluru if (!buf) 15683a69cae8SSudarsana Reddy Kalluru return -ENOMEM; 15693a69cae8SSudarsana Reddy Kalluru 15703a69cae8SSudarsana Reddy Kalluru /* Read image into buffer */ 15713a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr, 15723a69cae8SSudarsana Reddy Kalluru buf, nvm_image->length); 15733a69cae8SSudarsana Reddy Kalluru if (rc) { 15743a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading image from nvm\n"); 15753a69cae8SSudarsana Reddy Kalluru goto out; 15763a69cae8SSudarsana Reddy Kalluru } 15773a69cae8SSudarsana Reddy Kalluru 15783a69cae8SSudarsana Reddy Kalluru /* Convert the buffer into big-endian format (excluding the 15793a69cae8SSudarsana Reddy Kalluru * closing 4 bytes of CRC). 15803a69cae8SSudarsana Reddy Kalluru */ 15813a69cae8SSudarsana Reddy Kalluru for (j = 0; j < nvm_image->length - 4; j += 4) { 15823a69cae8SSudarsana Reddy Kalluru val = cpu_to_be32(*(u32 *)&buf[j]); 15833a69cae8SSudarsana Reddy Kalluru *(u32 *)&buf[j] = val; 15843a69cae8SSudarsana Reddy Kalluru } 15853a69cae8SSudarsana Reddy Kalluru 15863a69cae8SSudarsana Reddy Kalluru /* Calc CRC for the "actual" image buffer, i.e. not including 15873a69cae8SSudarsana Reddy Kalluru * the last 4 CRC bytes. 15883a69cae8SSudarsana Reddy Kalluru */ 15893a69cae8SSudarsana Reddy Kalluru *crc = (~cpu_to_be32(crc32(0xffffffff, buf, nvm_image->length - 4))); 15903a69cae8SSudarsana Reddy Kalluru 15913a69cae8SSudarsana Reddy Kalluru out: 15923a69cae8SSudarsana Reddy Kalluru kfree(buf); 15933a69cae8SSudarsana Reddy Kalluru 15943a69cae8SSudarsana Reddy Kalluru return rc; 15953a69cae8SSudarsana Reddy Kalluru } 15963a69cae8SSudarsana Reddy Kalluru 15973a69cae8SSudarsana Reddy Kalluru /* Binary file format - 15983a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 15993a69cae8SSudarsana Reddy Kalluru * 0B | 0x4 [command index] | 16003a69cae8SSudarsana Reddy Kalluru * 4B | image_type | Options | Number of register settings | 16013a69cae8SSudarsana Reddy Kalluru * 8B | Value | 16023a69cae8SSudarsana Reddy Kalluru * 12B | Mask | 16033a69cae8SSudarsana Reddy Kalluru * 16B | Offset | 16043a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 16053a69cae8SSudarsana Reddy Kalluru * There can be several Value-Mask-Offset sets as specified by 'Number of...'. 16063a69cae8SSudarsana Reddy Kalluru * Options - 0'b - Calculate & Update CRC for image 16073a69cae8SSudarsana Reddy Kalluru */ 16083a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data, 16093a69cae8SSudarsana Reddy Kalluru bool *check_resp) 16103a69cae8SSudarsana Reddy Kalluru { 16113a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att nvm_image; 16123a69cae8SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn; 16133a69cae8SSudarsana Reddy Kalluru bool is_crc = false; 16143a69cae8SSudarsana Reddy Kalluru u32 image_type; 16153a69cae8SSudarsana Reddy Kalluru int rc = 0, i; 16163a69cae8SSudarsana Reddy Kalluru u16 len; 16173a69cae8SSudarsana Reddy Kalluru 16183a69cae8SSudarsana Reddy Kalluru *data += 4; 16193a69cae8SSudarsana Reddy Kalluru image_type = **data; 16203a69cae8SSudarsana Reddy Kalluru p_hwfn = QED_LEADING_HWFN(cdev); 16213a69cae8SSudarsana Reddy Kalluru for (i = 0; i < p_hwfn->nvm_info.num_images; i++) 16223a69cae8SSudarsana Reddy Kalluru if (image_type == p_hwfn->nvm_info.image_att[i].image_type) 16233a69cae8SSudarsana Reddy Kalluru break; 16243a69cae8SSudarsana Reddy Kalluru if (i == p_hwfn->nvm_info.num_images) { 16253a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find nvram image of type %08x\n", 16263a69cae8SSudarsana Reddy Kalluru image_type); 16273a69cae8SSudarsana Reddy Kalluru return -ENOENT; 16283a69cae8SSudarsana Reddy Kalluru } 16293a69cae8SSudarsana Reddy Kalluru 16303a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr; 16313a69cae8SSudarsana Reddy Kalluru nvm_image.length = p_hwfn->nvm_info.image_att[i].len; 16323a69cae8SSudarsana Reddy Kalluru 16333a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 16343a69cae8SSudarsana Reddy Kalluru "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n", 16353a69cae8SSudarsana Reddy Kalluru **data, image_type, nvm_image.start_addr, 16363a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 1); 16373a69cae8SSudarsana Reddy Kalluru (*data)++; 16383a69cae8SSudarsana Reddy Kalluru is_crc = !!(**data & BIT(0)); 16393a69cae8SSudarsana Reddy Kalluru (*data)++; 16403a69cae8SSudarsana Reddy Kalluru len = *((u16 *)*data); 16413a69cae8SSudarsana Reddy Kalluru *data += 2; 16423a69cae8SSudarsana Reddy Kalluru if (is_crc) { 16433a69cae8SSudarsana Reddy Kalluru u32 crc = 0; 16443a69cae8SSudarsana Reddy Kalluru 16453a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc); 16463a69cae8SSudarsana Reddy Kalluru if (rc) { 16473a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc); 16483a69cae8SSudarsana Reddy Kalluru goto exit; 16493a69cae8SSudarsana Reddy Kalluru } 16503a69cae8SSudarsana Reddy Kalluru 16513a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM, 16523a69cae8SSudarsana Reddy Kalluru (nvm_image.start_addr + 16533a69cae8SSudarsana Reddy Kalluru nvm_image.length - 4), (u8 *)&crc, 4); 16543a69cae8SSudarsana Reddy Kalluru if (rc) 16553a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x, rc = %d\n", 16563a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 4, rc); 16573a69cae8SSudarsana Reddy Kalluru goto exit; 16583a69cae8SSudarsana Reddy Kalluru } 16593a69cae8SSudarsana Reddy Kalluru 16603a69cae8SSudarsana Reddy Kalluru /* Iterate over the values for setting */ 16613a69cae8SSudarsana Reddy Kalluru while (len) { 16623a69cae8SSudarsana Reddy Kalluru u32 offset, mask, value, cur_value; 16633a69cae8SSudarsana Reddy Kalluru u8 buf[4]; 16643a69cae8SSudarsana Reddy Kalluru 16653a69cae8SSudarsana Reddy Kalluru value = *((u32 *)*data); 16663a69cae8SSudarsana Reddy Kalluru *data += 4; 16673a69cae8SSudarsana Reddy Kalluru mask = *((u32 *)*data); 16683a69cae8SSudarsana Reddy Kalluru *data += 4; 16693a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)*data); 16703a69cae8SSudarsana Reddy Kalluru *data += 4; 16713a69cae8SSudarsana Reddy Kalluru 16723a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf, 16733a69cae8SSudarsana Reddy Kalluru 4); 16743a69cae8SSudarsana Reddy Kalluru if (rc) { 16753a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading from %08x\n", 16763a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset); 16773a69cae8SSudarsana Reddy Kalluru goto exit; 16783a69cae8SSudarsana Reddy Kalluru } 16793a69cae8SSudarsana Reddy Kalluru 16803a69cae8SSudarsana Reddy Kalluru cur_value = le32_to_cpu(*((__le32 *)buf)); 16813a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 16823a69cae8SSudarsana Reddy Kalluru "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n", 16833a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, cur_value, 16843a69cae8SSudarsana Reddy Kalluru (cur_value & ~mask) | (value & mask), value, mask); 16853a69cae8SSudarsana Reddy Kalluru value = (value & mask) | (cur_value & ~mask); 16863a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM, 16873a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, 16883a69cae8SSudarsana Reddy Kalluru (u8 *)&value, 4); 16893a69cae8SSudarsana Reddy Kalluru if (rc) { 16903a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x\n", 16913a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset); 16923a69cae8SSudarsana Reddy Kalluru goto exit; 16933a69cae8SSudarsana Reddy Kalluru } 16943a69cae8SSudarsana Reddy Kalluru 16953a69cae8SSudarsana Reddy Kalluru len--; 16963a69cae8SSudarsana Reddy Kalluru } 16973a69cae8SSudarsana Reddy Kalluru exit: 16983a69cae8SSudarsana Reddy Kalluru return rc; 16993a69cae8SSudarsana Reddy Kalluru } 17003a69cae8SSudarsana Reddy Kalluru 17013a69cae8SSudarsana Reddy Kalluru /* Binary file format - 17023a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 17033a69cae8SSudarsana Reddy Kalluru * 0B | 0x3 [command index] | 17043a69cae8SSudarsana Reddy Kalluru * 4B | b'0: check_response? | b'1-31 reserved | 17053a69cae8SSudarsana Reddy Kalluru * 8B | File-type | reserved | 17063a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 17073a69cae8SSudarsana Reddy Kalluru * Start a new file of the provided type 17083a69cae8SSudarsana Reddy Kalluru */ 17093a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_start(struct qed_dev *cdev, 17103a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp) 17113a69cae8SSudarsana Reddy Kalluru { 17123a69cae8SSudarsana Reddy Kalluru int rc; 17133a69cae8SSudarsana Reddy Kalluru 17143a69cae8SSudarsana Reddy Kalluru *data += 4; 17153a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0)); 17163a69cae8SSudarsana Reddy Kalluru *data += 4; 17173a69cae8SSudarsana Reddy Kalluru 17183a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 17193a69cae8SSudarsana Reddy Kalluru "About to start a new file of type %02x\n", **data); 17203a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_put_file_begin(cdev, **data); 17213a69cae8SSudarsana Reddy Kalluru *data += 4; 17223a69cae8SSudarsana Reddy Kalluru 17233a69cae8SSudarsana Reddy Kalluru return rc; 17243a69cae8SSudarsana Reddy Kalluru } 17253a69cae8SSudarsana Reddy Kalluru 17263a69cae8SSudarsana Reddy Kalluru /* Binary file format - 17273a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 17283a69cae8SSudarsana Reddy Kalluru * 0B | 0x2 [command index] | 17293a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes | 17303a69cae8SSudarsana Reddy Kalluru * 8B | b'0: check_response? | b'1-31 reserved | 17313a69cae8SSudarsana Reddy Kalluru * 12B | Offset in bytes | 17323a69cae8SSudarsana Reddy Kalluru * 16B | Data ... | 17333a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 17343a69cae8SSudarsana Reddy Kalluru * Write data as part of a file that was previously started. Data should be 17353a69cae8SSudarsana Reddy Kalluru * of length equal to that provided in the message 17363a69cae8SSudarsana Reddy Kalluru */ 17373a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_data(struct qed_dev *cdev, 17383a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp) 17393a69cae8SSudarsana Reddy Kalluru { 17403a69cae8SSudarsana Reddy Kalluru u32 offset, len; 17413a69cae8SSudarsana Reddy Kalluru int rc; 17423a69cae8SSudarsana Reddy Kalluru 17433a69cae8SSudarsana Reddy Kalluru *data += 4; 17443a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data)); 17453a69cae8SSudarsana Reddy Kalluru *data += 4; 17463a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0)); 17473a69cae8SSudarsana Reddy Kalluru *data += 4; 17483a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)(*data)); 17493a69cae8SSudarsana Reddy Kalluru *data += 4; 17503a69cae8SSudarsana Reddy Kalluru 17513a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 17523a69cae8SSudarsana Reddy Kalluru "About to write File-data: %08x bytes to offset %08x\n", 17533a69cae8SSudarsana Reddy Kalluru len, offset); 17543a69cae8SSudarsana Reddy Kalluru 17553a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset, 17563a69cae8SSudarsana Reddy Kalluru (char *)(*data), len); 17573a69cae8SSudarsana Reddy Kalluru *data += len; 17583a69cae8SSudarsana Reddy Kalluru 17593a69cae8SSudarsana Reddy Kalluru return rc; 17603a69cae8SSudarsana Reddy Kalluru } 17613a69cae8SSudarsana Reddy Kalluru 17623a69cae8SSudarsana Reddy Kalluru /* Binary file format [General header] - 17633a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 17643a69cae8SSudarsana Reddy Kalluru * 0B | QED_NVM_SIGNATURE | 17653a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes | 17663a69cae8SSudarsana Reddy Kalluru * 8B | Highest command in this batchfile | Reserved | 17673a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 17683a69cae8SSudarsana Reddy Kalluru */ 17693a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_validate(struct qed_dev *cdev, 17703a69cae8SSudarsana Reddy Kalluru const struct firmware *image, 17713a69cae8SSudarsana Reddy Kalluru const u8 **data) 17723a69cae8SSudarsana Reddy Kalluru { 17733a69cae8SSudarsana Reddy Kalluru u32 signature, len; 17743a69cae8SSudarsana Reddy Kalluru 17753a69cae8SSudarsana Reddy Kalluru /* Check minimum size */ 17763a69cae8SSudarsana Reddy Kalluru if (image->size < 12) { 17773a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size); 17783a69cae8SSudarsana Reddy Kalluru return -EINVAL; 17793a69cae8SSudarsana Reddy Kalluru } 17803a69cae8SSudarsana Reddy Kalluru 17813a69cae8SSudarsana Reddy Kalluru /* Check signature */ 17823a69cae8SSudarsana Reddy Kalluru signature = *((u32 *)(*data)); 17833a69cae8SSudarsana Reddy Kalluru if (signature != QED_NVM_SIGNATURE) { 17843a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Wrong signature '%08x'\n", signature); 17853a69cae8SSudarsana Reddy Kalluru return -EINVAL; 17863a69cae8SSudarsana Reddy Kalluru } 17873a69cae8SSudarsana Reddy Kalluru 17883a69cae8SSudarsana Reddy Kalluru *data += 4; 17893a69cae8SSudarsana Reddy Kalluru /* Validate internal size equals the image-size */ 17903a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data)); 17913a69cae8SSudarsana Reddy Kalluru if (len != image->size) { 17923a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n", 17933a69cae8SSudarsana Reddy Kalluru len, (u32)image->size); 17943a69cae8SSudarsana Reddy Kalluru return -EINVAL; 17953a69cae8SSudarsana Reddy Kalluru } 17963a69cae8SSudarsana Reddy Kalluru 17973a69cae8SSudarsana Reddy Kalluru *data += 4; 17983a69cae8SSudarsana Reddy Kalluru /* Make sure driver familiar with all commands necessary for this */ 17993a69cae8SSudarsana Reddy Kalluru if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) { 18003a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n", 18013a69cae8SSudarsana Reddy Kalluru *((u16 *)(*data))); 18023a69cae8SSudarsana Reddy Kalluru return -EINVAL; 18033a69cae8SSudarsana Reddy Kalluru } 18043a69cae8SSudarsana Reddy Kalluru 18053a69cae8SSudarsana Reddy Kalluru *data += 4; 18063a69cae8SSudarsana Reddy Kalluru 18073a69cae8SSudarsana Reddy Kalluru return 0; 18083a69cae8SSudarsana Reddy Kalluru } 18093a69cae8SSudarsana Reddy Kalluru 18103a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash(struct qed_dev *cdev, const char *name) 18113a69cae8SSudarsana Reddy Kalluru { 18123a69cae8SSudarsana Reddy Kalluru const struct firmware *image; 18133a69cae8SSudarsana Reddy Kalluru const u8 *data, *data_end; 18143a69cae8SSudarsana Reddy Kalluru u32 cmd_type; 18153a69cae8SSudarsana Reddy Kalluru int rc; 18163a69cae8SSudarsana Reddy Kalluru 18173a69cae8SSudarsana Reddy Kalluru rc = request_firmware(&image, name, &cdev->pdev->dev); 18183a69cae8SSudarsana Reddy Kalluru if (rc) { 18193a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find '%s'\n", name); 18203a69cae8SSudarsana Reddy Kalluru return rc; 18213a69cae8SSudarsana Reddy Kalluru } 18223a69cae8SSudarsana Reddy Kalluru 18233a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 18243a69cae8SSudarsana Reddy Kalluru "Flashing '%s' - firmware's data at %p, size is %08x\n", 18253a69cae8SSudarsana Reddy Kalluru name, image->data, (u32)image->size); 18263a69cae8SSudarsana Reddy Kalluru data = image->data; 18273a69cae8SSudarsana Reddy Kalluru data_end = data + image->size; 18283a69cae8SSudarsana Reddy Kalluru 18293a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_validate(cdev, image, &data); 18303a69cae8SSudarsana Reddy Kalluru if (rc) 18313a69cae8SSudarsana Reddy Kalluru goto exit; 18323a69cae8SSudarsana Reddy Kalluru 18333a69cae8SSudarsana Reddy Kalluru while (data < data_end) { 18343a69cae8SSudarsana Reddy Kalluru bool check_resp = false; 18353a69cae8SSudarsana Reddy Kalluru 18363a69cae8SSudarsana Reddy Kalluru /* Parse the actual command */ 18373a69cae8SSudarsana Reddy Kalluru cmd_type = *((u32 *)data); 18383a69cae8SSudarsana Reddy Kalluru switch (cmd_type) { 18393a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_DATA: 18403a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_data(cdev, &data, 18413a69cae8SSudarsana Reddy Kalluru &check_resp); 18423a69cae8SSudarsana Reddy Kalluru break; 18433a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_START: 18443a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_start(cdev, &data, 18453a69cae8SSudarsana Reddy Kalluru &check_resp); 18463a69cae8SSudarsana Reddy Kalluru break; 18473a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CHANGE: 18483a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access(cdev, &data, 18493a69cae8SSudarsana Reddy Kalluru &check_resp); 18503a69cae8SSudarsana Reddy Kalluru break; 18513a69cae8SSudarsana Reddy Kalluru default: 18523a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Unknown command %08x\n", cmd_type); 18533a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 18543a69cae8SSudarsana Reddy Kalluru goto exit; 18553a69cae8SSudarsana Reddy Kalluru } 18563a69cae8SSudarsana Reddy Kalluru 18573a69cae8SSudarsana Reddy Kalluru if (rc) { 18583a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Command %08x failed\n", cmd_type); 18593a69cae8SSudarsana Reddy Kalluru goto exit; 18603a69cae8SSudarsana Reddy Kalluru } 18613a69cae8SSudarsana Reddy Kalluru 18623a69cae8SSudarsana Reddy Kalluru /* Check response if needed */ 18633a69cae8SSudarsana Reddy Kalluru if (check_resp) { 18643a69cae8SSudarsana Reddy Kalluru u32 mcp_response = 0; 18653a69cae8SSudarsana Reddy Kalluru 18663a69cae8SSudarsana Reddy Kalluru if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) { 18673a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed getting MCP response\n"); 18683a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 18693a69cae8SSudarsana Reddy Kalluru goto exit; 18703a69cae8SSudarsana Reddy Kalluru } 18713a69cae8SSudarsana Reddy Kalluru 18723a69cae8SSudarsana Reddy Kalluru switch (mcp_response & FW_MSG_CODE_MASK) { 18733a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_OK: 18743a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_OK: 18753a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK: 18763a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_PHY_OK: 18773a69cae8SSudarsana Reddy Kalluru break; 18783a69cae8SSudarsana Reddy Kalluru default: 18793a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "MFW returns error: %08x\n", 18803a69cae8SSudarsana Reddy Kalluru mcp_response); 18813a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 18823a69cae8SSudarsana Reddy Kalluru goto exit; 18833a69cae8SSudarsana Reddy Kalluru } 18843a69cae8SSudarsana Reddy Kalluru } 18853a69cae8SSudarsana Reddy Kalluru } 18863a69cae8SSudarsana Reddy Kalluru 18873a69cae8SSudarsana Reddy Kalluru exit: 18883a69cae8SSudarsana Reddy Kalluru release_firmware(image); 18893a69cae8SSudarsana Reddy Kalluru 18903a69cae8SSudarsana Reddy Kalluru return rc; 18913a69cae8SSudarsana Reddy Kalluru } 18923a69cae8SSudarsana Reddy Kalluru 189320675b37SMintz, Yuval static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type, 189420675b37SMintz, Yuval u8 *buf, u16 len) 189520675b37SMintz, Yuval { 189620675b37SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 189720675b37SMintz, Yuval struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 189820675b37SMintz, Yuval int rc; 189920675b37SMintz, Yuval 190020675b37SMintz, Yuval if (!ptt) 190120675b37SMintz, Yuval return -EAGAIN; 190220675b37SMintz, Yuval 190320675b37SMintz, Yuval rc = qed_mcp_get_nvm_image(hwfn, ptt, type, buf, len); 190420675b37SMintz, Yuval qed_ptt_release(hwfn, ptt); 190520675b37SMintz, Yuval return rc; 190620675b37SMintz, Yuval } 190720675b37SMintz, Yuval 1908722003acSSudarsana Reddy Kalluru static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, 1909477f2d14SRahul Verma void *handle) 1910722003acSSudarsana Reddy Kalluru { 1911477f2d14SRahul Verma return qed_set_queue_coalesce(rx_coal, tx_coal, handle); 1912722003acSSudarsana Reddy Kalluru } 1913722003acSSudarsana Reddy Kalluru 191491420b83SSudarsana Kalluru static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) 191591420b83SSudarsana Kalluru { 191691420b83SSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 191791420b83SSudarsana Kalluru struct qed_ptt *ptt; 191891420b83SSudarsana Kalluru int status = 0; 191991420b83SSudarsana Kalluru 192091420b83SSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 192191420b83SSudarsana Kalluru if (!ptt) 192291420b83SSudarsana Kalluru return -EAGAIN; 192391420b83SSudarsana Kalluru 192491420b83SSudarsana Kalluru status = qed_mcp_set_led(hwfn, ptt, mode); 192591420b83SSudarsana Kalluru 192691420b83SSudarsana Kalluru qed_ptt_release(hwfn, ptt); 192791420b83SSudarsana Kalluru 192891420b83SSudarsana Kalluru return status; 192991420b83SSudarsana Kalluru } 193091420b83SSudarsana Kalluru 193114d39648SMintz, Yuval static int qed_update_wol(struct qed_dev *cdev, bool enabled) 193214d39648SMintz, Yuval { 193314d39648SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 193414d39648SMintz, Yuval struct qed_ptt *ptt; 193514d39648SMintz, Yuval int rc = 0; 193614d39648SMintz, Yuval 193714d39648SMintz, Yuval if (IS_VF(cdev)) 193814d39648SMintz, Yuval return 0; 193914d39648SMintz, Yuval 194014d39648SMintz, Yuval ptt = qed_ptt_acquire(hwfn); 194114d39648SMintz, Yuval if (!ptt) 194214d39648SMintz, Yuval return -EAGAIN; 194314d39648SMintz, Yuval 194414d39648SMintz, Yuval rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED 194514d39648SMintz, Yuval : QED_OV_WOL_DISABLED); 194614d39648SMintz, Yuval if (rc) 194714d39648SMintz, Yuval goto out; 194814d39648SMintz, Yuval rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 194914d39648SMintz, Yuval 195014d39648SMintz, Yuval out: 195114d39648SMintz, Yuval qed_ptt_release(hwfn, ptt); 195214d39648SMintz, Yuval return rc; 195314d39648SMintz, Yuval } 195414d39648SMintz, Yuval 19550fefbfbaSSudarsana Kalluru static int qed_update_drv_state(struct qed_dev *cdev, bool active) 19560fefbfbaSSudarsana Kalluru { 19570fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 19580fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 19590fefbfbaSSudarsana Kalluru int status = 0; 19600fefbfbaSSudarsana Kalluru 19610fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 19620fefbfbaSSudarsana Kalluru return 0; 19630fefbfbaSSudarsana Kalluru 19640fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 19650fefbfbaSSudarsana Kalluru if (!ptt) 19660fefbfbaSSudarsana Kalluru return -EAGAIN; 19670fefbfbaSSudarsana Kalluru 19680fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ? 19690fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_ACTIVE : 19700fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_DISABLED); 19710fefbfbaSSudarsana Kalluru 19720fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 19730fefbfbaSSudarsana Kalluru 19740fefbfbaSSudarsana Kalluru return status; 19750fefbfbaSSudarsana Kalluru } 19760fefbfbaSSudarsana Kalluru 19770fefbfbaSSudarsana Kalluru static int qed_update_mac(struct qed_dev *cdev, u8 *mac) 19780fefbfbaSSudarsana Kalluru { 19790fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 19800fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 19810fefbfbaSSudarsana Kalluru int status = 0; 19820fefbfbaSSudarsana Kalluru 19830fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 19840fefbfbaSSudarsana Kalluru return 0; 19850fefbfbaSSudarsana Kalluru 19860fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 19870fefbfbaSSudarsana Kalluru if (!ptt) 19880fefbfbaSSudarsana Kalluru return -EAGAIN; 19890fefbfbaSSudarsana Kalluru 19900fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mac(hwfn, ptt, mac); 19910fefbfbaSSudarsana Kalluru if (status) 19920fefbfbaSSudarsana Kalluru goto out; 19930fefbfbaSSudarsana Kalluru 19940fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 19950fefbfbaSSudarsana Kalluru 19960fefbfbaSSudarsana Kalluru out: 19970fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 19980fefbfbaSSudarsana Kalluru return status; 19990fefbfbaSSudarsana Kalluru } 20000fefbfbaSSudarsana Kalluru 20010fefbfbaSSudarsana Kalluru static int qed_update_mtu(struct qed_dev *cdev, u16 mtu) 20020fefbfbaSSudarsana Kalluru { 20030fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 20040fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 20050fefbfbaSSudarsana Kalluru int status = 0; 20060fefbfbaSSudarsana Kalluru 20070fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 20080fefbfbaSSudarsana Kalluru return 0; 20090fefbfbaSSudarsana Kalluru 20100fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 20110fefbfbaSSudarsana Kalluru if (!ptt) 20120fefbfbaSSudarsana Kalluru return -EAGAIN; 20130fefbfbaSSudarsana Kalluru 20140fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu); 20150fefbfbaSSudarsana Kalluru if (status) 20160fefbfbaSSudarsana Kalluru goto out; 20170fefbfbaSSudarsana Kalluru 20180fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 20190fefbfbaSSudarsana Kalluru 20200fefbfbaSSudarsana Kalluru out: 20210fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 20220fefbfbaSSudarsana Kalluru return status; 20230fefbfbaSSudarsana Kalluru } 20240fefbfbaSSudarsana Kalluru 20258c93beafSYuval Mintz static struct qed_selftest_ops qed_selftest_ops_pass = { 202603dc76caSSudarsana Reddy Kalluru .selftest_memory = &qed_selftest_memory, 202703dc76caSSudarsana Reddy Kalluru .selftest_interrupt = &qed_selftest_interrupt, 202803dc76caSSudarsana Reddy Kalluru .selftest_register = &qed_selftest_register, 202903dc76caSSudarsana Reddy Kalluru .selftest_clock = &qed_selftest_clock, 20307a4b21b7SMintz, Yuval .selftest_nvram = &qed_selftest_nvram, 203103dc76caSSudarsana Reddy Kalluru }; 203203dc76caSSudarsana Reddy Kalluru 2033fe56b9e6SYuval Mintz const struct qed_common_ops qed_common_ops_pass = { 203403dc76caSSudarsana Reddy Kalluru .selftest = &qed_selftest_ops_pass, 2035fe56b9e6SYuval Mintz .probe = &qed_probe, 2036fe56b9e6SYuval Mintz .remove = &qed_remove, 2037fe56b9e6SYuval Mintz .set_power_state = &qed_set_power_state, 2038712c3cbfSMintz, Yuval .set_name = &qed_set_name, 2039fe56b9e6SYuval Mintz .update_pf_params = &qed_update_pf_params, 2040fe56b9e6SYuval Mintz .slowpath_start = &qed_slowpath_start, 2041fe56b9e6SYuval Mintz .slowpath_stop = &qed_slowpath_stop, 2042fe56b9e6SYuval Mintz .set_fp_int = &qed_set_int_fp, 2043fe56b9e6SYuval Mintz .get_fp_int = &qed_get_int_fp, 2044fe56b9e6SYuval Mintz .sb_init = &qed_sb_init, 2045fe56b9e6SYuval Mintz .sb_release = &qed_sb_release, 2046fe56b9e6SYuval Mintz .simd_handler_config = &qed_simd_handler_config, 2047fe56b9e6SYuval Mintz .simd_handler_clean = &qed_simd_handler_clean, 20481e128c81SArun Easi .dbg_grc = &qed_dbg_grc, 20491e128c81SArun Easi .dbg_grc_size = &qed_dbg_grc_size, 2050fe7cd2bfSYuval Mintz .can_link_change = &qed_can_link_change, 2051cc875c2eSYuval Mintz .set_link = &qed_set_link, 2052cc875c2eSYuval Mintz .get_link = &qed_get_current_link, 2053fe56b9e6SYuval Mintz .drain = &qed_drain, 2054fe56b9e6SYuval Mintz .update_msglvl = &qed_init_dp, 2055e0971c83STomer Tayar .dbg_all_data = &qed_dbg_all_data, 2056e0971c83STomer Tayar .dbg_all_data_size = &qed_dbg_all_data_size, 2057fe56b9e6SYuval Mintz .chain_alloc = &qed_chain_alloc, 2058fe56b9e6SYuval Mintz .chain_free = &qed_chain_free, 20593a69cae8SSudarsana Reddy Kalluru .nvm_flash = &qed_nvm_flash, 206020675b37SMintz, Yuval .nvm_get_image = &qed_nvm_get_image, 2061722003acSSudarsana Reddy Kalluru .set_coalesce = &qed_set_coalesce, 206291420b83SSudarsana Kalluru .set_led = &qed_set_led, 20630fefbfbaSSudarsana Kalluru .update_drv_state = &qed_update_drv_state, 20640fefbfbaSSudarsana Kalluru .update_mac = &qed_update_mac, 20650fefbfbaSSudarsana Kalluru .update_mtu = &qed_update_mtu, 206614d39648SMintz, Yuval .update_wol = &qed_update_wol, 2067fe56b9e6SYuval Mintz }; 20686c754246SSudarsana Reddy Kalluru 20696c754246SSudarsana Reddy Kalluru void qed_get_protocol_stats(struct qed_dev *cdev, 20706c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type type, 20716c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats *stats) 20726c754246SSudarsana Reddy Kalluru { 20736c754246SSudarsana Reddy Kalluru struct qed_eth_stats eth_stats; 20746c754246SSudarsana Reddy Kalluru 20756c754246SSudarsana Reddy Kalluru memset(stats, 0, sizeof(*stats)); 20766c754246SSudarsana Reddy Kalluru 20776c754246SSudarsana Reddy Kalluru switch (type) { 20786c754246SSudarsana Reddy Kalluru case QED_MCP_LAN_STATS: 20796c754246SSudarsana Reddy Kalluru qed_get_vport_stats(cdev, ð_stats); 20809c79ddaaSMintz, Yuval stats->lan_stats.ucast_rx_pkts = 20819c79ddaaSMintz, Yuval eth_stats.common.rx_ucast_pkts; 20829c79ddaaSMintz, Yuval stats->lan_stats.ucast_tx_pkts = 20839c79ddaaSMintz, Yuval eth_stats.common.tx_ucast_pkts; 20846c754246SSudarsana Reddy Kalluru stats->lan_stats.fcs_err = -1; 20856c754246SSudarsana Reddy Kalluru break; 20861e128c81SArun Easi case QED_MCP_FCOE_STATS: 20871e128c81SArun Easi qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats); 20881e128c81SArun Easi break; 20892f2b2614SMintz, Yuval case QED_MCP_ISCSI_STATS: 20902f2b2614SMintz, Yuval qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); 20912f2b2614SMintz, Yuval break; 20926c754246SSudarsana Reddy Kalluru default: 2093512c7840SMintz, Yuval DP_VERBOSE(cdev, QED_MSG_SP, 2094512c7840SMintz, Yuval "Invalid protocol type = %d\n", type); 20956c754246SSudarsana Reddy Kalluru return; 20966c754246SSudarsana Reddy Kalluru } 20976c754246SSudarsana Reddy Kalluru } 2098