11f4d4ed6SAlexander Lobakin // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2fe56b9e6SYuval Mintz /* QLogic qed NIC Driver 3e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 4663eacd8SAlexander Lobakin * Copyright (c) 2019-2020 Marvell International Ltd. 5fe56b9e6SYuval Mintz */ 6fe56b9e6SYuval Mintz 7fe56b9e6SYuval Mintz #include <linux/stddef.h> 8fe56b9e6SYuval Mintz #include <linux/pci.h> 9fe56b9e6SYuval Mintz #include <linux/kernel.h> 10fe56b9e6SYuval Mintz #include <linux/slab.h> 11fe56b9e6SYuval Mintz #include <linux/delay.h> 12fe56b9e6SYuval Mintz #include <asm/byteorder.h> 13fe56b9e6SYuval Mintz #include <linux/dma-mapping.h> 14fe56b9e6SYuval Mintz #include <linux/string.h> 15fe56b9e6SYuval Mintz #include <linux/module.h> 16fe56b9e6SYuval Mintz #include <linux/interrupt.h> 17fe56b9e6SYuval Mintz #include <linux/workqueue.h> 18fe56b9e6SYuval Mintz #include <linux/ethtool.h> 19fe56b9e6SYuval Mintz #include <linux/etherdevice.h> 20fe56b9e6SYuval Mintz #include <linux/vmalloc.h> 215d24bcf1STomer Tayar #include <linux/crash_dump.h> 223a69cae8SSudarsana Reddy Kalluru #include <linux/crc32.h> 23fe56b9e6SYuval Mintz #include <linux/qed/qed_if.h> 240a7fb11cSYuval Mintz #include <linux/qed/qed_ll2_if.h> 2524e04879SMichal Kalderon #include <net/devlink.h> 262196d831SSudarsana Reddy Kalluru #include <linux/aer.h> 27bdb5d8ecSAlexander Lobakin #include <linux/phylink.h> 28fe56b9e6SYuval Mintz 29fe56b9e6SYuval Mintz #include "qed.h" 3037bff2b9SYuval Mintz #include "qed_sriov.h" 31fe56b9e6SYuval Mintz #include "qed_sp.h" 32fe56b9e6SYuval Mintz #include "qed_dev_api.h" 330a7fb11cSYuval Mintz #include "qed_ll2.h" 341e128c81SArun Easi #include "qed_fcoe.h" 352f2b2614SMintz, Yuval #include "qed_iscsi.h" 362f2b2614SMintz, Yuval 37fe56b9e6SYuval Mintz #include "qed_mcp.h" 38c56a8be7SRahul Verma #include "qed_reg_addr.h" 39fe56b9e6SYuval Mintz #include "qed_hw.h" 4003dc76caSSudarsana Reddy Kalluru #include "qed_selftest.h" 411e128c81SArun Easi #include "qed_debug.h" 42fe56b9e6SYuval Mintz 4351ff1725SRam Amrani #define QED_ROCE_QPS (8192) 4451ff1725SRam Amrani #define QED_ROCE_DPIS (8) 4539dbc646SYuval Bason #define QED_RDMA_SRQS QED_ROCE_QPS 462d4c8495SSudarsana Reddy Kalluru #define QED_NVM_CFG_GET_FLAGS 0xA 472d4c8495SSudarsana Reddy Kalluru #define QED_NVM_CFG_GET_PF_FLAGS 0x1A 48c63b0968SSudarsana Reddy Kalluru #define QED_NVM_CFG_MAX_ATTRS 50 4951ff1725SRam Amrani 505abd7e92SYuval Mintz static char version[] = 515abd7e92SYuval Mintz "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n"; 52fe56b9e6SYuval Mintz 535abd7e92SYuval Mintz MODULE_DESCRIPTION("QLogic FastLinQ 4xxxx Core Module"); 54fe56b9e6SYuval Mintz MODULE_LICENSE("GPL"); 55fe56b9e6SYuval Mintz MODULE_VERSION(DRV_MODULE_VERSION); 56fe56b9e6SYuval Mintz 57fe56b9e6SYuval Mintz #define FW_FILE_VERSION \ 58fe56b9e6SYuval Mintz __stringify(FW_MAJOR_VERSION) "." \ 59fe56b9e6SYuval Mintz __stringify(FW_MINOR_VERSION) "." \ 60fe56b9e6SYuval Mintz __stringify(FW_REVISION_VERSION) "." \ 61fe56b9e6SYuval Mintz __stringify(FW_ENGINEERING_VERSION) 62fe56b9e6SYuval Mintz 63fe56b9e6SYuval Mintz #define QED_FW_FILE_NAME \ 64fe56b9e6SYuval Mintz "qed/qed_init_values_zipped-" FW_FILE_VERSION ".bin" 65fe56b9e6SYuval Mintz 66d43d3f0fSYuval Mintz MODULE_FIRMWARE(QED_FW_FILE_NAME); 67d43d3f0fSYuval Mintz 68097818fcSAlexander Lobakin /* MFW speed capabilities maps */ 69097818fcSAlexander Lobakin 70097818fcSAlexander Lobakin struct qed_mfw_speed_map { 71097818fcSAlexander Lobakin u32 mfw_val; 72097818fcSAlexander Lobakin __ETHTOOL_DECLARE_LINK_MODE_MASK(caps); 73097818fcSAlexander Lobakin 74097818fcSAlexander Lobakin const u32 *cap_arr; 75097818fcSAlexander Lobakin u32 arr_size; 76097818fcSAlexander Lobakin }; 77097818fcSAlexander Lobakin 78097818fcSAlexander Lobakin #define QED_MFW_SPEED_MAP(type, arr) \ 79097818fcSAlexander Lobakin { \ 80097818fcSAlexander Lobakin .mfw_val = (type), \ 81097818fcSAlexander Lobakin .cap_arr = (arr), \ 82097818fcSAlexander Lobakin .arr_size = ARRAY_SIZE(arr), \ 83097818fcSAlexander Lobakin } 84097818fcSAlexander Lobakin 8599785a87SAlexander Lobakin static const u32 qed_mfw_ext_1g[] __initconst = { 8699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 8799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 8899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_1000baseX_Full_BIT, 8999785a87SAlexander Lobakin }; 9099785a87SAlexander Lobakin 9199785a87SAlexander Lobakin static const u32 qed_mfw_ext_10g[] __initconst = { 9299785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 9399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 9499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 9599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, 9699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 9799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 9899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, 9999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, 10099785a87SAlexander Lobakin }; 10199785a87SAlexander Lobakin 10299785a87SAlexander Lobakin static const u32 qed_mfw_ext_20g[] __initconst = { 10399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT, 10499785a87SAlexander Lobakin }; 10599785a87SAlexander Lobakin 10699785a87SAlexander Lobakin static const u32 qed_mfw_ext_25g[] __initconst = { 10799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 10899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 10999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 11099785a87SAlexander Lobakin }; 11199785a87SAlexander Lobakin 11299785a87SAlexander Lobakin static const u32 qed_mfw_ext_40g[] __initconst = { 11399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 11499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 11599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 11699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 11799785a87SAlexander Lobakin }; 11899785a87SAlexander Lobakin 11999785a87SAlexander Lobakin static const u32 qed_mfw_ext_50g_base_r[] __initconst = { 12099785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 12199785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 12299785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 12399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 12499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, 12599785a87SAlexander Lobakin }; 12699785a87SAlexander Lobakin 12799785a87SAlexander Lobakin static const u32 qed_mfw_ext_50g_base_r2[] __initconst = { 12899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 12999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 13099785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 13199785a87SAlexander Lobakin }; 13299785a87SAlexander Lobakin 13399785a87SAlexander Lobakin static const u32 qed_mfw_ext_100g_base_r2[] __initconst = { 13499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, 13599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, 13699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, 13799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, 13899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, 13999785a87SAlexander Lobakin }; 14099785a87SAlexander Lobakin 14199785a87SAlexander Lobakin static const u32 qed_mfw_ext_100g_base_r4[] __initconst = { 14299785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 14399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 14499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 14599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 14699785a87SAlexander Lobakin }; 14799785a87SAlexander Lobakin 14899785a87SAlexander Lobakin static struct qed_mfw_speed_map qed_mfw_ext_maps[] __ro_after_init = { 14999785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_1G, qed_mfw_ext_1g), 15099785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_10G, qed_mfw_ext_10g), 15199785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_20G, qed_mfw_ext_20g), 15299785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_25G, qed_mfw_ext_25g), 15399785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_40G, qed_mfw_ext_40g), 15499785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_50G_BASE_R, 15599785a87SAlexander Lobakin qed_mfw_ext_50g_base_r), 15699785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_50G_BASE_R2, 15799785a87SAlexander Lobakin qed_mfw_ext_50g_base_r2), 15899785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_100G_BASE_R2, 15999785a87SAlexander Lobakin qed_mfw_ext_100g_base_r2), 16099785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_100G_BASE_R4, 16199785a87SAlexander Lobakin qed_mfw_ext_100g_base_r4), 16299785a87SAlexander Lobakin }; 16399785a87SAlexander Lobakin 164097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_1g[] __initconst = { 165097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 166097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 167097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseX_Full_BIT, 168097818fcSAlexander Lobakin }; 169097818fcSAlexander Lobakin 170097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_10g[] __initconst = { 171097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 172097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 173097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 174097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, 175097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 176097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 177097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, 178097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, 179097818fcSAlexander Lobakin }; 180097818fcSAlexander Lobakin 181097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_20g[] __initconst = { 182097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT, 183097818fcSAlexander Lobakin }; 184097818fcSAlexander Lobakin 185097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_25g[] __initconst = { 186097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 187097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 188097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 189097818fcSAlexander Lobakin }; 190097818fcSAlexander Lobakin 191097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_40g[] __initconst = { 192097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 193097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 194097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 195097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 196097818fcSAlexander Lobakin }; 197097818fcSAlexander Lobakin 198097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_50g[] __initconst = { 199097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 200097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 201097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 202097818fcSAlexander Lobakin }; 203097818fcSAlexander Lobakin 204097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_bb_100g[] __initconst = { 205097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 206097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 207097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 208097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 209097818fcSAlexander Lobakin }; 210097818fcSAlexander Lobakin 211097818fcSAlexander Lobakin static struct qed_mfw_speed_map qed_mfw_legacy_maps[] __ro_after_init = { 212097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G, 213097818fcSAlexander Lobakin qed_mfw_legacy_1g), 214097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G, 215097818fcSAlexander Lobakin qed_mfw_legacy_10g), 216097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G, 217097818fcSAlexander Lobakin qed_mfw_legacy_20g), 218097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G, 219097818fcSAlexander Lobakin qed_mfw_legacy_25g), 220097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G, 221097818fcSAlexander Lobakin qed_mfw_legacy_40g), 222097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G, 223097818fcSAlexander Lobakin qed_mfw_legacy_50g), 224097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G, 225097818fcSAlexander Lobakin qed_mfw_legacy_bb_100g), 226097818fcSAlexander Lobakin }; 227097818fcSAlexander Lobakin 228097818fcSAlexander Lobakin static void __init qed_mfw_speed_map_populate(struct qed_mfw_speed_map *map) 229097818fcSAlexander Lobakin { 230097818fcSAlexander Lobakin linkmode_set_bit_array(map->cap_arr, map->arr_size, map->caps); 231097818fcSAlexander Lobakin 232097818fcSAlexander Lobakin map->cap_arr = NULL; 233097818fcSAlexander Lobakin map->arr_size = 0; 234097818fcSAlexander Lobakin } 235097818fcSAlexander Lobakin 236097818fcSAlexander Lobakin static void __init qed_mfw_speed_maps_init(void) 237097818fcSAlexander Lobakin { 238097818fcSAlexander Lobakin u32 i; 239097818fcSAlexander Lobakin 24099785a87SAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++) 24199785a87SAlexander Lobakin qed_mfw_speed_map_populate(qed_mfw_ext_maps + i); 24299785a87SAlexander Lobakin 243097818fcSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++) 244097818fcSAlexander Lobakin qed_mfw_speed_map_populate(qed_mfw_legacy_maps + i); 245097818fcSAlexander Lobakin } 246097818fcSAlexander Lobakin 247fe56b9e6SYuval Mintz static int __init qed_init(void) 248fe56b9e6SYuval Mintz { 249fe56b9e6SYuval Mintz pr_info("%s", version); 250fe56b9e6SYuval Mintz 251097818fcSAlexander Lobakin qed_mfw_speed_maps_init(); 252097818fcSAlexander Lobakin 253fe56b9e6SYuval Mintz return 0; 254fe56b9e6SYuval Mintz } 255fe56b9e6SYuval Mintz module_init(qed_init); 256097818fcSAlexander Lobakin 257097818fcSAlexander Lobakin static void __exit qed_exit(void) 258097818fcSAlexander Lobakin { 259097818fcSAlexander Lobakin /* To prevent marking this module as "permanent" */ 260097818fcSAlexander Lobakin } 261097818fcSAlexander Lobakin module_exit(qed_exit); 262fe56b9e6SYuval Mintz 263fe56b9e6SYuval Mintz /* Check if the DMA controller on the machine can properly handle the DMA 264fe56b9e6SYuval Mintz * addressing required by the device. 265fe56b9e6SYuval Mintz */ 266fe56b9e6SYuval Mintz static int qed_set_coherency_mask(struct qed_dev *cdev) 267fe56b9e6SYuval Mintz { 268fe56b9e6SYuval Mintz struct device *dev = &cdev->pdev->dev; 269fe56b9e6SYuval Mintz 270fe56b9e6SYuval Mintz if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) { 271fe56b9e6SYuval Mintz if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) { 272fe56b9e6SYuval Mintz DP_NOTICE(cdev, 273fe56b9e6SYuval Mintz "Can't request 64-bit consistent allocations\n"); 274fe56b9e6SYuval Mintz return -EIO; 275fe56b9e6SYuval Mintz } 276fe56b9e6SYuval Mintz } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) { 277fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Can't request 64b/32b DMA addresses\n"); 278fe56b9e6SYuval Mintz return -EIO; 279fe56b9e6SYuval Mintz } 280fe56b9e6SYuval Mintz 281fe56b9e6SYuval Mintz return 0; 282fe56b9e6SYuval Mintz } 283fe56b9e6SYuval Mintz 284fe56b9e6SYuval Mintz static void qed_free_pci(struct qed_dev *cdev) 285fe56b9e6SYuval Mintz { 286fe56b9e6SYuval Mintz struct pci_dev *pdev = cdev->pdev; 287fe56b9e6SYuval Mintz 2882196d831SSudarsana Reddy Kalluru pci_disable_pcie_error_reporting(pdev); 2892196d831SSudarsana Reddy Kalluru 2901a850bfcSMintz, Yuval if (cdev->doorbells && cdev->db_size) 291fe56b9e6SYuval Mintz iounmap(cdev->doorbells); 292fe56b9e6SYuval Mintz if (cdev->regview) 293fe56b9e6SYuval Mintz iounmap(cdev->regview); 294fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) 295fe56b9e6SYuval Mintz pci_release_regions(pdev); 296fe56b9e6SYuval Mintz 297fe56b9e6SYuval Mintz pci_disable_device(pdev); 298fe56b9e6SYuval Mintz } 299fe56b9e6SYuval Mintz 3000dfaba6dSYuval Mintz #define PCI_REVISION_ID_ERROR_VAL 0xff 3010dfaba6dSYuval Mintz 302fe56b9e6SYuval Mintz /* Performs PCI initializations as well as initializing PCI-related parameters 303fe56b9e6SYuval Mintz * in the device structrue. Returns 0 in case of success. 304fe56b9e6SYuval Mintz */ 3051a635e48SYuval Mintz static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev) 306fe56b9e6SYuval Mintz { 3070dfaba6dSYuval Mintz u8 rev_id; 308fe56b9e6SYuval Mintz int rc; 309fe56b9e6SYuval Mintz 310fe56b9e6SYuval Mintz cdev->pdev = pdev; 311fe56b9e6SYuval Mintz 312fe56b9e6SYuval Mintz rc = pci_enable_device(pdev); 313fe56b9e6SYuval Mintz if (rc) { 314fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot enable PCI device\n"); 315fe56b9e6SYuval Mintz goto err0; 316fe56b9e6SYuval Mintz } 317fe56b9e6SYuval Mintz 318fe56b9e6SYuval Mintz if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 319fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #0\n"); 320fe56b9e6SYuval Mintz rc = -EIO; 321fe56b9e6SYuval Mintz goto err1; 322fe56b9e6SYuval Mintz } 323fe56b9e6SYuval Mintz 3241408cc1fSYuval Mintz if (IS_PF(cdev) && !(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { 325fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #2\n"); 326fe56b9e6SYuval Mintz rc = -EIO; 327fe56b9e6SYuval Mintz goto err1; 328fe56b9e6SYuval Mintz } 329fe56b9e6SYuval Mintz 330fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) { 331fe56b9e6SYuval Mintz rc = pci_request_regions(pdev, "qed"); 332fe56b9e6SYuval Mintz if (rc) { 333fe56b9e6SYuval Mintz DP_NOTICE(cdev, 334fe56b9e6SYuval Mintz "Failed to request PCI memory resources\n"); 335fe56b9e6SYuval Mintz goto err1; 336fe56b9e6SYuval Mintz } 337fe56b9e6SYuval Mintz pci_set_master(pdev); 338fe56b9e6SYuval Mintz pci_save_state(pdev); 339fe56b9e6SYuval Mintz } 340fe56b9e6SYuval Mintz 3410dfaba6dSYuval Mintz pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); 3420dfaba6dSYuval Mintz if (rev_id == PCI_REVISION_ID_ERROR_VAL) { 3430dfaba6dSYuval Mintz DP_NOTICE(cdev, 3440dfaba6dSYuval Mintz "Detected PCI device error [rev_id 0x%x]. Probably due to prior indication. Aborting.\n", 3450dfaba6dSYuval Mintz rev_id); 3460dfaba6dSYuval Mintz rc = -ENODEV; 3470dfaba6dSYuval Mintz goto err2; 3480dfaba6dSYuval Mintz } 349fe56b9e6SYuval Mintz if (!pci_is_pcie(pdev)) { 350fe56b9e6SYuval Mintz DP_NOTICE(cdev, "The bus is not PCI Express\n"); 351fe56b9e6SYuval Mintz rc = -EIO; 352fe56b9e6SYuval Mintz goto err2; 353fe56b9e6SYuval Mintz } 354fe56b9e6SYuval Mintz 355fe56b9e6SYuval Mintz cdev->pci_params.pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); 356416cdf06SYuval Mintz if (IS_PF(cdev) && !cdev->pci_params.pm_cap) 357fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot find power management capability\n"); 358fe56b9e6SYuval Mintz 359fe56b9e6SYuval Mintz rc = qed_set_coherency_mask(cdev); 360fe56b9e6SYuval Mintz if (rc) 361fe56b9e6SYuval Mintz goto err2; 362fe56b9e6SYuval Mintz 363fe56b9e6SYuval Mintz cdev->pci_params.mem_start = pci_resource_start(pdev, 0); 364fe56b9e6SYuval Mintz cdev->pci_params.mem_end = pci_resource_end(pdev, 0); 365fe56b9e6SYuval Mintz cdev->pci_params.irq = pdev->irq; 366fe56b9e6SYuval Mintz 367fe56b9e6SYuval Mintz cdev->regview = pci_ioremap_bar(pdev, 0); 368fe56b9e6SYuval Mintz if (!cdev->regview) { 369fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map register space, aborting\n"); 370fe56b9e6SYuval Mintz rc = -ENOMEM; 371fe56b9e6SYuval Mintz goto err2; 372fe56b9e6SYuval Mintz } 373fe56b9e6SYuval Mintz 374fe56b9e6SYuval Mintz cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2); 375fe56b9e6SYuval Mintz cdev->db_size = pci_resource_len(cdev->pdev, 2); 3761a850bfcSMintz, Yuval if (!cdev->db_size) { 3771a850bfcSMintz, Yuval if (IS_PF(cdev)) { 3781a850bfcSMintz, Yuval DP_NOTICE(cdev, "No Doorbell bar available\n"); 3791a850bfcSMintz, Yuval return -EINVAL; 3801a850bfcSMintz, Yuval } else { 3811a850bfcSMintz, Yuval return 0; 3821a850bfcSMintz, Yuval } 3831a850bfcSMintz, Yuval } 3841a850bfcSMintz, Yuval 385fe56b9e6SYuval Mintz cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size); 3861a850bfcSMintz, Yuval 387fe56b9e6SYuval Mintz if (!cdev->doorbells) { 388fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map doorbell space\n"); 389fe56b9e6SYuval Mintz return -ENOMEM; 390fe56b9e6SYuval Mintz } 391fe56b9e6SYuval Mintz 3922196d831SSudarsana Reddy Kalluru /* AER (Advanced Error reporting) configuration */ 3932196d831SSudarsana Reddy Kalluru rc = pci_enable_pcie_error_reporting(pdev); 3942196d831SSudarsana Reddy Kalluru if (rc) 3952196d831SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 3962196d831SSudarsana Reddy Kalluru "Failed to configure PCIe AER [%d]\n", rc); 3972196d831SSudarsana Reddy Kalluru 398fe56b9e6SYuval Mintz return 0; 399fe56b9e6SYuval Mintz 400fe56b9e6SYuval Mintz err2: 401fe56b9e6SYuval Mintz pci_release_regions(pdev); 402fe56b9e6SYuval Mintz err1: 403fe56b9e6SYuval Mintz pci_disable_device(pdev); 404fe56b9e6SYuval Mintz err0: 405fe56b9e6SYuval Mintz return rc; 406fe56b9e6SYuval Mintz } 407fe56b9e6SYuval Mintz 408fe56b9e6SYuval Mintz int qed_fill_dev_info(struct qed_dev *cdev, 409fe56b9e6SYuval Mintz struct qed_dev_info *dev_info) 410fe56b9e6SYuval Mintz { 411c851a9dcSKalderon, Michal struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 412c851a9dcSKalderon, Michal struct qed_hw_info *hw_info = &p_hwfn->hw_info; 41319489c7fSChopra, Manish struct qed_tunnel_info *tun = &cdev->tunnel; 414cee4d264SManish Chopra struct qed_ptt *ptt; 415cee4d264SManish Chopra 416fe56b9e6SYuval Mintz memset(dev_info, 0, sizeof(struct qed_dev_info)); 417fe56b9e6SYuval Mintz 41819489c7fSChopra, Manish if (tun->vxlan.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 41919489c7fSChopra, Manish tun->vxlan.b_mode_enabled) 42019489c7fSChopra, Manish dev_info->vxlan_enable = true; 42119489c7fSChopra, Manish 42219489c7fSChopra, Manish if (tun->l2_gre.b_mode_enabled && tun->ip_gre.b_mode_enabled && 42319489c7fSChopra, Manish tun->l2_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 42419489c7fSChopra, Manish tun->ip_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 42519489c7fSChopra, Manish dev_info->gre_enable = true; 42619489c7fSChopra, Manish 42719489c7fSChopra, Manish if (tun->l2_geneve.b_mode_enabled && tun->ip_geneve.b_mode_enabled && 42819489c7fSChopra, Manish tun->l2_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN && 42919489c7fSChopra, Manish tun->ip_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN) 43019489c7fSChopra, Manish dev_info->geneve_enable = true; 43119489c7fSChopra, Manish 432fe56b9e6SYuval Mintz dev_info->num_hwfns = cdev->num_hwfns; 433fe56b9e6SYuval Mintz dev_info->pci_mem_start = cdev->pci_params.mem_start; 434fe56b9e6SYuval Mintz dev_info->pci_mem_end = cdev->pci_params.mem_end; 435fe56b9e6SYuval Mintz dev_info->pci_irq = cdev->pci_params.irq; 436c851a9dcSKalderon, Michal dev_info->rdma_supported = QED_IS_RDMA_PERSONALITY(p_hwfn); 4379c79ddaaSMintz, Yuval dev_info->dev_type = cdev->type; 438c851a9dcSKalderon, Michal ether_addr_copy(dev_info->hw_mac, hw_info->hw_mac_addr); 439fe56b9e6SYuval Mintz 4401408cc1fSYuval Mintz if (IS_PF(cdev)) { 441fe56b9e6SYuval Mintz dev_info->fw_major = FW_MAJOR_VERSION; 442fe56b9e6SYuval Mintz dev_info->fw_minor = FW_MINOR_VERSION; 443fe56b9e6SYuval Mintz dev_info->fw_rev = FW_REVISION_VERSION; 444fe56b9e6SYuval Mintz dev_info->fw_eng = FW_ENGINEERING_VERSION; 4450bc5fe85SSudarsana Reddy Kalluru dev_info->b_inter_pf_switch = test_bit(QED_MF_INTER_PF_SWITCH, 4460bc5fe85SSudarsana Reddy Kalluru &cdev->mf_bits); 4472d2fe843SDmitry Bogdanov if (!test_bit(QED_MF_DISABLE_ARFS, &cdev->mf_bits)) 4482d2fe843SDmitry Bogdanov dev_info->b_arfs_capable = true; 449831bfb0eSYuval Mintz dev_info->tx_switching = true; 45014d39648SMintz, Yuval 451c851a9dcSKalderon, Michal if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME) 45214d39648SMintz, Yuval dev_info->wol_support = true; 4533c5da942SMintz, Yuval 454df9c716dSSudarsana Reddy Kalluru dev_info->smart_an = qed_mcp_is_smart_an_supported(p_hwfn); 455df9c716dSSudarsana Reddy Kalluru 4563c5da942SMintz, Yuval dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id; 4571408cc1fSYuval Mintz } else { 4581408cc1fSYuval Mintz qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, 4591408cc1fSYuval Mintz &dev_info->fw_minor, &dev_info->fw_rev, 4601408cc1fSYuval Mintz &dev_info->fw_eng); 4611408cc1fSYuval Mintz } 462fe56b9e6SYuval Mintz 4631408cc1fSYuval Mintz if (IS_PF(cdev)) { 464cee4d264SManish Chopra ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 465cee4d264SManish Chopra if (ptt) { 4661408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), ptt, 4671408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 4681408cc1fSYuval Mintz 469ae33666aSTomer Tayar qed_mcp_get_mbi_ver(QED_LEADING_HWFN(cdev), ptt, 470ae33666aSTomer Tayar &dev_info->mbi_version); 471ae33666aSTomer Tayar 472cee4d264SManish Chopra qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt, 473cee4d264SManish Chopra &dev_info->flash_size); 474cee4d264SManish Chopra 475cee4d264SManish Chopra qed_ptt_release(QED_LEADING_HWFN(cdev), ptt); 476cee4d264SManish Chopra } 4771408cc1fSYuval Mintz } else { 4781408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), NULL, 4791408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 4801408cc1fSYuval Mintz } 481cee4d264SManish Chopra 482c851a9dcSKalderon, Michal dev_info->mtu = hw_info->mtu; 4830fefbfbaSSudarsana Kalluru 484fe56b9e6SYuval Mintz return 0; 485fe56b9e6SYuval Mintz } 486fe56b9e6SYuval Mintz 487fe56b9e6SYuval Mintz static void qed_free_cdev(struct qed_dev *cdev) 488fe56b9e6SYuval Mintz { 489fe56b9e6SYuval Mintz kfree((void *)cdev); 490fe56b9e6SYuval Mintz } 491fe56b9e6SYuval Mintz 492fe56b9e6SYuval Mintz static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev) 493fe56b9e6SYuval Mintz { 494fe56b9e6SYuval Mintz struct qed_dev *cdev; 495fe56b9e6SYuval Mintz 496fe56b9e6SYuval Mintz cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 497fe56b9e6SYuval Mintz if (!cdev) 498fe56b9e6SYuval Mintz return cdev; 499fe56b9e6SYuval Mintz 500fe56b9e6SYuval Mintz qed_init_struct(cdev); 501fe56b9e6SYuval Mintz 502fe56b9e6SYuval Mintz return cdev; 503fe56b9e6SYuval Mintz } 504fe56b9e6SYuval Mintz 505fe56b9e6SYuval Mintz /* Sets the requested power state */ 5061a635e48SYuval Mintz static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state) 507fe56b9e6SYuval Mintz { 508fe56b9e6SYuval Mintz if (!cdev) 509fe56b9e6SYuval Mintz return -ENODEV; 510fe56b9e6SYuval Mintz 511fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n"); 512fe56b9e6SYuval Mintz return 0; 513fe56b9e6SYuval Mintz } 514fe56b9e6SYuval Mintz 51524e04879SMichal Kalderon struct qed_devlink { 51624e04879SMichal Kalderon struct qed_dev *cdev; 51724e04879SMichal Kalderon }; 51824e04879SMichal Kalderon 51924e04879SMichal Kalderon enum qed_devlink_param_id { 52024e04879SMichal Kalderon QED_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 52124e04879SMichal Kalderon QED_DEVLINK_PARAM_ID_IWARP_CMT, 52224e04879SMichal Kalderon }; 52324e04879SMichal Kalderon 52424e04879SMichal Kalderon static int qed_dl_param_get(struct devlink *dl, u32 id, 52524e04879SMichal Kalderon struct devlink_param_gset_ctx *ctx) 52624e04879SMichal Kalderon { 52724e04879SMichal Kalderon struct qed_devlink *qed_dl; 52824e04879SMichal Kalderon struct qed_dev *cdev; 52924e04879SMichal Kalderon 53024e04879SMichal Kalderon qed_dl = devlink_priv(dl); 53124e04879SMichal Kalderon cdev = qed_dl->cdev; 53224e04879SMichal Kalderon ctx->val.vbool = cdev->iwarp_cmt; 53324e04879SMichal Kalderon 53424e04879SMichal Kalderon return 0; 53524e04879SMichal Kalderon } 53624e04879SMichal Kalderon 53724e04879SMichal Kalderon static int qed_dl_param_set(struct devlink *dl, u32 id, 53824e04879SMichal Kalderon struct devlink_param_gset_ctx *ctx) 53924e04879SMichal Kalderon { 54024e04879SMichal Kalderon struct qed_devlink *qed_dl; 54124e04879SMichal Kalderon struct qed_dev *cdev; 54224e04879SMichal Kalderon 54324e04879SMichal Kalderon qed_dl = devlink_priv(dl); 54424e04879SMichal Kalderon cdev = qed_dl->cdev; 54524e04879SMichal Kalderon cdev->iwarp_cmt = ctx->val.vbool; 54624e04879SMichal Kalderon 54724e04879SMichal Kalderon return 0; 54824e04879SMichal Kalderon } 54924e04879SMichal Kalderon 55024e04879SMichal Kalderon static const struct devlink_param qed_devlink_params[] = { 55124e04879SMichal Kalderon DEVLINK_PARAM_DRIVER(QED_DEVLINK_PARAM_ID_IWARP_CMT, 55224e04879SMichal Kalderon "iwarp_cmt", DEVLINK_PARAM_TYPE_BOOL, 55324e04879SMichal Kalderon BIT(DEVLINK_PARAM_CMODE_RUNTIME), 55424e04879SMichal Kalderon qed_dl_param_get, qed_dl_param_set, NULL), 55524e04879SMichal Kalderon }; 55624e04879SMichal Kalderon 55724e04879SMichal Kalderon static const struct devlink_ops qed_dl_ops; 55824e04879SMichal Kalderon 55924e04879SMichal Kalderon static int qed_devlink_register(struct qed_dev *cdev) 56024e04879SMichal Kalderon { 56124e04879SMichal Kalderon union devlink_param_value value; 56224e04879SMichal Kalderon struct qed_devlink *qed_dl; 56324e04879SMichal Kalderon struct devlink *dl; 56424e04879SMichal Kalderon int rc; 56524e04879SMichal Kalderon 56624e04879SMichal Kalderon dl = devlink_alloc(&qed_dl_ops, sizeof(*qed_dl)); 56724e04879SMichal Kalderon if (!dl) 56824e04879SMichal Kalderon return -ENOMEM; 56924e04879SMichal Kalderon 57024e04879SMichal Kalderon qed_dl = devlink_priv(dl); 57124e04879SMichal Kalderon 57224e04879SMichal Kalderon cdev->dl = dl; 57324e04879SMichal Kalderon qed_dl->cdev = cdev; 57424e04879SMichal Kalderon 57524e04879SMichal Kalderon rc = devlink_register(dl, &cdev->pdev->dev); 57624e04879SMichal Kalderon if (rc) 57724e04879SMichal Kalderon goto err_free; 57824e04879SMichal Kalderon 57924e04879SMichal Kalderon rc = devlink_params_register(dl, qed_devlink_params, 58024e04879SMichal Kalderon ARRAY_SIZE(qed_devlink_params)); 58124e04879SMichal Kalderon if (rc) 58224e04879SMichal Kalderon goto err_unregister; 58324e04879SMichal Kalderon 58424e04879SMichal Kalderon value.vbool = false; 58524e04879SMichal Kalderon devlink_param_driverinit_value_set(dl, 58624e04879SMichal Kalderon QED_DEVLINK_PARAM_ID_IWARP_CMT, 58724e04879SMichal Kalderon value); 58824e04879SMichal Kalderon 58924e04879SMichal Kalderon devlink_params_publish(dl); 59024e04879SMichal Kalderon cdev->iwarp_cmt = false; 59124e04879SMichal Kalderon 59224e04879SMichal Kalderon return 0; 59324e04879SMichal Kalderon 59424e04879SMichal Kalderon err_unregister: 59524e04879SMichal Kalderon devlink_unregister(dl); 59624e04879SMichal Kalderon 59724e04879SMichal Kalderon err_free: 59824e04879SMichal Kalderon cdev->dl = NULL; 59924e04879SMichal Kalderon devlink_free(dl); 60024e04879SMichal Kalderon 60124e04879SMichal Kalderon return rc; 60224e04879SMichal Kalderon } 60324e04879SMichal Kalderon 60424e04879SMichal Kalderon static void qed_devlink_unregister(struct qed_dev *cdev) 60524e04879SMichal Kalderon { 60624e04879SMichal Kalderon if (!cdev->dl) 60724e04879SMichal Kalderon return; 60824e04879SMichal Kalderon 60924e04879SMichal Kalderon devlink_params_unregister(cdev->dl, qed_devlink_params, 61024e04879SMichal Kalderon ARRAY_SIZE(qed_devlink_params)); 61124e04879SMichal Kalderon 61224e04879SMichal Kalderon devlink_unregister(cdev->dl); 61324e04879SMichal Kalderon devlink_free(cdev->dl); 61424e04879SMichal Kalderon } 61524e04879SMichal Kalderon 616fe56b9e6SYuval Mintz /* probing */ 617fe56b9e6SYuval Mintz static struct qed_dev *qed_probe(struct pci_dev *pdev, 6181408cc1fSYuval Mintz struct qed_probe_params *params) 619fe56b9e6SYuval Mintz { 620fe56b9e6SYuval Mintz struct qed_dev *cdev; 621fe56b9e6SYuval Mintz int rc; 622fe56b9e6SYuval Mintz 623fe56b9e6SYuval Mintz cdev = qed_alloc_cdev(pdev); 624fe56b9e6SYuval Mintz if (!cdev) 625fe56b9e6SYuval Mintz goto err0; 626fe56b9e6SYuval Mintz 627712c3cbfSMintz, Yuval cdev->drv_type = DRV_ID_DRV_TYPE_LINUX; 6281408cc1fSYuval Mintz cdev->protocol = params->protocol; 629fe56b9e6SYuval Mintz 6301408cc1fSYuval Mintz if (params->is_vf) 6311408cc1fSYuval Mintz cdev->b_is_vf = true; 6321408cc1fSYuval Mintz 6331408cc1fSYuval Mintz qed_init_dp(cdev, params->dp_module, params->dp_level); 634fe56b9e6SYuval Mintz 63564515dc8STomer Tayar cdev->recov_in_prog = params->recov_in_prog; 63664515dc8STomer Tayar 637fe56b9e6SYuval Mintz rc = qed_init_pci(cdev, pdev); 638fe56b9e6SYuval Mintz if (rc) { 639fe56b9e6SYuval Mintz DP_ERR(cdev, "init pci failed\n"); 640fe56b9e6SYuval Mintz goto err1; 641fe56b9e6SYuval Mintz } 642fe56b9e6SYuval Mintz DP_INFO(cdev, "PCI init completed successfully\n"); 643fe56b9e6SYuval Mintz 64424e04879SMichal Kalderon rc = qed_devlink_register(cdev); 64524e04879SMichal Kalderon if (rc) { 64624e04879SMichal Kalderon DP_INFO(cdev, "Failed to register devlink.\n"); 64724e04879SMichal Kalderon goto err2; 64824e04879SMichal Kalderon } 64924e04879SMichal Kalderon 650fe56b9e6SYuval Mintz rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); 651fe56b9e6SYuval Mintz if (rc) { 652fe56b9e6SYuval Mintz DP_ERR(cdev, "hw prepare failed\n"); 653fe56b9e6SYuval Mintz goto err2; 654fe56b9e6SYuval Mintz } 655fe56b9e6SYuval Mintz 65620c4515aSEwan D. Milne DP_INFO(cdev, "qed_probe completed successfully\n"); 657fe56b9e6SYuval Mintz 658fe56b9e6SYuval Mintz return cdev; 659fe56b9e6SYuval Mintz 660fe56b9e6SYuval Mintz err2: 661fe56b9e6SYuval Mintz qed_free_pci(cdev); 662fe56b9e6SYuval Mintz err1: 663fe56b9e6SYuval Mintz qed_free_cdev(cdev); 664fe56b9e6SYuval Mintz err0: 665fe56b9e6SYuval Mintz return NULL; 666fe56b9e6SYuval Mintz } 667fe56b9e6SYuval Mintz 668fe56b9e6SYuval Mintz static void qed_remove(struct qed_dev *cdev) 669fe56b9e6SYuval Mintz { 670fe56b9e6SYuval Mintz if (!cdev) 671fe56b9e6SYuval Mintz return; 672fe56b9e6SYuval Mintz 673fe56b9e6SYuval Mintz qed_hw_remove(cdev); 674fe56b9e6SYuval Mintz 675fe56b9e6SYuval Mintz qed_free_pci(cdev); 676fe56b9e6SYuval Mintz 677fe56b9e6SYuval Mintz qed_set_power_state(cdev, PCI_D3hot); 678fe56b9e6SYuval Mintz 67924e04879SMichal Kalderon qed_devlink_unregister(cdev); 68024e04879SMichal Kalderon 681fe56b9e6SYuval Mintz qed_free_cdev(cdev); 682fe56b9e6SYuval Mintz } 683fe56b9e6SYuval Mintz 684fe56b9e6SYuval Mintz static void qed_disable_msix(struct qed_dev *cdev) 685fe56b9e6SYuval Mintz { 686fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 687fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 688fe56b9e6SYuval Mintz kfree(cdev->int_params.msix_table); 689fe56b9e6SYuval Mintz } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) { 690fe56b9e6SYuval Mintz pci_disable_msi(cdev->pdev); 691fe56b9e6SYuval Mintz } 692fe56b9e6SYuval Mintz 693fe56b9e6SYuval Mintz memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param)); 694fe56b9e6SYuval Mintz } 695fe56b9e6SYuval Mintz 696fe56b9e6SYuval Mintz static int qed_enable_msix(struct qed_dev *cdev, 697fe56b9e6SYuval Mintz struct qed_int_params *int_params) 698fe56b9e6SYuval Mintz { 699fe56b9e6SYuval Mintz int i, rc, cnt; 700fe56b9e6SYuval Mintz 701fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 702fe56b9e6SYuval Mintz 703fe56b9e6SYuval Mintz for (i = 0; i < cnt; i++) 704fe56b9e6SYuval Mintz int_params->msix_table[i].entry = i; 705fe56b9e6SYuval Mintz 706fe56b9e6SYuval Mintz rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table, 707fe56b9e6SYuval Mintz int_params->in.min_msix_cnt, cnt); 708fe56b9e6SYuval Mintz if (rc < cnt && rc >= int_params->in.min_msix_cnt && 709fe56b9e6SYuval Mintz (rc % cdev->num_hwfns)) { 710fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 711fe56b9e6SYuval Mintz 712fe56b9e6SYuval Mintz /* If fastpath is initialized, we need at least one interrupt 713fe56b9e6SYuval Mintz * per hwfn [and the slow path interrupts]. New requested number 714fe56b9e6SYuval Mintz * should be a multiple of the number of hwfns. 715fe56b9e6SYuval Mintz */ 716fe56b9e6SYuval Mintz cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns; 717fe56b9e6SYuval Mintz DP_NOTICE(cdev, 718fe56b9e6SYuval Mintz "Trying to enable MSI-X with less vectors (%d out of %d)\n", 719fe56b9e6SYuval Mintz cnt, int_params->in.num_vectors); 7201a635e48SYuval Mintz rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table, 7211a635e48SYuval Mintz cnt); 722fe56b9e6SYuval Mintz if (!rc) 723fe56b9e6SYuval Mintz rc = cnt; 724fe56b9e6SYuval Mintz } 725fe56b9e6SYuval Mintz 726fe56b9e6SYuval Mintz if (rc > 0) { 727fe56b9e6SYuval Mintz /* MSI-x configuration was achieved */ 728fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSIX; 729fe56b9e6SYuval Mintz int_params->out.num_vectors = rc; 730fe56b9e6SYuval Mintz rc = 0; 731fe56b9e6SYuval Mintz } else { 732fe56b9e6SYuval Mintz DP_NOTICE(cdev, 733fe56b9e6SYuval Mintz "Failed to enable MSI-X [Requested %d vectors][rc %d]\n", 734fe56b9e6SYuval Mintz cnt, rc); 735fe56b9e6SYuval Mintz } 736fe56b9e6SYuval Mintz 737fe56b9e6SYuval Mintz return rc; 738fe56b9e6SYuval Mintz } 739fe56b9e6SYuval Mintz 740fe56b9e6SYuval Mintz /* This function outputs the int mode and the number of enabled msix vector */ 741fe56b9e6SYuval Mintz static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) 742fe56b9e6SYuval Mintz { 743fe56b9e6SYuval Mintz struct qed_int_params *int_params = &cdev->int_params; 744fe56b9e6SYuval Mintz struct msix_entry *tbl; 745fe56b9e6SYuval Mintz int rc = 0, cnt; 746fe56b9e6SYuval Mintz 747fe56b9e6SYuval Mintz switch (int_params->in.int_mode) { 748fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 749fe56b9e6SYuval Mintz /* Allocate MSIX table */ 750fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 751fe56b9e6SYuval Mintz int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL); 752fe56b9e6SYuval Mintz if (!int_params->msix_table) { 753fe56b9e6SYuval Mintz rc = -ENOMEM; 754fe56b9e6SYuval Mintz goto out; 755fe56b9e6SYuval Mintz } 756fe56b9e6SYuval Mintz 757fe56b9e6SYuval Mintz /* Enable MSIX */ 758fe56b9e6SYuval Mintz rc = qed_enable_msix(cdev, int_params); 759fe56b9e6SYuval Mintz if (!rc) 760fe56b9e6SYuval Mintz goto out; 761fe56b9e6SYuval Mintz 762fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI-X\n"); 763fe56b9e6SYuval Mintz kfree(int_params->msix_table); 764fe56b9e6SYuval Mintz if (force_mode) 765fe56b9e6SYuval Mintz goto out; 766df561f66SGustavo A. R. Silva fallthrough; 767fe56b9e6SYuval Mintz 768fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 769bb13ace7SSudarsana Reddy Kalluru if (cdev->num_hwfns == 1) { 770fe56b9e6SYuval Mintz rc = pci_enable_msi(cdev->pdev); 771fe56b9e6SYuval Mintz if (!rc) { 772fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSI; 773fe56b9e6SYuval Mintz goto out; 774fe56b9e6SYuval Mintz } 775fe56b9e6SYuval Mintz 776fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI\n"); 777fe56b9e6SYuval Mintz if (force_mode) 778fe56b9e6SYuval Mintz goto out; 779bb13ace7SSudarsana Reddy Kalluru } 780df561f66SGustavo A. R. Silva fallthrough; 781fe56b9e6SYuval Mintz 782fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 783fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_INTA; 784fe56b9e6SYuval Mintz rc = 0; 785fe56b9e6SYuval Mintz goto out; 786fe56b9e6SYuval Mintz default: 787fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Unknown int_mode value %d\n", 788fe56b9e6SYuval Mintz int_params->in.int_mode); 789fe56b9e6SYuval Mintz rc = -EINVAL; 790fe56b9e6SYuval Mintz } 791fe56b9e6SYuval Mintz 792fe56b9e6SYuval Mintz out: 793525ef5c0SYuval Mintz if (!rc) 794525ef5c0SYuval Mintz DP_INFO(cdev, "Using %s interrupts\n", 795525ef5c0SYuval Mintz int_params->out.int_mode == QED_INT_MODE_INTA ? 796525ef5c0SYuval Mintz "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ? 797525ef5c0SYuval Mintz "MSI" : "MSIX"); 798fe56b9e6SYuval Mintz cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE; 799fe56b9e6SYuval Mintz 800fe56b9e6SYuval Mintz return rc; 801fe56b9e6SYuval Mintz } 802fe56b9e6SYuval Mintz 803fe56b9e6SYuval Mintz static void qed_simd_handler_config(struct qed_dev *cdev, void *token, 804fe56b9e6SYuval Mintz int index, void(*handler)(void *)) 805fe56b9e6SYuval Mintz { 806fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 807fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 808fe56b9e6SYuval Mintz 809fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].func = handler; 810fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].token = token; 811fe56b9e6SYuval Mintz } 812fe56b9e6SYuval Mintz 813fe56b9e6SYuval Mintz static void qed_simd_handler_clean(struct qed_dev *cdev, int index) 814fe56b9e6SYuval Mintz { 815fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 816fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 817fe56b9e6SYuval Mintz 818fe56b9e6SYuval Mintz memset(&hwfn->simd_proto_handler[relative_idx], 0, 819fe56b9e6SYuval Mintz sizeof(struct qed_simd_fp_handler)); 820fe56b9e6SYuval Mintz } 821fe56b9e6SYuval Mintz 822fe56b9e6SYuval Mintz static irqreturn_t qed_msix_sp_int(int irq, void *tasklet) 823fe56b9e6SYuval Mintz { 824fe56b9e6SYuval Mintz tasklet_schedule((struct tasklet_struct *)tasklet); 825fe56b9e6SYuval Mintz return IRQ_HANDLED; 826fe56b9e6SYuval Mintz } 827fe56b9e6SYuval Mintz 828fe56b9e6SYuval Mintz static irqreturn_t qed_single_int(int irq, void *dev_instance) 829fe56b9e6SYuval Mintz { 830fe56b9e6SYuval Mintz struct qed_dev *cdev = (struct qed_dev *)dev_instance; 831fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 832fe56b9e6SYuval Mintz irqreturn_t rc = IRQ_NONE; 833fe56b9e6SYuval Mintz u64 status; 834fe56b9e6SYuval Mintz int i, j; 835fe56b9e6SYuval Mintz 836fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 837fe56b9e6SYuval Mintz status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]); 838fe56b9e6SYuval Mintz 839fe56b9e6SYuval Mintz if (!status) 840fe56b9e6SYuval Mintz continue; 841fe56b9e6SYuval Mintz 842fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 843fe56b9e6SYuval Mintz 844fe56b9e6SYuval Mintz /* Slowpath interrupt */ 845fe56b9e6SYuval Mintz if (unlikely(status & 0x1)) { 846fe56b9e6SYuval Mintz tasklet_schedule(hwfn->sp_dpc); 847fe56b9e6SYuval Mintz status &= ~0x1; 848fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 849fe56b9e6SYuval Mintz } 850fe56b9e6SYuval Mintz 851fe56b9e6SYuval Mintz /* Fastpath interrupts */ 852fe56b9e6SYuval Mintz for (j = 0; j < 64; j++) { 853fe56b9e6SYuval Mintz if ((0x2ULL << j) & status) { 8543935a709SSudarsana Reddy Kalluru struct qed_simd_fp_handler *p_handler = 8553935a709SSudarsana Reddy Kalluru &hwfn->simd_proto_handler[j]; 8563935a709SSudarsana Reddy Kalluru 8573935a709SSudarsana Reddy Kalluru if (p_handler->func) 8583935a709SSudarsana Reddy Kalluru p_handler->func(p_handler->token); 8593935a709SSudarsana Reddy Kalluru else 8603935a709SSudarsana Reddy Kalluru DP_NOTICE(hwfn, 8613935a709SSudarsana Reddy Kalluru "Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n", 8623935a709SSudarsana Reddy Kalluru j, status); 8633935a709SSudarsana Reddy Kalluru 864fe56b9e6SYuval Mintz status &= ~(0x2ULL << j); 865fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 866fe56b9e6SYuval Mintz } 867fe56b9e6SYuval Mintz } 868fe56b9e6SYuval Mintz 869fe56b9e6SYuval Mintz if (unlikely(status)) 870fe56b9e6SYuval Mintz DP_VERBOSE(hwfn, NETIF_MSG_INTR, 871fe56b9e6SYuval Mintz "got an unknown interrupt status 0x%llx\n", 872fe56b9e6SYuval Mintz status); 873fe56b9e6SYuval Mintz } 874fe56b9e6SYuval Mintz 875fe56b9e6SYuval Mintz return rc; 876fe56b9e6SYuval Mintz } 877fe56b9e6SYuval Mintz 8788f16bc97SSudarsana Kalluru int qed_slowpath_irq_req(struct qed_hwfn *hwfn) 879fe56b9e6SYuval Mintz { 8808f16bc97SSudarsana Kalluru struct qed_dev *cdev = hwfn->cdev; 881525ef5c0SYuval Mintz u32 int_mode; 8828f16bc97SSudarsana Kalluru int rc = 0; 8838f16bc97SSudarsana Kalluru u8 id; 884fe56b9e6SYuval Mintz 885525ef5c0SYuval Mintz int_mode = cdev->int_params.out.int_mode; 886525ef5c0SYuval Mintz if (int_mode == QED_INT_MODE_MSIX) { 8878f16bc97SSudarsana Kalluru id = hwfn->my_id; 8888f16bc97SSudarsana Kalluru snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x", 8898f16bc97SSudarsana Kalluru id, cdev->pdev->bus->number, 8908f16bc97SSudarsana Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 8918f16bc97SSudarsana Kalluru rc = request_irq(cdev->int_params.msix_table[id].vector, 8928f16bc97SSudarsana Kalluru qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); 893fe56b9e6SYuval Mintz } else { 894fe56b9e6SYuval Mintz unsigned long flags = 0; 895fe56b9e6SYuval Mintz 896fe56b9e6SYuval Mintz snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x", 897fe56b9e6SYuval Mintz cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), 898fe56b9e6SYuval Mintz PCI_FUNC(cdev->pdev->devfn)); 899fe56b9e6SYuval Mintz 900fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA) 901fe56b9e6SYuval Mintz flags |= IRQF_SHARED; 902fe56b9e6SYuval Mintz 903fe56b9e6SYuval Mintz rc = request_irq(cdev->pdev->irq, qed_single_int, 904fe56b9e6SYuval Mintz flags, cdev->name, cdev); 905fe56b9e6SYuval Mintz } 906fe56b9e6SYuval Mintz 907525ef5c0SYuval Mintz if (rc) 908525ef5c0SYuval Mintz DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc); 909525ef5c0SYuval Mintz else 910525ef5c0SYuval Mintz DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP), 911525ef5c0SYuval Mintz "Requested slowpath %s\n", 912525ef5c0SYuval Mintz (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ"); 913525ef5c0SYuval Mintz 914fe56b9e6SYuval Mintz return rc; 915fe56b9e6SYuval Mintz } 916fe56b9e6SYuval Mintz 91706892f2eSTomer Tayar static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn) 91806892f2eSTomer Tayar { 91906892f2eSTomer Tayar /* Calling the disable function will make sure that any 92006892f2eSTomer Tayar * currently-running function is completed. The following call to the 92106892f2eSTomer Tayar * enable function makes this sequence a flush-like operation. 92206892f2eSTomer Tayar */ 92306892f2eSTomer Tayar if (p_hwfn->b_sp_dpc_enabled) { 92406892f2eSTomer Tayar tasklet_disable(p_hwfn->sp_dpc); 92506892f2eSTomer Tayar tasklet_enable(p_hwfn->sp_dpc); 92606892f2eSTomer Tayar } 92706892f2eSTomer Tayar } 92806892f2eSTomer Tayar 9291226337aSTomer Tayar void qed_slowpath_irq_sync(struct qed_hwfn *p_hwfn) 9301226337aSTomer Tayar { 9311226337aSTomer Tayar struct qed_dev *cdev = p_hwfn->cdev; 9321226337aSTomer Tayar u8 id = p_hwfn->my_id; 9331226337aSTomer Tayar u32 int_mode; 9341226337aSTomer Tayar 9351226337aSTomer Tayar int_mode = cdev->int_params.out.int_mode; 9361226337aSTomer Tayar if (int_mode == QED_INT_MODE_MSIX) 9371226337aSTomer Tayar synchronize_irq(cdev->int_params.msix_table[id].vector); 9381226337aSTomer Tayar else 9391226337aSTomer Tayar synchronize_irq(cdev->pdev->irq); 94006892f2eSTomer Tayar 94106892f2eSTomer Tayar qed_slowpath_tasklet_flush(p_hwfn); 9421226337aSTomer Tayar } 9431226337aSTomer Tayar 944fe56b9e6SYuval Mintz static void qed_slowpath_irq_free(struct qed_dev *cdev) 945fe56b9e6SYuval Mintz { 946fe56b9e6SYuval Mintz int i; 947fe56b9e6SYuval Mintz 948fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 949fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 9508f16bc97SSudarsana Kalluru if (!cdev->hwfns[i].b_int_requested) 9518f16bc97SSudarsana Kalluru break; 952fe56b9e6SYuval Mintz synchronize_irq(cdev->int_params.msix_table[i].vector); 953fe56b9e6SYuval Mintz free_irq(cdev->int_params.msix_table[i].vector, 954fe56b9e6SYuval Mintz cdev->hwfns[i].sp_dpc); 955fe56b9e6SYuval Mintz } 956fe56b9e6SYuval Mintz } else { 9578f16bc97SSudarsana Kalluru if (QED_LEADING_HWFN(cdev)->b_int_requested) 958fe56b9e6SYuval Mintz free_irq(cdev->pdev->irq, cdev); 959fe56b9e6SYuval Mintz } 9608f16bc97SSudarsana Kalluru qed_int_disable_post_isr_release(cdev); 961fe56b9e6SYuval Mintz } 962fe56b9e6SYuval Mintz 963fe56b9e6SYuval Mintz static int qed_nic_stop(struct qed_dev *cdev) 964fe56b9e6SYuval Mintz { 965fe56b9e6SYuval Mintz int i, rc; 966fe56b9e6SYuval Mintz 967fe56b9e6SYuval Mintz rc = qed_hw_stop(cdev); 968fe56b9e6SYuval Mintz 969fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 970fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 971fe56b9e6SYuval Mintz 972fe56b9e6SYuval Mintz if (p_hwfn->b_sp_dpc_enabled) { 973fe56b9e6SYuval Mintz tasklet_disable(p_hwfn->sp_dpc); 974fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = false; 975fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_IFDOWN, 9762fdae034SColin Ian King "Disabled sp tasklet [hwfn %d] at %p\n", 977fe56b9e6SYuval Mintz i, p_hwfn->sp_dpc); 978fe56b9e6SYuval Mintz } 979fe56b9e6SYuval Mintz } 980fe56b9e6SYuval Mintz 981c965db44STomer Tayar qed_dbg_pf_exit(cdev); 982c965db44STomer Tayar 983fe56b9e6SYuval Mintz return rc; 984fe56b9e6SYuval Mintz } 985fe56b9e6SYuval Mintz 986fe56b9e6SYuval Mintz static int qed_nic_setup(struct qed_dev *cdev) 987fe56b9e6SYuval Mintz { 9880a7fb11cSYuval Mintz int rc, i; 9890a7fb11cSYuval Mintz 9900a7fb11cSYuval Mintz /* Determine if interface is going to require LL2 */ 9910a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) { 9920a7fb11cSYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 9930a7fb11cSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 9940a7fb11cSYuval Mintz 9950a7fb11cSYuval Mintz p_hwfn->using_ll2 = true; 9960a7fb11cSYuval Mintz } 9970a7fb11cSYuval Mintz } 998fe56b9e6SYuval Mintz 999fe56b9e6SYuval Mintz rc = qed_resc_alloc(cdev); 1000fe56b9e6SYuval Mintz if (rc) 1001fe56b9e6SYuval Mintz return rc; 1002fe56b9e6SYuval Mintz 1003fe56b9e6SYuval Mintz DP_INFO(cdev, "Allocated qed resources\n"); 1004fe56b9e6SYuval Mintz 1005fe56b9e6SYuval Mintz qed_resc_setup(cdev); 1006fe56b9e6SYuval Mintz 1007fe56b9e6SYuval Mintz return rc; 1008fe56b9e6SYuval Mintz } 1009fe56b9e6SYuval Mintz 1010fe56b9e6SYuval Mintz static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt) 1011fe56b9e6SYuval Mintz { 1012fe56b9e6SYuval Mintz int limit = 0; 1013fe56b9e6SYuval Mintz 1014fe56b9e6SYuval Mintz /* Mark the fastpath as free/used */ 1015fe56b9e6SYuval Mintz cdev->int_params.fp_initialized = cnt ? true : false; 1016fe56b9e6SYuval Mintz 1017fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX) 1018fe56b9e6SYuval Mintz limit = cdev->num_hwfns * 63; 1019fe56b9e6SYuval Mintz else if (cdev->int_params.fp_msix_cnt) 1020fe56b9e6SYuval Mintz limit = cdev->int_params.fp_msix_cnt; 1021fe56b9e6SYuval Mintz 1022fe56b9e6SYuval Mintz if (!limit) 1023fe56b9e6SYuval Mintz return -ENOMEM; 1024fe56b9e6SYuval Mintz 1025fe56b9e6SYuval Mintz return min_t(int, cnt, limit); 1026fe56b9e6SYuval Mintz } 1027fe56b9e6SYuval Mintz 1028fe56b9e6SYuval Mintz static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info) 1029fe56b9e6SYuval Mintz { 1030fe56b9e6SYuval Mintz memset(info, 0, sizeof(struct qed_int_info)); 1031fe56b9e6SYuval Mintz 1032fe56b9e6SYuval Mintz if (!cdev->int_params.fp_initialized) { 1033fe56b9e6SYuval Mintz DP_INFO(cdev, 1034fe56b9e6SYuval Mintz "Protocol driver requested interrupt information, but its support is not yet configured\n"); 1035fe56b9e6SYuval Mintz return -EINVAL; 1036fe56b9e6SYuval Mintz } 1037fe56b9e6SYuval Mintz 1038fe56b9e6SYuval Mintz /* Need to expose only MSI-X information; Single IRQ is handled solely 1039fe56b9e6SYuval Mintz * by qed. 1040fe56b9e6SYuval Mintz */ 1041fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 1042fe56b9e6SYuval Mintz int msix_base = cdev->int_params.fp_msix_base; 1043fe56b9e6SYuval Mintz 1044fe56b9e6SYuval Mintz info->msix_cnt = cdev->int_params.fp_msix_cnt; 1045fe56b9e6SYuval Mintz info->msix = &cdev->int_params.msix_table[msix_base]; 1046fe56b9e6SYuval Mintz } 1047fe56b9e6SYuval Mintz 1048fe56b9e6SYuval Mintz return 0; 1049fe56b9e6SYuval Mintz } 1050fe56b9e6SYuval Mintz 1051fe56b9e6SYuval Mintz static int qed_slowpath_setup_int(struct qed_dev *cdev, 1052fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 1053fe56b9e6SYuval Mintz { 10544ac801b7SYuval Mintz struct qed_sb_cnt_info sb_cnt_info; 10550189efb8SYuval Mintz int num_l2_queues = 0; 10564ac801b7SYuval Mintz int rc; 10574ac801b7SYuval Mintz int i; 1058fe56b9e6SYuval Mintz 10591d2c2024SSudarsana Reddy Kalluru if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { 10601d2c2024SSudarsana Reddy Kalluru DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); 10611d2c2024SSudarsana Reddy Kalluru return -EINVAL; 10621d2c2024SSudarsana Reddy Kalluru } 10631d2c2024SSudarsana Reddy Kalluru 10641d2c2024SSudarsana Reddy Kalluru memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 1065fe56b9e6SYuval Mintz cdev->int_params.in.int_mode = int_mode; 10664ac801b7SYuval Mintz for_each_hwfn(cdev, i) { 10674ac801b7SYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); 10684ac801b7SYuval Mintz qed_int_get_num_sbs(&cdev->hwfns[i], &sb_cnt_info); 1069726fdbe9SMintz, Yuval cdev->int_params.in.num_vectors += sb_cnt_info.cnt; 10704ac801b7SYuval Mintz cdev->int_params.in.num_vectors++; /* slowpath */ 10714ac801b7SYuval Mintz } 1072fe56b9e6SYuval Mintz 1073fe56b9e6SYuval Mintz /* We want a minimum of one slowpath and one fastpath vector per hwfn */ 1074fe56b9e6SYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; 1075fe56b9e6SYuval Mintz 1076bb7858baSSudarsana Reddy Kalluru if (is_kdump_kernel()) { 1077bb7858baSSudarsana Reddy Kalluru DP_INFO(cdev, 1078bb7858baSSudarsana Reddy Kalluru "Kdump kernel: Limit the max number of requested MSI-X vectors to %hd\n", 1079bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.min_msix_cnt); 1080bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.num_vectors = 1081bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.min_msix_cnt; 1082bb7858baSSudarsana Reddy Kalluru } 1083bb7858baSSudarsana Reddy Kalluru 1084fe56b9e6SYuval Mintz rc = qed_set_int_mode(cdev, false); 1085fe56b9e6SYuval Mintz if (rc) { 1086fe56b9e6SYuval Mintz DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); 1087fe56b9e6SYuval Mintz return rc; 1088fe56b9e6SYuval Mintz } 1089fe56b9e6SYuval Mintz 1090fe56b9e6SYuval Mintz cdev->int_params.fp_msix_base = cdev->num_hwfns; 1091fe56b9e6SYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors - 1092fe56b9e6SYuval Mintz cdev->num_hwfns; 1093fe56b9e6SYuval Mintz 10942f782278SMintz, Yuval if (!IS_ENABLED(CONFIG_QED_RDMA) || 1095c851a9dcSKalderon, Michal !QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) 10960189efb8SYuval Mintz return 0; 10970189efb8SYuval Mintz 109851ff1725SRam Amrani for_each_hwfn(cdev, i) 109951ff1725SRam Amrani num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE); 110051ff1725SRam Amrani 110151ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, 110251ff1725SRam Amrani "cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n", 110351ff1725SRam Amrani cdev->int_params.fp_msix_cnt, num_l2_queues); 110451ff1725SRam Amrani 110551ff1725SRam Amrani if (cdev->int_params.fp_msix_cnt > num_l2_queues) { 110651ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 110751ff1725SRam Amrani (cdev->int_params.fp_msix_cnt - num_l2_queues) 110851ff1725SRam Amrani / cdev->num_hwfns; 110951ff1725SRam Amrani cdev->int_params.rdma_msix_base = 111051ff1725SRam Amrani cdev->int_params.fp_msix_base + num_l2_queues; 111151ff1725SRam Amrani cdev->int_params.fp_msix_cnt = num_l2_queues; 111251ff1725SRam Amrani } else { 111351ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 0; 111451ff1725SRam Amrani } 111551ff1725SRam Amrani 111651ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n", 111751ff1725SRam Amrani cdev->int_params.rdma_msix_cnt, 111851ff1725SRam Amrani cdev->int_params.rdma_msix_base); 111951ff1725SRam Amrani 1120fe56b9e6SYuval Mintz return 0; 1121fe56b9e6SYuval Mintz } 1122fe56b9e6SYuval Mintz 11231408cc1fSYuval Mintz static int qed_slowpath_vf_setup_int(struct qed_dev *cdev) 11241408cc1fSYuval Mintz { 11251408cc1fSYuval Mintz int rc; 11261408cc1fSYuval Mintz 11271408cc1fSYuval Mintz memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 11281408cc1fSYuval Mintz cdev->int_params.in.int_mode = QED_INT_MODE_MSIX; 11291408cc1fSYuval Mintz 11301408cc1fSYuval Mintz qed_vf_get_num_rxqs(QED_LEADING_HWFN(cdev), 11311408cc1fSYuval Mintz &cdev->int_params.in.num_vectors); 11321408cc1fSYuval Mintz if (cdev->num_hwfns > 1) { 11331408cc1fSYuval Mintz u8 vectors = 0; 11341408cc1fSYuval Mintz 11351408cc1fSYuval Mintz qed_vf_get_num_rxqs(&cdev->hwfns[1], &vectors); 11361408cc1fSYuval Mintz cdev->int_params.in.num_vectors += vectors; 11371408cc1fSYuval Mintz } 11381408cc1fSYuval Mintz 11391408cc1fSYuval Mintz /* We want a minimum of one fastpath vector per vf hwfn */ 11401408cc1fSYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns; 11411408cc1fSYuval Mintz 11421408cc1fSYuval Mintz rc = qed_set_int_mode(cdev, true); 11431408cc1fSYuval Mintz if (rc) 11441408cc1fSYuval Mintz return rc; 11451408cc1fSYuval Mintz 11461408cc1fSYuval Mintz cdev->int_params.fp_msix_base = 0; 11471408cc1fSYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors; 11481408cc1fSYuval Mintz 11491408cc1fSYuval Mintz return 0; 11501408cc1fSYuval Mintz } 11511408cc1fSYuval Mintz 1152fe56b9e6SYuval Mintz u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, 1153fe56b9e6SYuval Mintz u8 *input_buf, u32 max_size, u8 *unzip_buf) 1154fe56b9e6SYuval Mintz { 1155fe56b9e6SYuval Mintz int rc; 1156fe56b9e6SYuval Mintz 1157fe56b9e6SYuval Mintz p_hwfn->stream->next_in = input_buf; 1158fe56b9e6SYuval Mintz p_hwfn->stream->avail_in = input_len; 1159fe56b9e6SYuval Mintz p_hwfn->stream->next_out = unzip_buf; 1160fe56b9e6SYuval Mintz p_hwfn->stream->avail_out = max_size; 1161fe56b9e6SYuval Mintz 1162fe56b9e6SYuval Mintz rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS); 1163fe56b9e6SYuval Mintz 1164fe56b9e6SYuval Mintz if (rc != Z_OK) { 1165fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n", 1166fe56b9e6SYuval Mintz rc); 1167fe56b9e6SYuval Mintz return 0; 1168fe56b9e6SYuval Mintz } 1169fe56b9e6SYuval Mintz 1170fe56b9e6SYuval Mintz rc = zlib_inflate(p_hwfn->stream, Z_FINISH); 1171fe56b9e6SYuval Mintz zlib_inflateEnd(p_hwfn->stream); 1172fe56b9e6SYuval Mintz 1173fe56b9e6SYuval Mintz if (rc != Z_OK && rc != Z_STREAM_END) { 1174fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n", 1175fe56b9e6SYuval Mintz p_hwfn->stream->msg, rc); 1176fe56b9e6SYuval Mintz return 0; 1177fe56b9e6SYuval Mintz } 1178fe56b9e6SYuval Mintz 1179fe56b9e6SYuval Mintz return p_hwfn->stream->total_out / 4; 1180fe56b9e6SYuval Mintz } 1181fe56b9e6SYuval Mintz 1182fe56b9e6SYuval Mintz static int qed_alloc_stream_mem(struct qed_dev *cdev) 1183fe56b9e6SYuval Mintz { 1184fe56b9e6SYuval Mintz int i; 1185fe56b9e6SYuval Mintz void *workspace; 1186fe56b9e6SYuval Mintz 1187fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1188fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 1189fe56b9e6SYuval Mintz 1190fe56b9e6SYuval Mintz p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL); 1191fe56b9e6SYuval Mintz if (!p_hwfn->stream) 1192fe56b9e6SYuval Mintz return -ENOMEM; 1193fe56b9e6SYuval Mintz 1194fe56b9e6SYuval Mintz workspace = vzalloc(zlib_inflate_workspacesize()); 1195fe56b9e6SYuval Mintz if (!workspace) 1196fe56b9e6SYuval Mintz return -ENOMEM; 1197fe56b9e6SYuval Mintz p_hwfn->stream->workspace = workspace; 1198fe56b9e6SYuval Mintz } 1199fe56b9e6SYuval Mintz 1200fe56b9e6SYuval Mintz return 0; 1201fe56b9e6SYuval Mintz } 1202fe56b9e6SYuval Mintz 1203fe56b9e6SYuval Mintz static void qed_free_stream_mem(struct qed_dev *cdev) 1204fe56b9e6SYuval Mintz { 1205fe56b9e6SYuval Mintz int i; 1206fe56b9e6SYuval Mintz 1207fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1208fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 1209fe56b9e6SYuval Mintz 1210fe56b9e6SYuval Mintz if (!p_hwfn->stream) 1211fe56b9e6SYuval Mintz return; 1212fe56b9e6SYuval Mintz 1213fe56b9e6SYuval Mintz vfree(p_hwfn->stream->workspace); 1214fe56b9e6SYuval Mintz kfree(p_hwfn->stream); 1215fe56b9e6SYuval Mintz } 1216fe56b9e6SYuval Mintz } 1217fe56b9e6SYuval Mintz 1218fe56b9e6SYuval Mintz static void qed_update_pf_params(struct qed_dev *cdev, 1219fe56b9e6SYuval Mintz struct qed_pf_params *params) 1220fe56b9e6SYuval Mintz { 1221fe56b9e6SYuval Mintz int i; 1222fe56b9e6SYuval Mintz 12235c5f2609SRam Amrani if (IS_ENABLED(CONFIG_QED_RDMA)) { 12240189efb8SYuval Mintz params->rdma_pf_params.num_qps = QED_ROCE_QPS; 12250189efb8SYuval Mintz params->rdma_pf_params.min_dpis = QED_ROCE_DPIS; 122639dbc646SYuval Bason params->rdma_pf_params.num_srqs = QED_RDMA_SRQS; 12270189efb8SYuval Mintz /* divide by 3 the MRs to avoid MF ILT overflow */ 12280189efb8SYuval Mintz params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX; 1229fe56b9e6SYuval Mintz } 1230fe56b9e6SYuval Mintz 1231d51e4af5SChopra, Manish if (cdev->num_hwfns > 1 || IS_VF(cdev)) 1232d51e4af5SChopra, Manish params->eth_pf_params.num_arfs_filters = 0; 1233d51e4af5SChopra, Manish 1234e1d32acbSMintz, Yuval /* In case we might support RDMA, don't allow qede to be greedy 12355e7baf0fSManish Chopra * with the L2 contexts. Allow for 64 queues [rx, tx cos, xdp] 12365e7baf0fSManish Chopra * per hwfn. 1237e1d32acbSMintz, Yuval */ 1238c851a9dcSKalderon, Michal if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) { 1239e1d32acbSMintz, Yuval u16 *num_cons; 1240e1d32acbSMintz, Yuval 1241e1d32acbSMintz, Yuval num_cons = ¶ms->eth_pf_params.num_cons; 12425e7baf0fSManish Chopra *num_cons = min_t(u16, *num_cons, QED_MAX_L2_CONS); 1243e1d32acbSMintz, Yuval } 1244e1d32acbSMintz, Yuval 12455c5f2609SRam Amrani for (i = 0; i < cdev->num_hwfns; i++) { 12465c5f2609SRam Amrani struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 12475c5f2609SRam Amrani 12485c5f2609SRam Amrani p_hwfn->pf_params = *params; 12495c5f2609SRam Amrani } 12505c5f2609SRam Amrani } 12515c5f2609SRam Amrani 1252d4476b8aSDenis Bolotin #define QED_PERIODIC_DB_REC_COUNT 10 1253a1b469b8SAriel Elior #define QED_PERIODIC_DB_REC_INTERVAL_MS 100 1254a1b469b8SAriel Elior #define QED_PERIODIC_DB_REC_INTERVAL \ 1255a1b469b8SAriel Elior msecs_to_jiffies(QED_PERIODIC_DB_REC_INTERVAL_MS) 1256a1b469b8SAriel Elior 1257a1b469b8SAriel Elior static int qed_slowpath_delayed_work(struct qed_hwfn *hwfn, 1258a1b469b8SAriel Elior enum qed_slowpath_wq_flag wq_flag, 1259a1b469b8SAriel Elior unsigned long delay) 1260a1b469b8SAriel Elior { 1261a1b469b8SAriel Elior if (!hwfn->slowpath_wq_active) 1262a1b469b8SAriel Elior return -EINVAL; 1263a1b469b8SAriel Elior 1264a1b469b8SAriel Elior /* Memory barrier for setting atomic bit */ 1265a1b469b8SAriel Elior smp_mb__before_atomic(); 1266a1b469b8SAriel Elior set_bit(wq_flag, &hwfn->slowpath_task_flags); 1267a1b469b8SAriel Elior smp_mb__after_atomic(); 1268a1b469b8SAriel Elior queue_delayed_work(hwfn->slowpath_wq, &hwfn->slowpath_task, delay); 1269a1b469b8SAriel Elior 1270a1b469b8SAriel Elior return 0; 1271a1b469b8SAriel Elior } 1272a1b469b8SAriel Elior 1273a1b469b8SAriel Elior void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn) 1274a1b469b8SAriel Elior { 1275a1b469b8SAriel Elior /* Reset periodic Doorbell Recovery counter */ 1276a1b469b8SAriel Elior p_hwfn->periodic_db_rec_count = QED_PERIODIC_DB_REC_COUNT; 1277a1b469b8SAriel Elior 1278a1b469b8SAriel Elior /* Don't schedule periodic Doorbell Recovery if already scheduled */ 1279a1b469b8SAriel Elior if (test_bit(QED_SLOWPATH_PERIODIC_DB_REC, 1280a1b469b8SAriel Elior &p_hwfn->slowpath_task_flags)) 1281a1b469b8SAriel Elior return; 1282a1b469b8SAriel Elior 1283a1b469b8SAriel Elior qed_slowpath_delayed_work(p_hwfn, QED_SLOWPATH_PERIODIC_DB_REC, 1284a1b469b8SAriel Elior QED_PERIODIC_DB_REC_INTERVAL); 1285a1b469b8SAriel Elior } 1286a1b469b8SAriel Elior 128759ccf86fSSudarsana Reddy Kalluru static void qed_slowpath_wq_stop(struct qed_dev *cdev) 128859ccf86fSSudarsana Reddy Kalluru { 12893b85720dSYuval Basson int i; 129059ccf86fSSudarsana Reddy Kalluru 129159ccf86fSSudarsana Reddy Kalluru if (IS_VF(cdev)) 129259ccf86fSSudarsana Reddy Kalluru return; 129359ccf86fSSudarsana Reddy Kalluru 129459ccf86fSSudarsana Reddy Kalluru for_each_hwfn(cdev, i) { 129559ccf86fSSudarsana Reddy Kalluru if (!cdev->hwfns[i].slowpath_wq) 129659ccf86fSSudarsana Reddy Kalluru continue; 129759ccf86fSSudarsana Reddy Kalluru 1298a1b469b8SAriel Elior /* Stop queuing new delayed works */ 1299a1b469b8SAriel Elior cdev->hwfns[i].slowpath_wq_active = false; 1300a1b469b8SAriel Elior 13013b85720dSYuval Basson cancel_delayed_work(&cdev->hwfns[i].slowpath_task); 130259ccf86fSSudarsana Reddy Kalluru destroy_workqueue(cdev->hwfns[i].slowpath_wq); 130359ccf86fSSudarsana Reddy Kalluru } 130459ccf86fSSudarsana Reddy Kalluru } 130559ccf86fSSudarsana Reddy Kalluru 130659ccf86fSSudarsana Reddy Kalluru static void qed_slowpath_task(struct work_struct *work) 130759ccf86fSSudarsana Reddy Kalluru { 130859ccf86fSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn, 130959ccf86fSSudarsana Reddy Kalluru slowpath_task.work); 131059ccf86fSSudarsana Reddy Kalluru struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 131159ccf86fSSudarsana Reddy Kalluru 131259ccf86fSSudarsana Reddy Kalluru if (!ptt) { 1313a1b469b8SAriel Elior if (hwfn->slowpath_wq_active) 1314a1b469b8SAriel Elior queue_delayed_work(hwfn->slowpath_wq, 1315a1b469b8SAriel Elior &hwfn->slowpath_task, 0); 1316a1b469b8SAriel Elior 131759ccf86fSSudarsana Reddy Kalluru return; 131859ccf86fSSudarsana Reddy Kalluru } 131959ccf86fSSudarsana Reddy Kalluru 132059ccf86fSSudarsana Reddy Kalluru if (test_and_clear_bit(QED_SLOWPATH_MFW_TLV_REQ, 132159ccf86fSSudarsana Reddy Kalluru &hwfn->slowpath_task_flags)) 132259ccf86fSSudarsana Reddy Kalluru qed_mfw_process_tlv_req(hwfn, ptt); 132359ccf86fSSudarsana Reddy Kalluru 1324a1b469b8SAriel Elior if (test_and_clear_bit(QED_SLOWPATH_PERIODIC_DB_REC, 1325a1b469b8SAriel Elior &hwfn->slowpath_task_flags)) { 1326a1b469b8SAriel Elior qed_db_rec_handler(hwfn, ptt); 1327a1b469b8SAriel Elior if (hwfn->periodic_db_rec_count--) 1328a1b469b8SAriel Elior qed_slowpath_delayed_work(hwfn, 1329a1b469b8SAriel Elior QED_SLOWPATH_PERIODIC_DB_REC, 1330a1b469b8SAriel Elior QED_PERIODIC_DB_REC_INTERVAL); 1331a1b469b8SAriel Elior } 1332a1b469b8SAriel Elior 133359ccf86fSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 133459ccf86fSSudarsana Reddy Kalluru } 133559ccf86fSSudarsana Reddy Kalluru 133659ccf86fSSudarsana Reddy Kalluru static int qed_slowpath_wq_start(struct qed_dev *cdev) 133759ccf86fSSudarsana Reddy Kalluru { 133859ccf86fSSudarsana Reddy Kalluru struct qed_hwfn *hwfn; 133959ccf86fSSudarsana Reddy Kalluru char name[NAME_SIZE]; 134059ccf86fSSudarsana Reddy Kalluru int i; 134159ccf86fSSudarsana Reddy Kalluru 134259ccf86fSSudarsana Reddy Kalluru if (IS_VF(cdev)) 134359ccf86fSSudarsana Reddy Kalluru return 0; 134459ccf86fSSudarsana Reddy Kalluru 134559ccf86fSSudarsana Reddy Kalluru for_each_hwfn(cdev, i) { 134659ccf86fSSudarsana Reddy Kalluru hwfn = &cdev->hwfns[i]; 134759ccf86fSSudarsana Reddy Kalluru 134859ccf86fSSudarsana Reddy Kalluru snprintf(name, NAME_SIZE, "slowpath-%02x:%02x.%02x", 134959ccf86fSSudarsana Reddy Kalluru cdev->pdev->bus->number, 135059ccf86fSSudarsana Reddy Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 135159ccf86fSSudarsana Reddy Kalluru 135259ccf86fSSudarsana Reddy Kalluru hwfn->slowpath_wq = alloc_workqueue(name, 0, 0); 135359ccf86fSSudarsana Reddy Kalluru if (!hwfn->slowpath_wq) { 135459ccf86fSSudarsana Reddy Kalluru DP_NOTICE(hwfn, "Cannot create slowpath workqueue\n"); 135559ccf86fSSudarsana Reddy Kalluru return -ENOMEM; 135659ccf86fSSudarsana Reddy Kalluru } 135759ccf86fSSudarsana Reddy Kalluru 135859ccf86fSSudarsana Reddy Kalluru INIT_DELAYED_WORK(&hwfn->slowpath_task, qed_slowpath_task); 1359a1b469b8SAriel Elior hwfn->slowpath_wq_active = true; 136059ccf86fSSudarsana Reddy Kalluru } 136159ccf86fSSudarsana Reddy Kalluru 136259ccf86fSSudarsana Reddy Kalluru return 0; 136359ccf86fSSudarsana Reddy Kalluru } 136459ccf86fSSudarsana Reddy Kalluru 1365fe56b9e6SYuval Mintz static int qed_slowpath_start(struct qed_dev *cdev, 1366fe56b9e6SYuval Mintz struct qed_slowpath_params *params) 1367fe56b9e6SYuval Mintz { 13685d24bcf1STomer Tayar struct qed_drv_load_params drv_load_params; 1369c0c2d0b4SMintz, Yuval struct qed_hw_init_params hw_init_params; 1370fe56b9e6SYuval Mintz struct qed_mcp_drv_version drv_version; 137119968430SChopra, Manish struct qed_tunnel_info tunn_info; 1372fe56b9e6SYuval Mintz const u8 *data = NULL; 1373fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 1374c78c70faSSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 137537bff2b9SYuval Mintz int rc = -EINVAL; 137637bff2b9SYuval Mintz 137737bff2b9SYuval Mintz if (qed_iov_wq_start(cdev)) 137837bff2b9SYuval Mintz goto err; 1379fe56b9e6SYuval Mintz 138059ccf86fSSudarsana Reddy Kalluru if (qed_slowpath_wq_start(cdev)) 138159ccf86fSSudarsana Reddy Kalluru goto err; 138259ccf86fSSudarsana Reddy Kalluru 13831408cc1fSYuval Mintz if (IS_PF(cdev)) { 1384fe56b9e6SYuval Mintz rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME, 1385fe56b9e6SYuval Mintz &cdev->pdev->dev); 1386fe56b9e6SYuval Mintz if (rc) { 1387fe56b9e6SYuval Mintz DP_NOTICE(cdev, 1388fe56b9e6SYuval Mintz "Failed to find fw file - /lib/firmware/%s\n", 1389fe56b9e6SYuval Mintz QED_FW_FILE_NAME); 1390fe56b9e6SYuval Mintz goto err; 1391fe56b9e6SYuval Mintz } 1392c78c70faSSudarsana Reddy Kalluru 1393d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) { 1394d51e4af5SChopra, Manish p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 1395d51e4af5SChopra, Manish if (p_ptt) { 1396d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt = p_ptt; 1397d51e4af5SChopra, Manish } else { 1398d51e4af5SChopra, Manish DP_NOTICE(cdev, 1399d51e4af5SChopra, Manish "Failed to acquire PTT for aRFS\n"); 1400d51e4af5SChopra, Manish goto err; 1401d51e4af5SChopra, Manish } 1402d51e4af5SChopra, Manish } 14031408cc1fSYuval Mintz } 1404fe56b9e6SYuval Mintz 14050e191827SSudarsana Reddy Kalluru cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS; 1406fe56b9e6SYuval Mintz rc = qed_nic_setup(cdev); 1407fe56b9e6SYuval Mintz if (rc) 1408fe56b9e6SYuval Mintz goto err; 1409fe56b9e6SYuval Mintz 14101408cc1fSYuval Mintz if (IS_PF(cdev)) 1411fe56b9e6SYuval Mintz rc = qed_slowpath_setup_int(cdev, params->int_mode); 14121408cc1fSYuval Mintz else 14131408cc1fSYuval Mintz rc = qed_slowpath_vf_setup_int(cdev); 1414fe56b9e6SYuval Mintz if (rc) 1415fe56b9e6SYuval Mintz goto err1; 1416fe56b9e6SYuval Mintz 14171408cc1fSYuval Mintz if (IS_PF(cdev)) { 1418fe56b9e6SYuval Mintz /* Allocate stream for unzipping */ 1419fe56b9e6SYuval Mintz rc = qed_alloc_stream_mem(cdev); 14202591c280SJoe Perches if (rc) 14218f16bc97SSudarsana Kalluru goto err2; 1422fe56b9e6SYuval Mintz 14238ac1ed79SJoe Perches /* First Dword used to differentiate between various sources */ 1424351a4dedSYuval Mintz data = cdev->firmware->data + sizeof(u32); 1425c965db44STomer Tayar 1426c965db44STomer Tayar qed_dbg_pf_init(cdev); 14271408cc1fSYuval Mintz } 1428fe56b9e6SYuval Mintz 14291408cc1fSYuval Mintz /* Start the slowpath */ 1430c0c2d0b4SMintz, Yuval memset(&hw_init_params, 0, sizeof(hw_init_params)); 143119968430SChopra, Manish memset(&tunn_info, 0, sizeof(tunn_info)); 143219968430SChopra, Manish tunn_info.vxlan.b_mode_enabled = true; 143319968430SChopra, Manish tunn_info.l2_gre.b_mode_enabled = true; 143419968430SChopra, Manish tunn_info.ip_gre.b_mode_enabled = true; 143519968430SChopra, Manish tunn_info.l2_geneve.b_mode_enabled = true; 143619968430SChopra, Manish tunn_info.ip_geneve.b_mode_enabled = true; 143719968430SChopra, Manish tunn_info.vxlan.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 143819968430SChopra, Manish tunn_info.l2_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 143919968430SChopra, Manish tunn_info.ip_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 144019968430SChopra, Manish tunn_info.l2_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 144119968430SChopra, Manish tunn_info.ip_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 1442c0c2d0b4SMintz, Yuval hw_init_params.p_tunn = &tunn_info; 1443c0c2d0b4SMintz, Yuval hw_init_params.b_hw_start = true; 1444c0c2d0b4SMintz, Yuval hw_init_params.int_mode = cdev->int_params.out.int_mode; 1445c0c2d0b4SMintz, Yuval hw_init_params.allow_npar_tx_switch = true; 1446c0c2d0b4SMintz, Yuval hw_init_params.bin_fw_data = data; 1447c0c2d0b4SMintz, Yuval 14485d24bcf1STomer Tayar memset(&drv_load_params, 0, sizeof(drv_load_params)); 14495d24bcf1STomer Tayar drv_load_params.is_crash_kernel = is_kdump_kernel(); 14505d24bcf1STomer Tayar drv_load_params.mfw_timeout_val = QED_LOAD_REQ_LOCK_TO_DEFAULT; 14515d24bcf1STomer Tayar drv_load_params.avoid_eng_reset = false; 14525d24bcf1STomer Tayar drv_load_params.override_force_load = QED_OVERRIDE_FORCE_LOAD_NONE; 14535d24bcf1STomer Tayar hw_init_params.p_drv_load_params = &drv_load_params; 14545d24bcf1STomer Tayar 1455c0c2d0b4SMintz, Yuval rc = qed_hw_init(cdev, &hw_init_params); 1456fe56b9e6SYuval Mintz if (rc) 14578c925c44SYuval Mintz goto err2; 1458fe56b9e6SYuval Mintz 1459fe56b9e6SYuval Mintz DP_INFO(cdev, 1460fe56b9e6SYuval Mintz "HW initialization and function start completed successfully\n"); 1461fe56b9e6SYuval Mintz 1462eaf3c0c6SChopra, Manish if (IS_PF(cdev)) { 1463eaf3c0c6SChopra, Manish cdev->tunn_feature_mask = (BIT(QED_MODE_VXLAN_TUNN) | 1464eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GENEVE_TUNN) | 1465eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGENEVE_TUNN) | 1466eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GRE_TUNN) | 1467eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGRE_TUNN)); 1468eaf3c0c6SChopra, Manish } 1469eaf3c0c6SChopra, Manish 14700a7fb11cSYuval Mintz /* Allocate LL2 interface if needed */ 14710a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->using_ll2) { 14720a7fb11cSYuval Mintz rc = qed_ll2_alloc_if(cdev); 14730a7fb11cSYuval Mintz if (rc) 14740a7fb11cSYuval Mintz goto err3; 14750a7fb11cSYuval Mintz } 14761408cc1fSYuval Mintz if (IS_PF(cdev)) { 1477fe56b9e6SYuval Mintz hwfn = QED_LEADING_HWFN(cdev); 1478fe56b9e6SYuval Mintz drv_version.version = (params->drv_major << 24) | 1479fe56b9e6SYuval Mintz (params->drv_minor << 16) | 1480fe56b9e6SYuval Mintz (params->drv_rev << 8) | 1481fe56b9e6SYuval Mintz (params->drv_eng); 1482fe56b9e6SYuval Mintz strlcpy(drv_version.name, params->name, 1483fe56b9e6SYuval Mintz MCP_DRV_VER_STR_SIZE - 4); 1484fe56b9e6SYuval Mintz rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt, 1485fe56b9e6SYuval Mintz &drv_version); 1486fe56b9e6SYuval Mintz if (rc) { 1487fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed sending drv version command\n"); 1488de0e4fd2SWenwen Wang goto err4; 1489fe56b9e6SYuval Mintz } 14901408cc1fSYuval Mintz } 1491fe56b9e6SYuval Mintz 14928c925c44SYuval Mintz qed_reset_vport_stats(cdev); 14938c925c44SYuval Mintz 1494fe56b9e6SYuval Mintz return 0; 1495fe56b9e6SYuval Mintz 1496de0e4fd2SWenwen Wang err4: 1497de0e4fd2SWenwen Wang qed_ll2_dealloc_if(cdev); 14980a7fb11cSYuval Mintz err3: 14990a7fb11cSYuval Mintz qed_hw_stop(cdev); 1500fe56b9e6SYuval Mintz err2: 15018c925c44SYuval Mintz qed_hw_timers_stop_all(cdev); 15021408cc1fSYuval Mintz if (IS_PF(cdev)) 15038c925c44SYuval Mintz qed_slowpath_irq_free(cdev); 15048c925c44SYuval Mintz qed_free_stream_mem(cdev); 1505fe56b9e6SYuval Mintz qed_disable_msix(cdev); 1506fe56b9e6SYuval Mintz err1: 1507fe56b9e6SYuval Mintz qed_resc_free(cdev); 1508fe56b9e6SYuval Mintz err: 15091408cc1fSYuval Mintz if (IS_PF(cdev)) 1510fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1511fe56b9e6SYuval Mintz 1512d51e4af5SChopra, Manish if (IS_PF(cdev) && (cdev->num_hwfns == 1) && 1513d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt) 1514d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1515d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1516c78c70faSSudarsana Reddy Kalluru 151737bff2b9SYuval Mintz qed_iov_wq_stop(cdev, false); 151837bff2b9SYuval Mintz 151959ccf86fSSudarsana Reddy Kalluru qed_slowpath_wq_stop(cdev); 152059ccf86fSSudarsana Reddy Kalluru 1521fe56b9e6SYuval Mintz return rc; 1522fe56b9e6SYuval Mintz } 1523fe56b9e6SYuval Mintz 1524fe56b9e6SYuval Mintz static int qed_slowpath_stop(struct qed_dev *cdev) 1525fe56b9e6SYuval Mintz { 1526fe56b9e6SYuval Mintz if (!cdev) 1527fe56b9e6SYuval Mintz return -ENODEV; 1528fe56b9e6SYuval Mintz 152959ccf86fSSudarsana Reddy Kalluru qed_slowpath_wq_stop(cdev); 153059ccf86fSSudarsana Reddy Kalluru 15310a7fb11cSYuval Mintz qed_ll2_dealloc_if(cdev); 15320a7fb11cSYuval Mintz 15331408cc1fSYuval Mintz if (IS_PF(cdev)) { 1534d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) 1535d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1536d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1537fe56b9e6SYuval Mintz qed_free_stream_mem(cdev); 1538c5ac9319SYuval Mintz if (IS_QED_ETH_IF(cdev)) 15390b55e27dSYuval Mintz qed_sriov_disable(cdev, true); 15405f027d7aSMintz, Yuval } 1541fe56b9e6SYuval Mintz 1542fe56b9e6SYuval Mintz qed_nic_stop(cdev); 15435f027d7aSMintz, Yuval 15445f027d7aSMintz, Yuval if (IS_PF(cdev)) 1545fe56b9e6SYuval Mintz qed_slowpath_irq_free(cdev); 1546fe56b9e6SYuval Mintz 1547fe56b9e6SYuval Mintz qed_disable_msix(cdev); 15481226337aSTomer Tayar 15491226337aSTomer Tayar qed_resc_free(cdev); 1550fe56b9e6SYuval Mintz 155137bff2b9SYuval Mintz qed_iov_wq_stop(cdev, true); 155237bff2b9SYuval Mintz 15531408cc1fSYuval Mintz if (IS_PF(cdev)) 1554fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1555fe56b9e6SYuval Mintz 1556fe56b9e6SYuval Mintz return 0; 1557fe56b9e6SYuval Mintz } 1558fe56b9e6SYuval Mintz 1559712c3cbfSMintz, Yuval static void qed_set_name(struct qed_dev *cdev, char name[NAME_SIZE]) 1560fe56b9e6SYuval Mintz { 1561fe56b9e6SYuval Mintz int i; 1562fe56b9e6SYuval Mintz 1563fe56b9e6SYuval Mintz memcpy(cdev->name, name, NAME_SIZE); 1564fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) 1565fe56b9e6SYuval Mintz snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i); 1566fe56b9e6SYuval Mintz } 1567fe56b9e6SYuval Mintz 1568fe56b9e6SYuval Mintz static u32 qed_sb_init(struct qed_dev *cdev, 1569fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 1570fe56b9e6SYuval Mintz void *sb_virt_addr, 1571fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, u16 sb_id, 1572fe56b9e6SYuval Mintz enum qed_sb_type type) 1573fe56b9e6SYuval Mintz { 1574fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 157585750d74SMintz, Yuval struct qed_ptt *p_ptt; 1576fe56b9e6SYuval Mintz u16 rel_sb_id; 1577fe56b9e6SYuval Mintz u32 rc; 1578fe56b9e6SYuval Mintz 157908eb1fb0SMichal Kalderon /* RoCE/Storage use a single engine in CMT mode while L2 uses both */ 158008eb1fb0SMichal Kalderon if (type == QED_SB_TYPE_L2_QUEUE) { 158108eb1fb0SMichal Kalderon p_hwfn = &cdev->hwfns[sb_id % cdev->num_hwfns]; 158208eb1fb0SMichal Kalderon rel_sb_id = sb_id / cdev->num_hwfns; 158308eb1fb0SMichal Kalderon } else { 158408eb1fb0SMichal Kalderon p_hwfn = QED_AFFIN_HWFN(cdev); 158508eb1fb0SMichal Kalderon rel_sb_id = sb_id; 158608eb1fb0SMichal Kalderon } 1587fe56b9e6SYuval Mintz 1588fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1589fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 159008eb1fb0SMichal Kalderon IS_LEAD_HWFN(p_hwfn) ? 0 : 1, rel_sb_id, sb_id); 1591fe56b9e6SYuval Mintz 159285750d74SMintz, Yuval if (IS_PF(p_hwfn->cdev)) { 159385750d74SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 159485750d74SMintz, Yuval if (!p_ptt) 159585750d74SMintz, Yuval return -EBUSY; 159685750d74SMintz, Yuval 159785750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, p_ptt, sb_info, sb_virt_addr, 159885750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 159985750d74SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 160085750d74SMintz, Yuval } else { 160185750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, NULL, sb_info, sb_virt_addr, 160285750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 160385750d74SMintz, Yuval } 1604fe56b9e6SYuval Mintz 1605fe56b9e6SYuval Mintz return rc; 1606fe56b9e6SYuval Mintz } 1607fe56b9e6SYuval Mintz 1608fe56b9e6SYuval Mintz static u32 qed_sb_release(struct qed_dev *cdev, 160908eb1fb0SMichal Kalderon struct qed_sb_info *sb_info, 161008eb1fb0SMichal Kalderon u16 sb_id, 161108eb1fb0SMichal Kalderon enum qed_sb_type type) 1612fe56b9e6SYuval Mintz { 1613fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 1614fe56b9e6SYuval Mintz u16 rel_sb_id; 1615fe56b9e6SYuval Mintz u32 rc; 1616fe56b9e6SYuval Mintz 161708eb1fb0SMichal Kalderon /* RoCE/Storage use a single engine in CMT mode while L2 uses both */ 161808eb1fb0SMichal Kalderon if (type == QED_SB_TYPE_L2_QUEUE) { 161908eb1fb0SMichal Kalderon p_hwfn = &cdev->hwfns[sb_id % cdev->num_hwfns]; 1620fe56b9e6SYuval Mintz rel_sb_id = sb_id / cdev->num_hwfns; 162108eb1fb0SMichal Kalderon } else { 162208eb1fb0SMichal Kalderon p_hwfn = QED_AFFIN_HWFN(cdev); 162308eb1fb0SMichal Kalderon rel_sb_id = sb_id; 162408eb1fb0SMichal Kalderon } 1625fe56b9e6SYuval Mintz 1626fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1627fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 162808eb1fb0SMichal Kalderon IS_LEAD_HWFN(p_hwfn) ? 0 : 1, rel_sb_id, sb_id); 1629fe56b9e6SYuval Mintz 1630fe56b9e6SYuval Mintz rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id); 1631fe56b9e6SYuval Mintz 1632fe56b9e6SYuval Mintz return rc; 1633fe56b9e6SYuval Mintz } 1634fe56b9e6SYuval Mintz 1635fe7cd2bfSYuval Mintz static bool qed_can_link_change(struct qed_dev *cdev) 1636fe7cd2bfSYuval Mintz { 1637fe7cd2bfSYuval Mintz return true; 1638fe7cd2bfSYuval Mintz } 1639fe7cd2bfSYuval Mintz 164099785a87SAlexander Lobakin static void qed_set_ext_speed_params(struct qed_mcp_link_params *link_params, 164199785a87SAlexander Lobakin const struct qed_link_params *params) 164299785a87SAlexander Lobakin { 164399785a87SAlexander Lobakin struct qed_mcp_link_speed_params *ext_speed = &link_params->ext_speed; 164499785a87SAlexander Lobakin const struct qed_mfw_speed_map *map; 164599785a87SAlexander Lobakin u32 i; 164699785a87SAlexander Lobakin 164799785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 164899785a87SAlexander Lobakin ext_speed->autoneg = !!params->autoneg; 164999785a87SAlexander Lobakin 165099785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 165199785a87SAlexander Lobakin ext_speed->advertised_speeds = 0; 165299785a87SAlexander Lobakin 165399785a87SAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++) { 165499785a87SAlexander Lobakin map = qed_mfw_ext_maps + i; 165599785a87SAlexander Lobakin 165699785a87SAlexander Lobakin if (linkmode_intersects(params->adv_speeds, map->caps)) 165799785a87SAlexander Lobakin ext_speed->advertised_speeds |= map->mfw_val; 165899785a87SAlexander Lobakin } 165999785a87SAlexander Lobakin } 166099785a87SAlexander Lobakin 166199785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) { 166299785a87SAlexander Lobakin switch (params->forced_speed) { 166399785a87SAlexander Lobakin case SPEED_1000: 166499785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_1G; 166599785a87SAlexander Lobakin break; 166699785a87SAlexander Lobakin case SPEED_10000: 166799785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_10G; 166899785a87SAlexander Lobakin break; 166999785a87SAlexander Lobakin case SPEED_20000: 167099785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_20G; 167199785a87SAlexander Lobakin break; 167299785a87SAlexander Lobakin case SPEED_25000: 167399785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_25G; 167499785a87SAlexander Lobakin break; 167599785a87SAlexander Lobakin case SPEED_40000: 167699785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_40G; 167799785a87SAlexander Lobakin break; 167899785a87SAlexander Lobakin case SPEED_50000: 167999785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_50G_R | 168099785a87SAlexander Lobakin QED_EXT_SPEED_50G_R2; 168199785a87SAlexander Lobakin break; 168299785a87SAlexander Lobakin case SPEED_100000: 168399785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_100G_R2 | 168499785a87SAlexander Lobakin QED_EXT_SPEED_100G_R4 | 168599785a87SAlexander Lobakin QED_EXT_SPEED_100G_P4; 168699785a87SAlexander Lobakin break; 168799785a87SAlexander Lobakin default: 168899785a87SAlexander Lobakin break; 168999785a87SAlexander Lobakin } 169099785a87SAlexander Lobakin } 169199785a87SAlexander Lobakin 169299785a87SAlexander Lobakin if (!(params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG)) 169399785a87SAlexander Lobakin return; 169499785a87SAlexander Lobakin 169599785a87SAlexander Lobakin switch (params->forced_speed) { 169699785a87SAlexander Lobakin case SPEED_25000: 169799785a87SAlexander Lobakin switch (params->fec) { 169899785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 169999785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_NONE; 170099785a87SAlexander Lobakin break; 170199785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 170299785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_BASE_R; 170399785a87SAlexander Lobakin break; 170499785a87SAlexander Lobakin case FEC_FORCE_MODE_RS: 170599785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528; 170699785a87SAlexander Lobakin break; 170799785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 170899785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528 | 170999785a87SAlexander Lobakin ETH_EXT_FEC_25G_BASE_R | 171099785a87SAlexander Lobakin ETH_EXT_FEC_25G_NONE; 171199785a87SAlexander Lobakin break; 171299785a87SAlexander Lobakin default: 171399785a87SAlexander Lobakin break; 171499785a87SAlexander Lobakin } 171599785a87SAlexander Lobakin 171699785a87SAlexander Lobakin break; 171799785a87SAlexander Lobakin case SPEED_40000: 171899785a87SAlexander Lobakin switch (params->fec) { 171999785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 172099785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_NONE; 172199785a87SAlexander Lobakin break; 172299785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 172399785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R; 172499785a87SAlexander Lobakin break; 172599785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 172699785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R | 172799785a87SAlexander Lobakin ETH_EXT_FEC_40G_NONE; 172899785a87SAlexander Lobakin break; 172999785a87SAlexander Lobakin default: 173099785a87SAlexander Lobakin break; 173199785a87SAlexander Lobakin } 173299785a87SAlexander Lobakin 173399785a87SAlexander Lobakin break; 173499785a87SAlexander Lobakin case SPEED_50000: 173599785a87SAlexander Lobakin switch (params->fec) { 173699785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 173799785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_NONE; 173899785a87SAlexander Lobakin break; 173999785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 174099785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_BASE_R; 174199785a87SAlexander Lobakin break; 174299785a87SAlexander Lobakin case FEC_FORCE_MODE_RS: 174399785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528; 174499785a87SAlexander Lobakin break; 174599785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 174699785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528 | 174799785a87SAlexander Lobakin ETH_EXT_FEC_50G_BASE_R | 174899785a87SAlexander Lobakin ETH_EXT_FEC_50G_NONE; 174999785a87SAlexander Lobakin break; 175099785a87SAlexander Lobakin default: 175199785a87SAlexander Lobakin break; 175299785a87SAlexander Lobakin } 175399785a87SAlexander Lobakin 175499785a87SAlexander Lobakin break; 175599785a87SAlexander Lobakin case SPEED_100000: 175699785a87SAlexander Lobakin switch (params->fec) { 175799785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 175899785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_NONE; 175999785a87SAlexander Lobakin break; 176099785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 176199785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_BASE_R; 176299785a87SAlexander Lobakin break; 176399785a87SAlexander Lobakin case FEC_FORCE_MODE_RS: 176499785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528; 176599785a87SAlexander Lobakin break; 176699785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 176799785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528 | 176899785a87SAlexander Lobakin ETH_EXT_FEC_100G_BASE_R | 176999785a87SAlexander Lobakin ETH_EXT_FEC_100G_NONE; 177099785a87SAlexander Lobakin break; 177199785a87SAlexander Lobakin default: 177299785a87SAlexander Lobakin break; 177399785a87SAlexander Lobakin } 177499785a87SAlexander Lobakin 177599785a87SAlexander Lobakin break; 177699785a87SAlexander Lobakin default: 177799785a87SAlexander Lobakin break; 177899785a87SAlexander Lobakin } 177999785a87SAlexander Lobakin } 178099785a87SAlexander Lobakin 1781351a4dedSYuval Mintz static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params) 1782cc875c2eSYuval Mintz { 1783cc875c2eSYuval Mintz struct qed_mcp_link_params *link_params; 1784097818fcSAlexander Lobakin struct qed_mcp_link_speed_params *speed; 1785097818fcSAlexander Lobakin const struct qed_mfw_speed_map *map; 1786bdb5d8ecSAlexander Lobakin struct qed_hwfn *hwfn; 1787cc875c2eSYuval Mintz struct qed_ptt *ptt; 1788cc875c2eSYuval Mintz int rc; 1789097818fcSAlexander Lobakin u32 i; 1790cc875c2eSYuval Mintz 1791cc875c2eSYuval Mintz if (!cdev) 1792cc875c2eSYuval Mintz return -ENODEV; 1793cc875c2eSYuval Mintz 1794cc875c2eSYuval Mintz /* The link should be set only once per PF */ 1795cc875c2eSYuval Mintz hwfn = &cdev->hwfns[0]; 1796cc875c2eSYuval Mintz 179765ed2ffdSMintz, Yuval /* When VF wants to set link, force it to read the bulletin instead. 179865ed2ffdSMintz, Yuval * This mimics the PF behavior, where a noitification [both immediate 179965ed2ffdSMintz, Yuval * and possible later] would be generated when changing properties. 180065ed2ffdSMintz, Yuval */ 180165ed2ffdSMintz, Yuval if (IS_VF(cdev)) { 180265ed2ffdSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG); 180365ed2ffdSMintz, Yuval return 0; 180465ed2ffdSMintz, Yuval } 180565ed2ffdSMintz, Yuval 1806cc875c2eSYuval Mintz ptt = qed_ptt_acquire(hwfn); 1807cc875c2eSYuval Mintz if (!ptt) 1808cc875c2eSYuval Mintz return -EBUSY; 1809cc875c2eSYuval Mintz 1810cc875c2eSYuval Mintz link_params = qed_mcp_get_link_params(hwfn); 1811bdb5d8ecSAlexander Lobakin if (!link_params) 1812bdb5d8ecSAlexander Lobakin return -ENODATA; 1813bdb5d8ecSAlexander Lobakin 1814097818fcSAlexander Lobakin speed = &link_params->speed; 1815097818fcSAlexander Lobakin 1816cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 1817097818fcSAlexander Lobakin speed->autoneg = !!params->autoneg; 1818bdb5d8ecSAlexander Lobakin 1819cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 1820097818fcSAlexander Lobakin speed->advertised_speeds = 0; 1821bdb5d8ecSAlexander Lobakin 1822097818fcSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++) { 1823097818fcSAlexander Lobakin map = qed_mfw_legacy_maps + i; 1824bdb5d8ecSAlexander Lobakin 1825097818fcSAlexander Lobakin if (linkmode_intersects(params->adv_speeds, map->caps)) 1826097818fcSAlexander Lobakin speed->advertised_speeds |= map->mfw_val; 1827097818fcSAlexander Lobakin } 1828cc875c2eSYuval Mintz } 1829bdb5d8ecSAlexander Lobakin 1830cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) 1831097818fcSAlexander Lobakin speed->forced_speed = params->forced_speed; 1832097818fcSAlexander Lobakin 183399785a87SAlexander Lobakin if (qed_mcp_is_ext_speed_supported(hwfn)) 183499785a87SAlexander Lobakin qed_set_ext_speed_params(link_params, params); 183599785a87SAlexander Lobakin 1836a43f235fSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) { 1837a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 1838a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = true; 1839a43f235fSSudarsana Reddy Kalluru else 1840a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = false; 1841a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE) 1842a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = true; 1843a43f235fSSudarsana Reddy Kalluru else 1844a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = false; 1845a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE) 1846a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = true; 1847a43f235fSSudarsana Reddy Kalluru else 1848a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = false; 1849a43f235fSSudarsana Reddy Kalluru } 1850097818fcSAlexander Lobakin 185103dc76caSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) { 185203dc76caSSudarsana Reddy Kalluru switch (params->loopback_mode) { 185303dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_INT_PHY: 1854351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_INT_PHY; 185503dc76caSSudarsana Reddy Kalluru break; 185603dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT_PHY: 1857351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT_PHY; 185803dc76caSSudarsana Reddy Kalluru break; 185903dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT: 1860351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT; 186103dc76caSSudarsana Reddy Kalluru break; 186203dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_MAC: 1863351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_MAC; 186403dc76caSSudarsana Reddy Kalluru break; 186598e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_CNIG_AH_ONLY_0123: 186698e675ecSAlexander Lobakin link_params->loopback_mode = 186798e675ecSAlexander Lobakin ETH_LOOPBACK_CNIG_AH_ONLY_0123; 186898e675ecSAlexander Lobakin break; 186998e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_CNIG_AH_ONLY_2301: 187098e675ecSAlexander Lobakin link_params->loopback_mode = 187198e675ecSAlexander Lobakin ETH_LOOPBACK_CNIG_AH_ONLY_2301; 187298e675ecSAlexander Lobakin break; 187398e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_PCS_AH_ONLY: 187498e675ecSAlexander Lobakin link_params->loopback_mode = ETH_LOOPBACK_PCS_AH_ONLY; 187598e675ecSAlexander Lobakin break; 187698e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_REVERSE_MAC_AH_ONLY: 187798e675ecSAlexander Lobakin link_params->loopback_mode = 187898e675ecSAlexander Lobakin ETH_LOOPBACK_REVERSE_MAC_AH_ONLY; 187998e675ecSAlexander Lobakin break; 188098e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_INT_PHY_FEA_AH_ONLY: 188198e675ecSAlexander Lobakin link_params->loopback_mode = 188298e675ecSAlexander Lobakin ETH_LOOPBACK_INT_PHY_FEA_AH_ONLY; 188398e675ecSAlexander Lobakin break; 188403dc76caSSudarsana Reddy Kalluru default: 1885351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_NONE; 188603dc76caSSudarsana Reddy Kalluru break; 188703dc76caSSudarsana Reddy Kalluru } 188803dc76caSSudarsana Reddy Kalluru } 1889cc875c2eSYuval Mintz 1890645874e5SSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG) 1891645874e5SSudarsana Reddy Kalluru memcpy(&link_params->eee, ¶ms->eee, 1892645874e5SSudarsana Reddy Kalluru sizeof(link_params->eee)); 1893645874e5SSudarsana Reddy Kalluru 1894ae7e6937SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG) 1895ae7e6937SAlexander Lobakin link_params->fec = params->fec; 1896ae7e6937SAlexander Lobakin 1897cc875c2eSYuval Mintz rc = qed_mcp_set_link(hwfn, ptt, params->link_up); 1898cc875c2eSYuval Mintz 1899cc875c2eSYuval Mintz qed_ptt_release(hwfn, ptt); 1900cc875c2eSYuval Mintz 1901cc875c2eSYuval Mintz return rc; 1902cc875c2eSYuval Mintz } 1903cc875c2eSYuval Mintz 1904cc875c2eSYuval Mintz static int qed_get_port_type(u32 media_type) 1905cc875c2eSYuval Mintz { 1906cc875c2eSYuval Mintz int port_type; 1907cc875c2eSYuval Mintz 1908cc875c2eSYuval Mintz switch (media_type) { 1909cc875c2eSYuval Mintz case MEDIA_SFPP_10G_FIBER: 1910cc875c2eSYuval Mintz case MEDIA_SFP_1G_FIBER: 1911cc875c2eSYuval Mintz case MEDIA_XFP_FIBER: 1912b639f197SYuval Mintz case MEDIA_MODULE_FIBER: 1913cc875c2eSYuval Mintz port_type = PORT_FIBRE; 1914cc875c2eSYuval Mintz break; 1915cc875c2eSYuval Mintz case MEDIA_DA_TWINAX: 1916cc875c2eSYuval Mintz port_type = PORT_DA; 1917cc875c2eSYuval Mintz break; 1918cc875c2eSYuval Mintz case MEDIA_BASE_T: 1919cc875c2eSYuval Mintz port_type = PORT_TP; 1920cc875c2eSYuval Mintz break; 192199785a87SAlexander Lobakin case MEDIA_KR: 1922cc875c2eSYuval Mintz case MEDIA_NOT_PRESENT: 1923cc875c2eSYuval Mintz port_type = PORT_NONE; 1924cc875c2eSYuval Mintz break; 1925cc875c2eSYuval Mintz case MEDIA_UNSPECIFIED: 1926cc875c2eSYuval Mintz default: 1927cc875c2eSYuval Mintz port_type = PORT_OTHER; 1928cc875c2eSYuval Mintz break; 1929cc875c2eSYuval Mintz } 1930cc875c2eSYuval Mintz return port_type; 1931cc875c2eSYuval Mintz } 1932cc875c2eSYuval Mintz 193314b84e86SArnd Bergmann static int qed_get_link_data(struct qed_hwfn *hwfn, 193414b84e86SArnd Bergmann struct qed_mcp_link_params *params, 193514b84e86SArnd Bergmann struct qed_mcp_link_state *link, 193614b84e86SArnd Bergmann struct qed_mcp_link_capabilities *link_caps) 193714b84e86SArnd Bergmann { 193814b84e86SArnd Bergmann void *p; 193914b84e86SArnd Bergmann 194014b84e86SArnd Bergmann if (!IS_PF(hwfn->cdev)) { 194114b84e86SArnd Bergmann qed_vf_get_link_params(hwfn, params); 194214b84e86SArnd Bergmann qed_vf_get_link_state(hwfn, link); 194314b84e86SArnd Bergmann qed_vf_get_link_caps(hwfn, link_caps); 194414b84e86SArnd Bergmann 194514b84e86SArnd Bergmann return 0; 194614b84e86SArnd Bergmann } 194714b84e86SArnd Bergmann 194814b84e86SArnd Bergmann p = qed_mcp_get_link_params(hwfn); 194914b84e86SArnd Bergmann if (!p) 195014b84e86SArnd Bergmann return -ENXIO; 195114b84e86SArnd Bergmann memcpy(params, p, sizeof(*params)); 195214b84e86SArnd Bergmann 195314b84e86SArnd Bergmann p = qed_mcp_get_link_state(hwfn); 195414b84e86SArnd Bergmann if (!p) 195514b84e86SArnd Bergmann return -ENXIO; 195614b84e86SArnd Bergmann memcpy(link, p, sizeof(*link)); 195714b84e86SArnd Bergmann 195814b84e86SArnd Bergmann p = qed_mcp_get_link_capabilities(hwfn); 195914b84e86SArnd Bergmann if (!p) 196014b84e86SArnd Bergmann return -ENXIO; 196114b84e86SArnd Bergmann memcpy(link_caps, p, sizeof(*link_caps)); 196214b84e86SArnd Bergmann 196314b84e86SArnd Bergmann return 0; 196414b84e86SArnd Bergmann } 196514b84e86SArnd Bergmann 1966c56a8be7SRahul Verma static void qed_fill_link_capability(struct qed_hwfn *hwfn, 1967c56a8be7SRahul Verma struct qed_ptt *ptt, u32 capability, 1968bdb5d8ecSAlexander Lobakin unsigned long *if_caps) 1969c56a8be7SRahul Verma { 1970c56a8be7SRahul Verma u32 media_type, tcvr_state, tcvr_type; 1971c56a8be7SRahul Verma u32 speed_mask, board_cfg; 1972c56a8be7SRahul Verma 1973c56a8be7SRahul Verma if (qed_mcp_get_media_type(hwfn, ptt, &media_type)) 1974c56a8be7SRahul Verma media_type = MEDIA_UNSPECIFIED; 1975c56a8be7SRahul Verma 1976c56a8be7SRahul Verma if (qed_mcp_get_transceiver_data(hwfn, ptt, &tcvr_state, &tcvr_type)) 1977c56a8be7SRahul Verma tcvr_type = ETH_TRANSCEIVER_STATE_UNPLUGGED; 1978c56a8be7SRahul Verma 1979c56a8be7SRahul Verma if (qed_mcp_trans_speed_mask(hwfn, ptt, &speed_mask)) 1980c56a8be7SRahul Verma speed_mask = 0xFFFFFFFF; 1981c56a8be7SRahul Verma 1982c56a8be7SRahul Verma if (qed_mcp_get_board_config(hwfn, ptt, &board_cfg)) 1983c56a8be7SRahul Verma board_cfg = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED; 1984c56a8be7SRahul Verma 1985c56a8be7SRahul Verma DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV, 1986c56a8be7SRahul Verma "Media_type = 0x%x tcvr_state = 0x%x tcvr_type = 0x%x speed_mask = 0x%x board_cfg = 0x%x\n", 1987c56a8be7SRahul Verma media_type, tcvr_state, tcvr_type, speed_mask, board_cfg); 1988c56a8be7SRahul Verma 1989c56a8be7SRahul Verma switch (media_type) { 1990c56a8be7SRahul Verma case MEDIA_DA_TWINAX: 1991bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE); 1992bdb5d8ecSAlexander Lobakin 1993c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) 1994bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full); 1995bdb5d8ecSAlexander Lobakin 1996c56a8be7SRahul Verma /* For DAC media multiple speed capabilities are supported */ 19979228b7c1SAlexander Lobakin capability |= speed_mask; 19989228b7c1SAlexander Lobakin 1999c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 2000bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full); 2001c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 2002bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseCR_Full); 20039228b7c1SAlexander Lobakin 2004c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 20059228b7c1SAlexander Lobakin switch (tcvr_type) { 20069228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_CR4: 20079228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR: 20089228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR: 2009bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseCR4_Full); 20109228b7c1SAlexander Lobakin break; 20119228b7c1SAlexander Lobakin default: 20129228b7c1SAlexander Lobakin break; 20139228b7c1SAlexander Lobakin } 20149228b7c1SAlexander Lobakin 2015c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 2016bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseCR_Full); 2017c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 2018bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseCR2_Full); 20199228b7c1SAlexander Lobakin 2020c56a8be7SRahul Verma if (capability & 2021c56a8be7SRahul Verma NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 20229228b7c1SAlexander Lobakin switch (tcvr_type) { 20239228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_100G_CR4: 20249228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR: 2025bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseCR4_Full); 20269228b7c1SAlexander Lobakin break; 20279228b7c1SAlexander Lobakin default: 20289228b7c1SAlexander Lobakin break; 20299228b7c1SAlexander Lobakin } 2030bdb5d8ecSAlexander Lobakin 2031c56a8be7SRahul Verma break; 2032c56a8be7SRahul Verma case MEDIA_BASE_T: 2033bdb5d8ecSAlexander Lobakin phylink_set(if_caps, TP); 2034bdb5d8ecSAlexander Lobakin 2035c56a8be7SRahul Verma if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) { 2036c56a8be7SRahul Verma if (capability & 2037bdb5d8ecSAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 2038bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseT_Full); 2039c56a8be7SRahul Verma if (capability & 2040bdb5d8ecSAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 2041bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseT_Full); 2042c56a8be7SRahul Verma } 2043bdb5d8ecSAlexander Lobakin 2044c56a8be7SRahul Verma if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) { 2045bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE); 2046bdb5d8ecSAlexander Lobakin 20479228b7c1SAlexander Lobakin switch (tcvr_type) { 20489228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1000BASET: 2049bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseT_Full); 20509228b7c1SAlexander Lobakin break; 20519228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_BASET: 2052bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseT_Full); 20539228b7c1SAlexander Lobakin break; 20549228b7c1SAlexander Lobakin default: 20559228b7c1SAlexander Lobakin break; 20569228b7c1SAlexander Lobakin } 2057c56a8be7SRahul Verma } 2058bdb5d8ecSAlexander Lobakin 2059c56a8be7SRahul Verma break; 2060c56a8be7SRahul Verma case MEDIA_SFP_1G_FIBER: 2061c56a8be7SRahul Verma case MEDIA_SFPP_10G_FIBER: 2062c56a8be7SRahul Verma case MEDIA_XFP_FIBER: 2063c56a8be7SRahul Verma case MEDIA_MODULE_FIBER: 2064bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE); 20659228b7c1SAlexander Lobakin capability |= speed_mask; 2066bdb5d8ecSAlexander Lobakin 20679228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 20689228b7c1SAlexander Lobakin switch (tcvr_type) { 20699228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1G_LX: 20709228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1G_SX: 20719228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR: 20729228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR: 2073bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full); 20749228b7c1SAlexander Lobakin break; 20759228b7c1SAlexander Lobakin default: 20769228b7c1SAlexander Lobakin break; 2077c56a8be7SRahul Verma } 2078bdb5d8ecSAlexander Lobakin 20799228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 20809228b7c1SAlexander Lobakin switch (tcvr_type) { 20819228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_SR: 20829228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR: 20839228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR: 20849228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR: 2085bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseSR_Full); 20869228b7c1SAlexander Lobakin break; 20879228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_LR: 20889228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR: 20899228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR: 20909228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR: 2091bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseLR_Full); 20929228b7c1SAlexander Lobakin break; 20939228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_LRM: 2094bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseLRM_Full); 20959228b7c1SAlexander Lobakin break; 20969228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_ER: 2097bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseR_FEC); 20989228b7c1SAlexander Lobakin break; 20999228b7c1SAlexander Lobakin default: 21009228b7c1SAlexander Lobakin break; 2101c56a8be7SRahul Verma } 2102bdb5d8ecSAlexander Lobakin 2103c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) 2104bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full); 2105bdb5d8ecSAlexander Lobakin 21069228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 21079228b7c1SAlexander Lobakin switch (tcvr_type) { 21089228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_25G_SR: 21099228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR: 2110bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseSR_Full); 21119228b7c1SAlexander Lobakin break; 21129228b7c1SAlexander Lobakin default: 21139228b7c1SAlexander Lobakin break; 2114c56a8be7SRahul Verma } 2115bdb5d8ecSAlexander Lobakin 21169228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 21179228b7c1SAlexander Lobakin switch (tcvr_type) { 21189228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_LR4: 21199228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR: 21209228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR: 2121bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseLR4_Full); 21229228b7c1SAlexander Lobakin break; 21239228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_SR4: 21249228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR: 21259228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR: 2126bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseSR4_Full); 21279228b7c1SAlexander Lobakin break; 21289228b7c1SAlexander Lobakin default: 21299228b7c1SAlexander Lobakin break; 2130c56a8be7SRahul Verma } 2131bdb5d8ecSAlexander Lobakin 2132bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 2133bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseKR2_Full); 2134bdb5d8ecSAlexander Lobakin 2135c56a8be7SRahul Verma if (capability & 21369228b7c1SAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 21379228b7c1SAlexander Lobakin switch (tcvr_type) { 21389228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_100G_SR4: 21399228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR: 2140bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseSR4_Full); 21419228b7c1SAlexander Lobakin break; 21429228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR: 21439228b7c1SAlexander Lobakin phylink_set(if_caps, 100000baseLR4_ER4_Full); 21449228b7c1SAlexander Lobakin break; 21459228b7c1SAlexander Lobakin default: 21469228b7c1SAlexander Lobakin break; 2147c56a8be7SRahul Verma } 2148c56a8be7SRahul Verma 2149c56a8be7SRahul Verma break; 2150c56a8be7SRahul Verma case MEDIA_KR: 2151bdb5d8ecSAlexander Lobakin phylink_set(if_caps, Backplane); 2152bdb5d8ecSAlexander Lobakin 2153c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) 2154bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full); 2155bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 2156bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full); 2157bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 2158bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseKR_Full); 2159bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 2160bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseKR_Full); 2161bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 2162bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseKR4_Full); 2163bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 2164bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseKR2_Full); 2165c56a8be7SRahul Verma if (capability & 2166c56a8be7SRahul Verma NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 2167bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseKR4_Full); 2168bdb5d8ecSAlexander Lobakin 2169c56a8be7SRahul Verma break; 2170c56a8be7SRahul Verma case MEDIA_UNSPECIFIED: 2171c56a8be7SRahul Verma case MEDIA_NOT_PRESENT: 21729228b7c1SAlexander Lobakin default: 2173c56a8be7SRahul Verma DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG, 2174c56a8be7SRahul Verma "Unknown media and transceiver type;\n"); 2175c56a8be7SRahul Verma break; 2176c56a8be7SRahul Verma } 2177c56a8be7SRahul Verma } 2178c56a8be7SRahul Verma 21793c41486eSAlexander Lobakin static void qed_lp_caps_to_speed_mask(u32 caps, u32 *speed_mask) 21803c41486eSAlexander Lobakin { 21813c41486eSAlexander Lobakin *speed_mask = 0; 21823c41486eSAlexander Lobakin 21833c41486eSAlexander Lobakin if (caps & 21843c41486eSAlexander Lobakin (QED_LINK_PARTNER_SPEED_1G_FD | QED_LINK_PARTNER_SPEED_1G_HD)) 21853c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G; 21863c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_10G) 21873c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G; 21883c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_20G) 21893c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G; 21903c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_25G) 21913c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G; 21923c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_40G) 21933c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G; 21943c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_50G) 21953c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G; 21963c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_100G) 21973c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G; 21983c41486eSAlexander Lobakin } 21993c41486eSAlexander Lobakin 2200cc875c2eSYuval Mintz static void qed_fill_link(struct qed_hwfn *hwfn, 2201706d0891SRahul Verma struct qed_ptt *ptt, 2202cc875c2eSYuval Mintz struct qed_link_output *if_link) 2203cc875c2eSYuval Mintz { 2204c56a8be7SRahul Verma struct qed_mcp_link_capabilities link_caps; 2205cc875c2eSYuval Mintz struct qed_mcp_link_params params; 2206cc875c2eSYuval Mintz struct qed_mcp_link_state link; 22073c41486eSAlexander Lobakin u32 media_type, speed_mask; 2208cc875c2eSYuval Mintz 2209cc875c2eSYuval Mintz memset(if_link, 0, sizeof(*if_link)); 2210cc875c2eSYuval Mintz 2211cc875c2eSYuval Mintz /* Prepare source inputs */ 221214b84e86SArnd Bergmann if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) { 221314b84e86SArnd Bergmann dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n"); 221414b84e86SArnd Bergmann return; 22151408cc1fSYuval Mintz } 2216cc875c2eSYuval Mintz 2217cc875c2eSYuval Mintz /* Set the link parameters to pass to protocol driver */ 2218cc875c2eSYuval Mintz if (link.link_up) 2219cc875c2eSYuval Mintz if_link->link_up = true; 2220cc875c2eSYuval Mintz 222199785a87SAlexander Lobakin if (IS_PF(hwfn->cdev) && qed_mcp_is_ext_speed_supported(hwfn)) { 222299785a87SAlexander Lobakin if (link_caps.default_ext_autoneg) 222399785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Autoneg); 222499785a87SAlexander Lobakin 222599785a87SAlexander Lobakin linkmode_copy(if_link->advertised_caps, if_link->supported_caps); 222699785a87SAlexander Lobakin 222799785a87SAlexander Lobakin if (params.ext_speed.autoneg) 222899785a87SAlexander Lobakin phylink_set(if_link->advertised_caps, Autoneg); 222999785a87SAlexander Lobakin else 223099785a87SAlexander Lobakin phylink_clear(if_link->advertised_caps, Autoneg); 223199785a87SAlexander Lobakin 223299785a87SAlexander Lobakin qed_fill_link_capability(hwfn, ptt, 223399785a87SAlexander Lobakin params.ext_speed.advertised_speeds, 223499785a87SAlexander Lobakin if_link->advertised_caps); 223599785a87SAlexander Lobakin } else { 223634f9199cSsudarsana.kalluru@cavium.com if (link_caps.default_speed_autoneg) 2237bdb5d8ecSAlexander Lobakin phylink_set(if_link->supported_caps, Autoneg); 2238cc875c2eSYuval Mintz 2239bdb5d8ecSAlexander Lobakin linkmode_copy(if_link->advertised_caps, if_link->supported_caps); 2240bdb5d8ecSAlexander Lobakin 224134f9199cSsudarsana.kalluru@cavium.com if (params.speed.autoneg) 2242bdb5d8ecSAlexander Lobakin phylink_set(if_link->advertised_caps, Autoneg); 224334f9199cSsudarsana.kalluru@cavium.com else 2244bdb5d8ecSAlexander Lobakin phylink_clear(if_link->advertised_caps, Autoneg); 224599785a87SAlexander Lobakin } 224699785a87SAlexander Lobakin 224799785a87SAlexander Lobakin if (params.pause.autoneg || 224899785a87SAlexander Lobakin (params.pause.forced_rx && params.pause.forced_tx)) 224999785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Asym_Pause); 225099785a87SAlexander Lobakin if (params.pause.autoneg || params.pause.forced_rx || 225199785a87SAlexander Lobakin params.pause.forced_tx) 225299785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Pause); 2253cc875c2eSYuval Mintz 2254ae7e6937SAlexander Lobakin if_link->sup_fec = link_caps.fec_default; 2255ae7e6937SAlexander Lobakin if_link->active_fec = params.fec; 2256ae7e6937SAlexander Lobakin 2257c56a8be7SRahul Verma /* Fill link advertised capability */ 2258c56a8be7SRahul Verma qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds, 2259bdb5d8ecSAlexander Lobakin if_link->advertised_caps); 22603c41486eSAlexander Lobakin 2261c56a8be7SRahul Verma /* Fill link supported capability */ 2262c56a8be7SRahul Verma qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities, 2263bdb5d8ecSAlexander Lobakin if_link->supported_caps); 2264cc875c2eSYuval Mintz 22653c41486eSAlexander Lobakin /* Fill partner advertised capability */ 22663c41486eSAlexander Lobakin qed_lp_caps_to_speed_mask(link.partner_adv_speed, &speed_mask); 22673c41486eSAlexander Lobakin qed_fill_link_capability(hwfn, ptt, speed_mask, if_link->lp_caps); 22683c41486eSAlexander Lobakin 2269cc875c2eSYuval Mintz if (link.link_up) 2270cc875c2eSYuval Mintz if_link->speed = link.speed; 2271cc875c2eSYuval Mintz 2272cc875c2eSYuval Mintz /* TODO - fill duplex properly */ 2273cc875c2eSYuval Mintz if_link->duplex = DUPLEX_FULL; 2274706d0891SRahul Verma qed_mcp_get_media_type(hwfn, ptt, &media_type); 2275cc875c2eSYuval Mintz if_link->port = qed_get_port_type(media_type); 2276cc875c2eSYuval Mintz 2277cc875c2eSYuval Mintz if_link->autoneg = params.speed.autoneg; 2278cc875c2eSYuval Mintz 2279cc875c2eSYuval Mintz if (params.pause.autoneg) 2280cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 2281cc875c2eSYuval Mintz if (params.pause.forced_rx) 2282cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE; 2283cc875c2eSYuval Mintz if (params.pause.forced_tx) 2284cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE; 2285cc875c2eSYuval Mintz 2286cc875c2eSYuval Mintz if (link.an_complete) 2287bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Autoneg); 2288cc875c2eSYuval Mintz if (link.partner_adv_pause) 2289bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Pause); 2290cc875c2eSYuval Mintz if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE || 2291cc875c2eSYuval Mintz link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE) 2292bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Asym_Pause); 2293645874e5SSudarsana Reddy Kalluru 2294645874e5SSudarsana Reddy Kalluru if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) { 2295645874e5SSudarsana Reddy Kalluru if_link->eee_supported = false; 2296645874e5SSudarsana Reddy Kalluru } else { 2297645874e5SSudarsana Reddy Kalluru if_link->eee_supported = true; 2298645874e5SSudarsana Reddy Kalluru if_link->eee_active = link.eee_active; 2299645874e5SSudarsana Reddy Kalluru if_link->sup_caps = link_caps.eee_speed_caps; 2300645874e5SSudarsana Reddy Kalluru /* MFW clears adv_caps on eee disable; use configured value */ 2301645874e5SSudarsana Reddy Kalluru if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps : 2302645874e5SSudarsana Reddy Kalluru params.eee.adv_caps; 2303645874e5SSudarsana Reddy Kalluru if_link->eee.lp_adv_caps = link.eee_lp_adv_caps; 2304645874e5SSudarsana Reddy Kalluru if_link->eee.enable = params.eee.enable; 2305645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable; 2306645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer; 2307645874e5SSudarsana Reddy Kalluru } 2308cc875c2eSYuval Mintz } 2309cc875c2eSYuval Mintz 2310cc875c2eSYuval Mintz static void qed_get_current_link(struct qed_dev *cdev, 2311cc875c2eSYuval Mintz struct qed_link_output *if_link) 2312cc875c2eSYuval Mintz { 2313706d0891SRahul Verma struct qed_hwfn *hwfn; 2314706d0891SRahul Verma struct qed_ptt *ptt; 231536558c3dSYuval Mintz int i; 231636558c3dSYuval Mintz 2317706d0891SRahul Verma hwfn = &cdev->hwfns[0]; 2318706d0891SRahul Verma if (IS_PF(cdev)) { 2319706d0891SRahul Verma ptt = qed_ptt_acquire(hwfn); 2320706d0891SRahul Verma if (ptt) { 2321706d0891SRahul Verma qed_fill_link(hwfn, ptt, if_link); 2322706d0891SRahul Verma qed_ptt_release(hwfn, ptt); 2323706d0891SRahul Verma } else { 2324706d0891SRahul Verma DP_NOTICE(hwfn, "Failed to fill link; No PTT\n"); 2325706d0891SRahul Verma } 2326706d0891SRahul Verma } else { 2327706d0891SRahul Verma qed_fill_link(hwfn, NULL, if_link); 2328706d0891SRahul Verma } 232936558c3dSYuval Mintz 233036558c3dSYuval Mintz for_each_hwfn(cdev, i) 233136558c3dSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 2332cc875c2eSYuval Mintz } 2333cc875c2eSYuval Mintz 2334706d0891SRahul Verma void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt) 2335cc875c2eSYuval Mintz { 2336cc875c2eSYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 2337cc875c2eSYuval Mintz struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 2338cc875c2eSYuval Mintz struct qed_link_output if_link; 2339cc875c2eSYuval Mintz 2340706d0891SRahul Verma qed_fill_link(hwfn, ptt, &if_link); 234136558c3dSYuval Mintz qed_inform_vf_link_state(hwfn); 2342cc875c2eSYuval Mintz 2343cc875c2eSYuval Mintz if (IS_LEAD_HWFN(hwfn) && cookie) 2344cc875c2eSYuval Mintz op->link_update(cookie, &if_link); 2345cc875c2eSYuval Mintz } 2346cc875c2eSYuval Mintz 2347699fed4aSSudarsana Reddy Kalluru void qed_bw_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt) 2348699fed4aSSudarsana Reddy Kalluru { 2349699fed4aSSudarsana Reddy Kalluru void *cookie = hwfn->cdev->ops_cookie; 2350699fed4aSSudarsana Reddy Kalluru struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 2351699fed4aSSudarsana Reddy Kalluru 2352699fed4aSSudarsana Reddy Kalluru if (IS_LEAD_HWFN(hwfn) && cookie && op && op->bw_update) 2353699fed4aSSudarsana Reddy Kalluru op->bw_update(cookie); 2354699fed4aSSudarsana Reddy Kalluru } 2355699fed4aSSudarsana Reddy Kalluru 2356fe56b9e6SYuval Mintz static int qed_drain(struct qed_dev *cdev) 2357fe56b9e6SYuval Mintz { 2358fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 2359fe56b9e6SYuval Mintz struct qed_ptt *ptt; 2360fe56b9e6SYuval Mintz int i, rc; 2361fe56b9e6SYuval Mintz 23621408cc1fSYuval Mintz if (IS_VF(cdev)) 23631408cc1fSYuval Mintz return 0; 23641408cc1fSYuval Mintz 2365fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 2366fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 2367fe56b9e6SYuval Mintz ptt = qed_ptt_acquire(hwfn); 2368fe56b9e6SYuval Mintz if (!ptt) { 2369fe56b9e6SYuval Mintz DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n"); 2370fe56b9e6SYuval Mintz return -EBUSY; 2371fe56b9e6SYuval Mintz } 2372fe56b9e6SYuval Mintz rc = qed_mcp_drain(hwfn, ptt); 23739aaa4e8bSDenis Bolotin qed_ptt_release(hwfn, ptt); 2374fe56b9e6SYuval Mintz if (rc) 2375fe56b9e6SYuval Mintz return rc; 2376fe56b9e6SYuval Mintz } 2377fe56b9e6SYuval Mintz 2378fe56b9e6SYuval Mintz return 0; 2379fe56b9e6SYuval Mintz } 2380fe56b9e6SYuval Mintz 23813a69cae8SSudarsana Reddy Kalluru static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev, 23823a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att *nvm_image, 23833a69cae8SSudarsana Reddy Kalluru u32 *crc) 23843a69cae8SSudarsana Reddy Kalluru { 23853a69cae8SSudarsana Reddy Kalluru u8 *buf = NULL; 23865ab90341SAlexander Lobakin int rc; 23873a69cae8SSudarsana Reddy Kalluru 23883a69cae8SSudarsana Reddy Kalluru /* Allocate a buffer for holding the nvram image */ 23893a69cae8SSudarsana Reddy Kalluru buf = kzalloc(nvm_image->length, GFP_KERNEL); 23903a69cae8SSudarsana Reddy Kalluru if (!buf) 23913a69cae8SSudarsana Reddy Kalluru return -ENOMEM; 23923a69cae8SSudarsana Reddy Kalluru 23933a69cae8SSudarsana Reddy Kalluru /* Read image into buffer */ 23943a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr, 23953a69cae8SSudarsana Reddy Kalluru buf, nvm_image->length); 23963a69cae8SSudarsana Reddy Kalluru if (rc) { 23973a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading image from nvm\n"); 23983a69cae8SSudarsana Reddy Kalluru goto out; 23993a69cae8SSudarsana Reddy Kalluru } 24003a69cae8SSudarsana Reddy Kalluru 24013a69cae8SSudarsana Reddy Kalluru /* Convert the buffer into big-endian format (excluding the 24023a69cae8SSudarsana Reddy Kalluru * closing 4 bytes of CRC). 24033a69cae8SSudarsana Reddy Kalluru */ 24045ab90341SAlexander Lobakin cpu_to_be32_array((__force __be32 *)buf, (const u32 *)buf, 24055ab90341SAlexander Lobakin DIV_ROUND_UP(nvm_image->length - 4, 4)); 24063a69cae8SSudarsana Reddy Kalluru 24073a69cae8SSudarsana Reddy Kalluru /* Calc CRC for the "actual" image buffer, i.e. not including 24083a69cae8SSudarsana Reddy Kalluru * the last 4 CRC bytes. 24093a69cae8SSudarsana Reddy Kalluru */ 24105ab90341SAlexander Lobakin *crc = ~crc32(~0U, buf, nvm_image->length - 4); 24115ab90341SAlexander Lobakin *crc = (__force u32)cpu_to_be32p(crc); 24123a69cae8SSudarsana Reddy Kalluru 24133a69cae8SSudarsana Reddy Kalluru out: 24143a69cae8SSudarsana Reddy Kalluru kfree(buf); 24153a69cae8SSudarsana Reddy Kalluru 24163a69cae8SSudarsana Reddy Kalluru return rc; 24173a69cae8SSudarsana Reddy Kalluru } 24183a69cae8SSudarsana Reddy Kalluru 24193a69cae8SSudarsana Reddy Kalluru /* Binary file format - 24203a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 24213a69cae8SSudarsana Reddy Kalluru * 0B | 0x4 [command index] | 24223a69cae8SSudarsana Reddy Kalluru * 4B | image_type | Options | Number of register settings | 24233a69cae8SSudarsana Reddy Kalluru * 8B | Value | 24243a69cae8SSudarsana Reddy Kalluru * 12B | Mask | 24253a69cae8SSudarsana Reddy Kalluru * 16B | Offset | 24263a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 24273a69cae8SSudarsana Reddy Kalluru * There can be several Value-Mask-Offset sets as specified by 'Number of...'. 24283a69cae8SSudarsana Reddy Kalluru * Options - 0'b - Calculate & Update CRC for image 24293a69cae8SSudarsana Reddy Kalluru */ 24303a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data, 24313a69cae8SSudarsana Reddy Kalluru bool *check_resp) 24323a69cae8SSudarsana Reddy Kalluru { 24333a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att nvm_image; 24343a69cae8SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn; 24353a69cae8SSudarsana Reddy Kalluru bool is_crc = false; 24363a69cae8SSudarsana Reddy Kalluru u32 image_type; 24373a69cae8SSudarsana Reddy Kalluru int rc = 0, i; 24383a69cae8SSudarsana Reddy Kalluru u16 len; 24393a69cae8SSudarsana Reddy Kalluru 24403a69cae8SSudarsana Reddy Kalluru *data += 4; 24413a69cae8SSudarsana Reddy Kalluru image_type = **data; 24423a69cae8SSudarsana Reddy Kalluru p_hwfn = QED_LEADING_HWFN(cdev); 24433a69cae8SSudarsana Reddy Kalluru for (i = 0; i < p_hwfn->nvm_info.num_images; i++) 24443a69cae8SSudarsana Reddy Kalluru if (image_type == p_hwfn->nvm_info.image_att[i].image_type) 24453a69cae8SSudarsana Reddy Kalluru break; 24463a69cae8SSudarsana Reddy Kalluru if (i == p_hwfn->nvm_info.num_images) { 24473a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find nvram image of type %08x\n", 24483a69cae8SSudarsana Reddy Kalluru image_type); 24493a69cae8SSudarsana Reddy Kalluru return -ENOENT; 24503a69cae8SSudarsana Reddy Kalluru } 24513a69cae8SSudarsana Reddy Kalluru 24523a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr; 24533a69cae8SSudarsana Reddy Kalluru nvm_image.length = p_hwfn->nvm_info.image_att[i].len; 24543a69cae8SSudarsana Reddy Kalluru 24553a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 24563a69cae8SSudarsana Reddy Kalluru "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n", 24573a69cae8SSudarsana Reddy Kalluru **data, image_type, nvm_image.start_addr, 24583a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 1); 24593a69cae8SSudarsana Reddy Kalluru (*data)++; 24603a69cae8SSudarsana Reddy Kalluru is_crc = !!(**data & BIT(0)); 24613a69cae8SSudarsana Reddy Kalluru (*data)++; 24623a69cae8SSudarsana Reddy Kalluru len = *((u16 *)*data); 24633a69cae8SSudarsana Reddy Kalluru *data += 2; 24643a69cae8SSudarsana Reddy Kalluru if (is_crc) { 24653a69cae8SSudarsana Reddy Kalluru u32 crc = 0; 24663a69cae8SSudarsana Reddy Kalluru 24673a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc); 24683a69cae8SSudarsana Reddy Kalluru if (rc) { 24693a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc); 24703a69cae8SSudarsana Reddy Kalluru goto exit; 24713a69cae8SSudarsana Reddy Kalluru } 24723a69cae8SSudarsana Reddy Kalluru 24733a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM, 24743a69cae8SSudarsana Reddy Kalluru (nvm_image.start_addr + 24753a69cae8SSudarsana Reddy Kalluru nvm_image.length - 4), (u8 *)&crc, 4); 24763a69cae8SSudarsana Reddy Kalluru if (rc) 24773a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x, rc = %d\n", 24783a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 4, rc); 24793a69cae8SSudarsana Reddy Kalluru goto exit; 24803a69cae8SSudarsana Reddy Kalluru } 24813a69cae8SSudarsana Reddy Kalluru 24823a69cae8SSudarsana Reddy Kalluru /* Iterate over the values for setting */ 24833a69cae8SSudarsana Reddy Kalluru while (len) { 24843a69cae8SSudarsana Reddy Kalluru u32 offset, mask, value, cur_value; 24853a69cae8SSudarsana Reddy Kalluru u8 buf[4]; 24863a69cae8SSudarsana Reddy Kalluru 24873a69cae8SSudarsana Reddy Kalluru value = *((u32 *)*data); 24883a69cae8SSudarsana Reddy Kalluru *data += 4; 24893a69cae8SSudarsana Reddy Kalluru mask = *((u32 *)*data); 24903a69cae8SSudarsana Reddy Kalluru *data += 4; 24913a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)*data); 24923a69cae8SSudarsana Reddy Kalluru *data += 4; 24933a69cae8SSudarsana Reddy Kalluru 24943a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf, 24953a69cae8SSudarsana Reddy Kalluru 4); 24963a69cae8SSudarsana Reddy Kalluru if (rc) { 24973a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading from %08x\n", 24983a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset); 24993a69cae8SSudarsana Reddy Kalluru goto exit; 25003a69cae8SSudarsana Reddy Kalluru } 25013a69cae8SSudarsana Reddy Kalluru 25023a69cae8SSudarsana Reddy Kalluru cur_value = le32_to_cpu(*((__le32 *)buf)); 25033a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 25043a69cae8SSudarsana Reddy Kalluru "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n", 25053a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, cur_value, 25063a69cae8SSudarsana Reddy Kalluru (cur_value & ~mask) | (value & mask), value, mask); 25073a69cae8SSudarsana Reddy Kalluru value = (value & mask) | (cur_value & ~mask); 25083a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM, 25093a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, 25103a69cae8SSudarsana Reddy Kalluru (u8 *)&value, 4); 25113a69cae8SSudarsana Reddy Kalluru if (rc) { 25123a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x\n", 25133a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset); 25143a69cae8SSudarsana Reddy Kalluru goto exit; 25153a69cae8SSudarsana Reddy Kalluru } 25163a69cae8SSudarsana Reddy Kalluru 25173a69cae8SSudarsana Reddy Kalluru len--; 25183a69cae8SSudarsana Reddy Kalluru } 25193a69cae8SSudarsana Reddy Kalluru exit: 25203a69cae8SSudarsana Reddy Kalluru return rc; 25213a69cae8SSudarsana Reddy Kalluru } 25223a69cae8SSudarsana Reddy Kalluru 25233a69cae8SSudarsana Reddy Kalluru /* Binary file format - 25243a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 25253a69cae8SSudarsana Reddy Kalluru * 0B | 0x3 [command index] | 25263a69cae8SSudarsana Reddy Kalluru * 4B | b'0: check_response? | b'1-31 reserved | 25273a69cae8SSudarsana Reddy Kalluru * 8B | File-type | reserved | 2528057d2b19SSudarsana Reddy Kalluru * 12B | Image length in bytes | 25293a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 25303a69cae8SSudarsana Reddy Kalluru * Start a new file of the provided type 25313a69cae8SSudarsana Reddy Kalluru */ 25323a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_start(struct qed_dev *cdev, 25333a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp) 25343a69cae8SSudarsana Reddy Kalluru { 2535057d2b19SSudarsana Reddy Kalluru u32 file_type, file_size = 0; 25363a69cae8SSudarsana Reddy Kalluru int rc; 25373a69cae8SSudarsana Reddy Kalluru 25383a69cae8SSudarsana Reddy Kalluru *data += 4; 25393a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0)); 25403a69cae8SSudarsana Reddy Kalluru *data += 4; 2541057d2b19SSudarsana Reddy Kalluru file_type = **data; 25423a69cae8SSudarsana Reddy Kalluru 25433a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 2544057d2b19SSudarsana Reddy Kalluru "About to start a new file of type %02x\n", file_type); 2545057d2b19SSudarsana Reddy Kalluru if (file_type == DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MBI) { 2546057d2b19SSudarsana Reddy Kalluru *data += 4; 2547057d2b19SSudarsana Reddy Kalluru file_size = *((u32 *)(*data)); 2548057d2b19SSudarsana Reddy Kalluru } 2549057d2b19SSudarsana Reddy Kalluru 2550057d2b19SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_BEGIN, file_type, 2551057d2b19SSudarsana Reddy Kalluru (u8 *)(&file_size), 4); 25523a69cae8SSudarsana Reddy Kalluru *data += 4; 25533a69cae8SSudarsana Reddy Kalluru 25543a69cae8SSudarsana Reddy Kalluru return rc; 25553a69cae8SSudarsana Reddy Kalluru } 25563a69cae8SSudarsana Reddy Kalluru 25573a69cae8SSudarsana Reddy Kalluru /* Binary file format - 25583a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 25593a69cae8SSudarsana Reddy Kalluru * 0B | 0x2 [command index] | 25603a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes | 25613a69cae8SSudarsana Reddy Kalluru * 8B | b'0: check_response? | b'1-31 reserved | 25623a69cae8SSudarsana Reddy Kalluru * 12B | Offset in bytes | 25633a69cae8SSudarsana Reddy Kalluru * 16B | Data ... | 25643a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 25653a69cae8SSudarsana Reddy Kalluru * Write data as part of a file that was previously started. Data should be 25663a69cae8SSudarsana Reddy Kalluru * of length equal to that provided in the message 25673a69cae8SSudarsana Reddy Kalluru */ 25683a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_data(struct qed_dev *cdev, 25693a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp) 25703a69cae8SSudarsana Reddy Kalluru { 25713a69cae8SSudarsana Reddy Kalluru u32 offset, len; 25723a69cae8SSudarsana Reddy Kalluru int rc; 25733a69cae8SSudarsana Reddy Kalluru 25743a69cae8SSudarsana Reddy Kalluru *data += 4; 25753a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data)); 25763a69cae8SSudarsana Reddy Kalluru *data += 4; 25773a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0)); 25783a69cae8SSudarsana Reddy Kalluru *data += 4; 25793a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)(*data)); 25803a69cae8SSudarsana Reddy Kalluru *data += 4; 25813a69cae8SSudarsana Reddy Kalluru 25823a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 25833a69cae8SSudarsana Reddy Kalluru "About to write File-data: %08x bytes to offset %08x\n", 25843a69cae8SSudarsana Reddy Kalluru len, offset); 25853a69cae8SSudarsana Reddy Kalluru 25863a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset, 25873a69cae8SSudarsana Reddy Kalluru (char *)(*data), len); 25883a69cae8SSudarsana Reddy Kalluru *data += len; 25893a69cae8SSudarsana Reddy Kalluru 25903a69cae8SSudarsana Reddy Kalluru return rc; 25913a69cae8SSudarsana Reddy Kalluru } 25923a69cae8SSudarsana Reddy Kalluru 25933a69cae8SSudarsana Reddy Kalluru /* Binary file format [General header] - 25943a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 25953a69cae8SSudarsana Reddy Kalluru * 0B | QED_NVM_SIGNATURE | 25963a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes | 25973a69cae8SSudarsana Reddy Kalluru * 8B | Highest command in this batchfile | Reserved | 25983a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 25993a69cae8SSudarsana Reddy Kalluru */ 26003a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_validate(struct qed_dev *cdev, 26013a69cae8SSudarsana Reddy Kalluru const struct firmware *image, 26023a69cae8SSudarsana Reddy Kalluru const u8 **data) 26033a69cae8SSudarsana Reddy Kalluru { 26043a69cae8SSudarsana Reddy Kalluru u32 signature, len; 26053a69cae8SSudarsana Reddy Kalluru 26063a69cae8SSudarsana Reddy Kalluru /* Check minimum size */ 26073a69cae8SSudarsana Reddy Kalluru if (image->size < 12) { 26083a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size); 26093a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26103a69cae8SSudarsana Reddy Kalluru } 26113a69cae8SSudarsana Reddy Kalluru 26123a69cae8SSudarsana Reddy Kalluru /* Check signature */ 26133a69cae8SSudarsana Reddy Kalluru signature = *((u32 *)(*data)); 26143a69cae8SSudarsana Reddy Kalluru if (signature != QED_NVM_SIGNATURE) { 26153a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Wrong signature '%08x'\n", signature); 26163a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26173a69cae8SSudarsana Reddy Kalluru } 26183a69cae8SSudarsana Reddy Kalluru 26193a69cae8SSudarsana Reddy Kalluru *data += 4; 26203a69cae8SSudarsana Reddy Kalluru /* Validate internal size equals the image-size */ 26213a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data)); 26223a69cae8SSudarsana Reddy Kalluru if (len != image->size) { 26233a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n", 26243a69cae8SSudarsana Reddy Kalluru len, (u32)image->size); 26253a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26263a69cae8SSudarsana Reddy Kalluru } 26273a69cae8SSudarsana Reddy Kalluru 26283a69cae8SSudarsana Reddy Kalluru *data += 4; 26293a69cae8SSudarsana Reddy Kalluru /* Make sure driver familiar with all commands necessary for this */ 26303a69cae8SSudarsana Reddy Kalluru if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) { 26313a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n", 26323a69cae8SSudarsana Reddy Kalluru *((u16 *)(*data))); 26333a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26343a69cae8SSudarsana Reddy Kalluru } 26353a69cae8SSudarsana Reddy Kalluru 26363a69cae8SSudarsana Reddy Kalluru *data += 4; 26373a69cae8SSudarsana Reddy Kalluru 26383a69cae8SSudarsana Reddy Kalluru return 0; 26393a69cae8SSudarsana Reddy Kalluru } 26403a69cae8SSudarsana Reddy Kalluru 26410dabbe1bSSudarsana Reddy Kalluru /* Binary file format - 26420dabbe1bSSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 26430dabbe1bSSudarsana Reddy Kalluru * 0B | 0x5 [command index] | 26442da244a5SSudarsana Reddy Kalluru * 4B | Number of config attributes | Reserved | 26452da244a5SSudarsana Reddy Kalluru * 4B | Config ID | Entity ID | Length | 26462da244a5SSudarsana Reddy Kalluru * 4B | Value | 26470dabbe1bSSudarsana Reddy Kalluru * | | 26480dabbe1bSSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 26492da244a5SSudarsana Reddy Kalluru * There can be several cfg_id-entity_id-Length-Value sets as specified by 26502da244a5SSudarsana Reddy Kalluru * 'Number of config attributes'. 26510dabbe1bSSudarsana Reddy Kalluru * 26520dabbe1bSSudarsana Reddy Kalluru * The API parses config attributes from the user provided buffer and flashes 26530dabbe1bSSudarsana Reddy Kalluru * them to the respective NVM path using Management FW inerface. 26540dabbe1bSSudarsana Reddy Kalluru */ 26550dabbe1bSSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data) 26560dabbe1bSSudarsana Reddy Kalluru { 26570dabbe1bSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 26580dabbe1bSSudarsana Reddy Kalluru u8 entity_id, len, buf[32]; 2659c63b0968SSudarsana Reddy Kalluru bool need_nvm_init = true; 26600dabbe1bSSudarsana Reddy Kalluru struct qed_ptt *ptt; 26610dabbe1bSSudarsana Reddy Kalluru u16 cfg_id, count; 26620dabbe1bSSudarsana Reddy Kalluru int rc = 0, i; 26630dabbe1bSSudarsana Reddy Kalluru u32 flags; 26640dabbe1bSSudarsana Reddy Kalluru 26650dabbe1bSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 26660dabbe1bSSudarsana Reddy Kalluru if (!ptt) 26670dabbe1bSSudarsana Reddy Kalluru return -EAGAIN; 26680dabbe1bSSudarsana Reddy Kalluru 26690dabbe1bSSudarsana Reddy Kalluru /* NVM CFG ID attribute header */ 26700dabbe1bSSudarsana Reddy Kalluru *data += 4; 26710dabbe1bSSudarsana Reddy Kalluru count = *((u16 *)*data); 26722da244a5SSudarsana Reddy Kalluru *data += 4; 26730dabbe1bSSudarsana Reddy Kalluru 26740dabbe1bSSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 26752da244a5SSudarsana Reddy Kalluru "Read config ids: num_attrs = %0d\n", count); 2676c63b0968SSudarsana Reddy Kalluru /* NVM CFG ID attributes. Start loop index from 1 to avoid additional 2677c63b0968SSudarsana Reddy Kalluru * arithmetic operations in the implementation. 2678c63b0968SSudarsana Reddy Kalluru */ 2679c63b0968SSudarsana Reddy Kalluru for (i = 1; i <= count; i++) { 26800dabbe1bSSudarsana Reddy Kalluru cfg_id = *((u16 *)*data); 26810dabbe1bSSudarsana Reddy Kalluru *data += 2; 26822da244a5SSudarsana Reddy Kalluru entity_id = **data; 26832da244a5SSudarsana Reddy Kalluru (*data)++; 26840dabbe1bSSudarsana Reddy Kalluru len = **data; 26850dabbe1bSSudarsana Reddy Kalluru (*data)++; 26860dabbe1bSSudarsana Reddy Kalluru memcpy(buf, *data, len); 26870dabbe1bSSudarsana Reddy Kalluru *data += len; 26880dabbe1bSSudarsana Reddy Kalluru 2689c63b0968SSudarsana Reddy Kalluru flags = 0; 2690c63b0968SSudarsana Reddy Kalluru if (need_nvm_init) { 2691c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_INIT; 2692c63b0968SSudarsana Reddy Kalluru need_nvm_init = false; 2693c63b0968SSudarsana Reddy Kalluru } 2694c63b0968SSudarsana Reddy Kalluru 2695c63b0968SSudarsana Reddy Kalluru /* Commit to flash and free the resources */ 2696c63b0968SSudarsana Reddy Kalluru if (!(i % QED_NVM_CFG_MAX_ATTRS) || i == count) { 2697c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_COMMIT | 2698c63b0968SSudarsana Reddy Kalluru QED_NVM_CFG_OPTION_FREE; 2699c63b0968SSudarsana Reddy Kalluru need_nvm_init = true; 2700c63b0968SSudarsana Reddy Kalluru } 2701c63b0968SSudarsana Reddy Kalluru 2702c63b0968SSudarsana Reddy Kalluru if (entity_id) 2703c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_ENTITY_SEL; 27040dabbe1bSSudarsana Reddy Kalluru 27050dabbe1bSSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 27062da244a5SSudarsana Reddy Kalluru "cfg_id = %d entity = %d len = %d\n", cfg_id, 27072da244a5SSudarsana Reddy Kalluru entity_id, len); 27080dabbe1bSSudarsana Reddy Kalluru rc = qed_mcp_nvm_set_cfg(hwfn, ptt, cfg_id, entity_id, flags, 27090dabbe1bSSudarsana Reddy Kalluru buf, len); 27100dabbe1bSSudarsana Reddy Kalluru if (rc) { 27110dabbe1bSSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d configuring %d\n", rc, cfg_id); 27120dabbe1bSSudarsana Reddy Kalluru break; 27130dabbe1bSSudarsana Reddy Kalluru } 27140dabbe1bSSudarsana Reddy Kalluru } 27150dabbe1bSSudarsana Reddy Kalluru 27160dabbe1bSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 27170dabbe1bSSudarsana Reddy Kalluru 27180dabbe1bSSudarsana Reddy Kalluru return rc; 27190dabbe1bSSudarsana Reddy Kalluru } 27200dabbe1bSSudarsana Reddy Kalluru 27219e54ba7cSSudarsana Reddy Kalluru #define QED_MAX_NVM_BUF_LEN 32 27229e54ba7cSSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_len(struct qed_dev *cdev, u32 cmd) 27239e54ba7cSSudarsana Reddy Kalluru { 27249e54ba7cSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 27259e54ba7cSSudarsana Reddy Kalluru u8 buf[QED_MAX_NVM_BUF_LEN]; 27269e54ba7cSSudarsana Reddy Kalluru struct qed_ptt *ptt; 27279e54ba7cSSudarsana Reddy Kalluru u32 len; 27289e54ba7cSSudarsana Reddy Kalluru int rc; 27299e54ba7cSSudarsana Reddy Kalluru 27309e54ba7cSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 27319e54ba7cSSudarsana Reddy Kalluru if (!ptt) 27329e54ba7cSSudarsana Reddy Kalluru return QED_MAX_NVM_BUF_LEN; 27339e54ba7cSSudarsana Reddy Kalluru 27349e54ba7cSSudarsana Reddy Kalluru rc = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, 0, QED_NVM_CFG_GET_FLAGS, buf, 27359e54ba7cSSudarsana Reddy Kalluru &len); 27369e54ba7cSSudarsana Reddy Kalluru if (rc || !len) { 27379e54ba7cSSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d reading %d\n", rc, cmd); 27389e54ba7cSSudarsana Reddy Kalluru len = QED_MAX_NVM_BUF_LEN; 27399e54ba7cSSudarsana Reddy Kalluru } 27409e54ba7cSSudarsana Reddy Kalluru 27419e54ba7cSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 27429e54ba7cSSudarsana Reddy Kalluru 27439e54ba7cSSudarsana Reddy Kalluru return len; 27449e54ba7cSSudarsana Reddy Kalluru } 27459e54ba7cSSudarsana Reddy Kalluru 27462d4c8495SSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_read(struct qed_dev *cdev, u8 **data, 27472d4c8495SSudarsana Reddy Kalluru u32 cmd, u32 entity_id) 27482d4c8495SSudarsana Reddy Kalluru { 27492d4c8495SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 27502d4c8495SSudarsana Reddy Kalluru struct qed_ptt *ptt; 27512d4c8495SSudarsana Reddy Kalluru u32 flags, len; 27522d4c8495SSudarsana Reddy Kalluru int rc = 0; 27532d4c8495SSudarsana Reddy Kalluru 27542d4c8495SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 27552d4c8495SSudarsana Reddy Kalluru if (!ptt) 27562d4c8495SSudarsana Reddy Kalluru return -EAGAIN; 27572d4c8495SSudarsana Reddy Kalluru 27582d4c8495SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 27592d4c8495SSudarsana Reddy Kalluru "Read config cmd = %d entity id %d\n", cmd, entity_id); 27602d4c8495SSudarsana Reddy Kalluru flags = entity_id ? QED_NVM_CFG_GET_PF_FLAGS : QED_NVM_CFG_GET_FLAGS; 27612d4c8495SSudarsana Reddy Kalluru rc = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, entity_id, flags, *data, &len); 27622d4c8495SSudarsana Reddy Kalluru if (rc) 27632d4c8495SSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d reading %d\n", rc, cmd); 27642d4c8495SSudarsana Reddy Kalluru 27652d4c8495SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 27662d4c8495SSudarsana Reddy Kalluru 27672d4c8495SSudarsana Reddy Kalluru return rc; 27682d4c8495SSudarsana Reddy Kalluru } 27692d4c8495SSudarsana Reddy Kalluru 27703a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash(struct qed_dev *cdev, const char *name) 27713a69cae8SSudarsana Reddy Kalluru { 27723a69cae8SSudarsana Reddy Kalluru const struct firmware *image; 27733a69cae8SSudarsana Reddy Kalluru const u8 *data, *data_end; 27743a69cae8SSudarsana Reddy Kalluru u32 cmd_type; 27753a69cae8SSudarsana Reddy Kalluru int rc; 27763a69cae8SSudarsana Reddy Kalluru 27773a69cae8SSudarsana Reddy Kalluru rc = request_firmware(&image, name, &cdev->pdev->dev); 27783a69cae8SSudarsana Reddy Kalluru if (rc) { 27793a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find '%s'\n", name); 27803a69cae8SSudarsana Reddy Kalluru return rc; 27813a69cae8SSudarsana Reddy Kalluru } 27823a69cae8SSudarsana Reddy Kalluru 27833a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 27843a69cae8SSudarsana Reddy Kalluru "Flashing '%s' - firmware's data at %p, size is %08x\n", 27853a69cae8SSudarsana Reddy Kalluru name, image->data, (u32)image->size); 27863a69cae8SSudarsana Reddy Kalluru data = image->data; 27873a69cae8SSudarsana Reddy Kalluru data_end = data + image->size; 27883a69cae8SSudarsana Reddy Kalluru 27893a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_validate(cdev, image, &data); 27903a69cae8SSudarsana Reddy Kalluru if (rc) 27913a69cae8SSudarsana Reddy Kalluru goto exit; 27923a69cae8SSudarsana Reddy Kalluru 27933a69cae8SSudarsana Reddy Kalluru while (data < data_end) { 27943a69cae8SSudarsana Reddy Kalluru bool check_resp = false; 27953a69cae8SSudarsana Reddy Kalluru 27963a69cae8SSudarsana Reddy Kalluru /* Parse the actual command */ 27973a69cae8SSudarsana Reddy Kalluru cmd_type = *((u32 *)data); 27983a69cae8SSudarsana Reddy Kalluru switch (cmd_type) { 27993a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_DATA: 28003a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_data(cdev, &data, 28013a69cae8SSudarsana Reddy Kalluru &check_resp); 28023a69cae8SSudarsana Reddy Kalluru break; 28033a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_START: 28043a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_start(cdev, &data, 28053a69cae8SSudarsana Reddy Kalluru &check_resp); 28063a69cae8SSudarsana Reddy Kalluru break; 28073a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CHANGE: 28083a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access(cdev, &data, 28093a69cae8SSudarsana Reddy Kalluru &check_resp); 28103a69cae8SSudarsana Reddy Kalluru break; 28110dabbe1bSSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CFG_ID: 28120dabbe1bSSudarsana Reddy Kalluru rc = qed_nvm_flash_cfg_write(cdev, &data); 28130dabbe1bSSudarsana Reddy Kalluru break; 28143a69cae8SSudarsana Reddy Kalluru default: 28153a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Unknown command %08x\n", cmd_type); 28163a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 28173a69cae8SSudarsana Reddy Kalluru goto exit; 28183a69cae8SSudarsana Reddy Kalluru } 28193a69cae8SSudarsana Reddy Kalluru 28203a69cae8SSudarsana Reddy Kalluru if (rc) { 28213a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Command %08x failed\n", cmd_type); 28223a69cae8SSudarsana Reddy Kalluru goto exit; 28233a69cae8SSudarsana Reddy Kalluru } 28243a69cae8SSudarsana Reddy Kalluru 28253a69cae8SSudarsana Reddy Kalluru /* Check response if needed */ 28263a69cae8SSudarsana Reddy Kalluru if (check_resp) { 28273a69cae8SSudarsana Reddy Kalluru u32 mcp_response = 0; 28283a69cae8SSudarsana Reddy Kalluru 28293a69cae8SSudarsana Reddy Kalluru if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) { 28303a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed getting MCP response\n"); 28313a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 28323a69cae8SSudarsana Reddy Kalluru goto exit; 28333a69cae8SSudarsana Reddy Kalluru } 28343a69cae8SSudarsana Reddy Kalluru 28353a69cae8SSudarsana Reddy Kalluru switch (mcp_response & FW_MSG_CODE_MASK) { 28363a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_OK: 28373a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_OK: 28383a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK: 28393a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_PHY_OK: 28403a69cae8SSudarsana Reddy Kalluru break; 28413a69cae8SSudarsana Reddy Kalluru default: 28423a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "MFW returns error: %08x\n", 28433a69cae8SSudarsana Reddy Kalluru mcp_response); 28443a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 28453a69cae8SSudarsana Reddy Kalluru goto exit; 28463a69cae8SSudarsana Reddy Kalluru } 28473a69cae8SSudarsana Reddy Kalluru } 28483a69cae8SSudarsana Reddy Kalluru } 28493a69cae8SSudarsana Reddy Kalluru 28503a69cae8SSudarsana Reddy Kalluru exit: 28513a69cae8SSudarsana Reddy Kalluru release_firmware(image); 28523a69cae8SSudarsana Reddy Kalluru 28533a69cae8SSudarsana Reddy Kalluru return rc; 28543a69cae8SSudarsana Reddy Kalluru } 28553a69cae8SSudarsana Reddy Kalluru 285620675b37SMintz, Yuval static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type, 285720675b37SMintz, Yuval u8 *buf, u16 len) 285820675b37SMintz, Yuval { 285920675b37SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 286020675b37SMintz, Yuval 2861b60bfdfeSDenis Bolotin return qed_mcp_get_nvm_image(hwfn, type, buf, len); 286220675b37SMintz, Yuval } 286320675b37SMintz, Yuval 286464515dc8STomer Tayar void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn) 286564515dc8STomer Tayar { 286664515dc8STomer Tayar struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common; 286764515dc8STomer Tayar void *cookie = p_hwfn->cdev->ops_cookie; 286864515dc8STomer Tayar 286964515dc8STomer Tayar if (ops && ops->schedule_recovery_handler) 287064515dc8STomer Tayar ops->schedule_recovery_handler(cookie); 287164515dc8STomer Tayar } 287264515dc8STomer Tayar 2873c6b7314dSAlexander Lobakin static const char * const qed_hw_err_type_descr[] = { 2874d639836aSIgor Russkikh [QED_HW_ERR_FAN_FAIL] = "Fan Failure", 2875d639836aSIgor Russkikh [QED_HW_ERR_MFW_RESP_FAIL] = "MFW Response Failure", 2876d639836aSIgor Russkikh [QED_HW_ERR_HW_ATTN] = "HW Attention", 2877d639836aSIgor Russkikh [QED_HW_ERR_DMAE_FAIL] = "DMAE Failure", 2878d639836aSIgor Russkikh [QED_HW_ERR_RAMROD_FAIL] = "Ramrod Failure", 2879d639836aSIgor Russkikh [QED_HW_ERR_FW_ASSERT] = "FW Assertion", 2880d639836aSIgor Russkikh [QED_HW_ERR_LAST] = "Unknown", 2881d639836aSIgor Russkikh }; 2882d639836aSIgor Russkikh 2883d639836aSIgor Russkikh void qed_hw_error_occurred(struct qed_hwfn *p_hwfn, 2884d639836aSIgor Russkikh enum qed_hw_err_type err_type) 2885d639836aSIgor Russkikh { 2886d639836aSIgor Russkikh struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common; 2887d639836aSIgor Russkikh void *cookie = p_hwfn->cdev->ops_cookie; 2888c6b7314dSAlexander Lobakin const char *err_str; 2889d639836aSIgor Russkikh 2890d639836aSIgor Russkikh if (err_type > QED_HW_ERR_LAST) 2891d639836aSIgor Russkikh err_type = QED_HW_ERR_LAST; 2892d639836aSIgor Russkikh err_str = qed_hw_err_type_descr[err_type]; 2893d639836aSIgor Russkikh 2894d639836aSIgor Russkikh DP_NOTICE(p_hwfn, "HW error occurred [%s]\n", err_str); 2895d639836aSIgor Russkikh 2896936c7ba4SIgor Russkikh /* Call the HW error handler of the protocol driver. 2897936c7ba4SIgor Russkikh * If it is not available - perform a minimal handling of preventing 2898936c7ba4SIgor Russkikh * HW attentions from being reasserted. 2899d639836aSIgor Russkikh */ 2900d639836aSIgor Russkikh if (ops && ops->schedule_hw_err_handler) 2901d639836aSIgor Russkikh ops->schedule_hw_err_handler(cookie, err_type); 2902936c7ba4SIgor Russkikh else 2903936c7ba4SIgor Russkikh qed_int_attn_clr_enable(p_hwfn->cdev, true); 2904d639836aSIgor Russkikh } 2905d639836aSIgor Russkikh 2906722003acSSudarsana Reddy Kalluru static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, 2907477f2d14SRahul Verma void *handle) 2908722003acSSudarsana Reddy Kalluru { 2909477f2d14SRahul Verma return qed_set_queue_coalesce(rx_coal, tx_coal, handle); 2910722003acSSudarsana Reddy Kalluru } 2911722003acSSudarsana Reddy Kalluru 291291420b83SSudarsana Kalluru static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) 291391420b83SSudarsana Kalluru { 291491420b83SSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 291591420b83SSudarsana Kalluru struct qed_ptt *ptt; 291691420b83SSudarsana Kalluru int status = 0; 291791420b83SSudarsana Kalluru 291891420b83SSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 291991420b83SSudarsana Kalluru if (!ptt) 292091420b83SSudarsana Kalluru return -EAGAIN; 292191420b83SSudarsana Kalluru 292291420b83SSudarsana Kalluru status = qed_mcp_set_led(hwfn, ptt, mode); 292391420b83SSudarsana Kalluru 292491420b83SSudarsana Kalluru qed_ptt_release(hwfn, ptt); 292591420b83SSudarsana Kalluru 292691420b83SSudarsana Kalluru return status; 292791420b83SSudarsana Kalluru } 292891420b83SSudarsana Kalluru 292964515dc8STomer Tayar static int qed_recovery_process(struct qed_dev *cdev) 293064515dc8STomer Tayar { 293164515dc8STomer Tayar struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 293264515dc8STomer Tayar struct qed_ptt *p_ptt; 293364515dc8STomer Tayar int rc = 0; 293464515dc8STomer Tayar 293564515dc8STomer Tayar p_ptt = qed_ptt_acquire(p_hwfn); 293664515dc8STomer Tayar if (!p_ptt) 293764515dc8STomer Tayar return -EAGAIN; 293864515dc8STomer Tayar 293964515dc8STomer Tayar rc = qed_start_recovery_process(p_hwfn, p_ptt); 294064515dc8STomer Tayar 294164515dc8STomer Tayar qed_ptt_release(p_hwfn, p_ptt); 294264515dc8STomer Tayar 294364515dc8STomer Tayar return rc; 294464515dc8STomer Tayar } 294564515dc8STomer Tayar 294614d39648SMintz, Yuval static int qed_update_wol(struct qed_dev *cdev, bool enabled) 294714d39648SMintz, Yuval { 294814d39648SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 294914d39648SMintz, Yuval struct qed_ptt *ptt; 295014d39648SMintz, Yuval int rc = 0; 295114d39648SMintz, Yuval 295214d39648SMintz, Yuval if (IS_VF(cdev)) 295314d39648SMintz, Yuval return 0; 295414d39648SMintz, Yuval 295514d39648SMintz, Yuval ptt = qed_ptt_acquire(hwfn); 295614d39648SMintz, Yuval if (!ptt) 295714d39648SMintz, Yuval return -EAGAIN; 295814d39648SMintz, Yuval 295914d39648SMintz, Yuval rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED 296014d39648SMintz, Yuval : QED_OV_WOL_DISABLED); 296114d39648SMintz, Yuval if (rc) 296214d39648SMintz, Yuval goto out; 296314d39648SMintz, Yuval rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 296414d39648SMintz, Yuval 296514d39648SMintz, Yuval out: 296614d39648SMintz, Yuval qed_ptt_release(hwfn, ptt); 296714d39648SMintz, Yuval return rc; 296814d39648SMintz, Yuval } 296914d39648SMintz, Yuval 29700fefbfbaSSudarsana Kalluru static int qed_update_drv_state(struct qed_dev *cdev, bool active) 29710fefbfbaSSudarsana Kalluru { 29720fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 29730fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 29740fefbfbaSSudarsana Kalluru int status = 0; 29750fefbfbaSSudarsana Kalluru 29760fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 29770fefbfbaSSudarsana Kalluru return 0; 29780fefbfbaSSudarsana Kalluru 29790fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 29800fefbfbaSSudarsana Kalluru if (!ptt) 29810fefbfbaSSudarsana Kalluru return -EAGAIN; 29820fefbfbaSSudarsana Kalluru 29830fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ? 29840fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_ACTIVE : 29850fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_DISABLED); 29860fefbfbaSSudarsana Kalluru 29870fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 29880fefbfbaSSudarsana Kalluru 29890fefbfbaSSudarsana Kalluru return status; 29900fefbfbaSSudarsana Kalluru } 29910fefbfbaSSudarsana Kalluru 29920fefbfbaSSudarsana Kalluru static int qed_update_mac(struct qed_dev *cdev, u8 *mac) 29930fefbfbaSSudarsana Kalluru { 29940fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 29950fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 29960fefbfbaSSudarsana Kalluru int status = 0; 29970fefbfbaSSudarsana Kalluru 29980fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 29990fefbfbaSSudarsana Kalluru return 0; 30000fefbfbaSSudarsana Kalluru 30010fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 30020fefbfbaSSudarsana Kalluru if (!ptt) 30030fefbfbaSSudarsana Kalluru return -EAGAIN; 30040fefbfbaSSudarsana Kalluru 30050fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mac(hwfn, ptt, mac); 30060fefbfbaSSudarsana Kalluru if (status) 30070fefbfbaSSudarsana Kalluru goto out; 30080fefbfbaSSudarsana Kalluru 30090fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 30100fefbfbaSSudarsana Kalluru 30110fefbfbaSSudarsana Kalluru out: 30120fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 30130fefbfbaSSudarsana Kalluru return status; 30140fefbfbaSSudarsana Kalluru } 30150fefbfbaSSudarsana Kalluru 30160fefbfbaSSudarsana Kalluru static int qed_update_mtu(struct qed_dev *cdev, u16 mtu) 30170fefbfbaSSudarsana Kalluru { 30180fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 30190fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 30200fefbfbaSSudarsana Kalluru int status = 0; 30210fefbfbaSSudarsana Kalluru 30220fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 30230fefbfbaSSudarsana Kalluru return 0; 30240fefbfbaSSudarsana Kalluru 30250fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 30260fefbfbaSSudarsana Kalluru if (!ptt) 30270fefbfbaSSudarsana Kalluru return -EAGAIN; 30280fefbfbaSSudarsana Kalluru 30290fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu); 30300fefbfbaSSudarsana Kalluru if (status) 30310fefbfbaSSudarsana Kalluru goto out; 30320fefbfbaSSudarsana Kalluru 30330fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 30340fefbfbaSSudarsana Kalluru 30350fefbfbaSSudarsana Kalluru out: 30360fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 30370fefbfbaSSudarsana Kalluru return status; 30380fefbfbaSSudarsana Kalluru } 30390fefbfbaSSudarsana Kalluru 3040b51dab46SSudarsana Reddy Kalluru static int qed_read_module_eeprom(struct qed_dev *cdev, char *buf, 3041b51dab46SSudarsana Reddy Kalluru u8 dev_addr, u32 offset, u32 len) 3042b51dab46SSudarsana Reddy Kalluru { 3043b51dab46SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 3044b51dab46SSudarsana Reddy Kalluru struct qed_ptt *ptt; 3045b51dab46SSudarsana Reddy Kalluru int rc = 0; 3046b51dab46SSudarsana Reddy Kalluru 3047b51dab46SSudarsana Reddy Kalluru if (IS_VF(cdev)) 3048b51dab46SSudarsana Reddy Kalluru return 0; 3049b51dab46SSudarsana Reddy Kalluru 3050b51dab46SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 3051b51dab46SSudarsana Reddy Kalluru if (!ptt) 3052b51dab46SSudarsana Reddy Kalluru return -EAGAIN; 3053b51dab46SSudarsana Reddy Kalluru 3054b51dab46SSudarsana Reddy Kalluru rc = qed_mcp_phy_sfp_read(hwfn, ptt, MFW_PORT(hwfn), dev_addr, 3055b51dab46SSudarsana Reddy Kalluru offset, len, buf); 3056b51dab46SSudarsana Reddy Kalluru 3057b51dab46SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 3058b51dab46SSudarsana Reddy Kalluru 3059b51dab46SSudarsana Reddy Kalluru return rc; 3060b51dab46SSudarsana Reddy Kalluru } 3061b51dab46SSudarsana Reddy Kalluru 30623b86bd07SSudarsana Reddy Kalluru static int qed_set_grc_config(struct qed_dev *cdev, u32 cfg_id, u32 val) 30633b86bd07SSudarsana Reddy Kalluru { 30643b86bd07SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 30653b86bd07SSudarsana Reddy Kalluru struct qed_ptt *ptt; 30663b86bd07SSudarsana Reddy Kalluru int rc = 0; 30673b86bd07SSudarsana Reddy Kalluru 30683b86bd07SSudarsana Reddy Kalluru if (IS_VF(cdev)) 30693b86bd07SSudarsana Reddy Kalluru return 0; 30703b86bd07SSudarsana Reddy Kalluru 30713b86bd07SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 30723b86bd07SSudarsana Reddy Kalluru if (!ptt) 30733b86bd07SSudarsana Reddy Kalluru return -EAGAIN; 30743b86bd07SSudarsana Reddy Kalluru 30752d22bc83SMichal Kalderon rc = qed_dbg_grc_config(hwfn, cfg_id, val); 30763b86bd07SSudarsana Reddy Kalluru 30773b86bd07SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 30783b86bd07SSudarsana Reddy Kalluru 30793b86bd07SSudarsana Reddy Kalluru return rc; 30803b86bd07SSudarsana Reddy Kalluru } 30813b86bd07SSudarsana Reddy Kalluru 308208eb1fb0SMichal Kalderon static u8 qed_get_affin_hwfn_idx(struct qed_dev *cdev) 308308eb1fb0SMichal Kalderon { 308408eb1fb0SMichal Kalderon return QED_AFFIN_HWFN_IDX(cdev); 308508eb1fb0SMichal Kalderon } 308608eb1fb0SMichal Kalderon 30878c93beafSYuval Mintz static struct qed_selftest_ops qed_selftest_ops_pass = { 308803dc76caSSudarsana Reddy Kalluru .selftest_memory = &qed_selftest_memory, 308903dc76caSSudarsana Reddy Kalluru .selftest_interrupt = &qed_selftest_interrupt, 309003dc76caSSudarsana Reddy Kalluru .selftest_register = &qed_selftest_register, 309103dc76caSSudarsana Reddy Kalluru .selftest_clock = &qed_selftest_clock, 30927a4b21b7SMintz, Yuval .selftest_nvram = &qed_selftest_nvram, 309303dc76caSSudarsana Reddy Kalluru }; 309403dc76caSSudarsana Reddy Kalluru 3095fe56b9e6SYuval Mintz const struct qed_common_ops qed_common_ops_pass = { 309603dc76caSSudarsana Reddy Kalluru .selftest = &qed_selftest_ops_pass, 3097fe56b9e6SYuval Mintz .probe = &qed_probe, 3098fe56b9e6SYuval Mintz .remove = &qed_remove, 3099fe56b9e6SYuval Mintz .set_power_state = &qed_set_power_state, 3100712c3cbfSMintz, Yuval .set_name = &qed_set_name, 3101fe56b9e6SYuval Mintz .update_pf_params = &qed_update_pf_params, 3102fe56b9e6SYuval Mintz .slowpath_start = &qed_slowpath_start, 3103fe56b9e6SYuval Mintz .slowpath_stop = &qed_slowpath_stop, 3104fe56b9e6SYuval Mintz .set_fp_int = &qed_set_int_fp, 3105fe56b9e6SYuval Mintz .get_fp_int = &qed_get_int_fp, 3106fe56b9e6SYuval Mintz .sb_init = &qed_sb_init, 3107fe56b9e6SYuval Mintz .sb_release = &qed_sb_release, 3108fe56b9e6SYuval Mintz .simd_handler_config = &qed_simd_handler_config, 3109fe56b9e6SYuval Mintz .simd_handler_clean = &qed_simd_handler_clean, 31101e128c81SArun Easi .dbg_grc = &qed_dbg_grc, 31111e128c81SArun Easi .dbg_grc_size = &qed_dbg_grc_size, 3112fe7cd2bfSYuval Mintz .can_link_change = &qed_can_link_change, 3113cc875c2eSYuval Mintz .set_link = &qed_set_link, 3114cc875c2eSYuval Mintz .get_link = &qed_get_current_link, 3115fe56b9e6SYuval Mintz .drain = &qed_drain, 3116fe56b9e6SYuval Mintz .update_msglvl = &qed_init_dp, 3117e0971c83STomer Tayar .dbg_all_data = &qed_dbg_all_data, 3118e0971c83STomer Tayar .dbg_all_data_size = &qed_dbg_all_data_size, 3119fe56b9e6SYuval Mintz .chain_alloc = &qed_chain_alloc, 3120fe56b9e6SYuval Mintz .chain_free = &qed_chain_free, 31213a69cae8SSudarsana Reddy Kalluru .nvm_flash = &qed_nvm_flash, 312220675b37SMintz, Yuval .nvm_get_image = &qed_nvm_get_image, 3123722003acSSudarsana Reddy Kalluru .set_coalesce = &qed_set_coalesce, 312491420b83SSudarsana Kalluru .set_led = &qed_set_led, 312564515dc8STomer Tayar .recovery_process = &qed_recovery_process, 312664515dc8STomer Tayar .recovery_prolog = &qed_recovery_prolog, 3127936c7ba4SIgor Russkikh .attn_clr_enable = &qed_int_attn_clr_enable, 31280fefbfbaSSudarsana Kalluru .update_drv_state = &qed_update_drv_state, 31290fefbfbaSSudarsana Kalluru .update_mac = &qed_update_mac, 31300fefbfbaSSudarsana Kalluru .update_mtu = &qed_update_mtu, 313114d39648SMintz, Yuval .update_wol = &qed_update_wol, 31320e1f1044SAriel Elior .db_recovery_add = &qed_db_recovery_add, 31330e1f1044SAriel Elior .db_recovery_del = &qed_db_recovery_del, 3134b51dab46SSudarsana Reddy Kalluru .read_module_eeprom = &qed_read_module_eeprom, 313508eb1fb0SMichal Kalderon .get_affin_hwfn_idx = &qed_get_affin_hwfn_idx, 31362d4c8495SSudarsana Reddy Kalluru .read_nvm_cfg = &qed_nvm_flash_cfg_read, 31379e54ba7cSSudarsana Reddy Kalluru .read_nvm_cfg_len = &qed_nvm_flash_cfg_len, 31383b86bd07SSudarsana Reddy Kalluru .set_grc_config = &qed_set_grc_config, 3139fe56b9e6SYuval Mintz }; 31406c754246SSudarsana Reddy Kalluru 31416c754246SSudarsana Reddy Kalluru void qed_get_protocol_stats(struct qed_dev *cdev, 31426c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type type, 31436c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats *stats) 31446c754246SSudarsana Reddy Kalluru { 31456c754246SSudarsana Reddy Kalluru struct qed_eth_stats eth_stats; 31466c754246SSudarsana Reddy Kalluru 31476c754246SSudarsana Reddy Kalluru memset(stats, 0, sizeof(*stats)); 31486c754246SSudarsana Reddy Kalluru 31496c754246SSudarsana Reddy Kalluru switch (type) { 31506c754246SSudarsana Reddy Kalluru case QED_MCP_LAN_STATS: 31516c754246SSudarsana Reddy Kalluru qed_get_vport_stats(cdev, ð_stats); 31529c79ddaaSMintz, Yuval stats->lan_stats.ucast_rx_pkts = 31539c79ddaaSMintz, Yuval eth_stats.common.rx_ucast_pkts; 31549c79ddaaSMintz, Yuval stats->lan_stats.ucast_tx_pkts = 31559c79ddaaSMintz, Yuval eth_stats.common.tx_ucast_pkts; 31566c754246SSudarsana Reddy Kalluru stats->lan_stats.fcs_err = -1; 31576c754246SSudarsana Reddy Kalluru break; 31581e128c81SArun Easi case QED_MCP_FCOE_STATS: 31591e128c81SArun Easi qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats); 31601e128c81SArun Easi break; 31612f2b2614SMintz, Yuval case QED_MCP_ISCSI_STATS: 31622f2b2614SMintz, Yuval qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); 31632f2b2614SMintz, Yuval break; 31646c754246SSudarsana Reddy Kalluru default: 3165512c7840SMintz, Yuval DP_VERBOSE(cdev, QED_MSG_SP, 3166512c7840SMintz, Yuval "Invalid protocol type = %d\n", type); 31676c754246SSudarsana Reddy Kalluru return; 31686c754246SSudarsana Reddy Kalluru } 31696c754246SSudarsana Reddy Kalluru } 31702528c389SSudarsana Reddy Kalluru 317159ccf86fSSudarsana Reddy Kalluru int qed_mfw_tlv_req(struct qed_hwfn *hwfn) 317259ccf86fSSudarsana Reddy Kalluru { 317359ccf86fSSudarsana Reddy Kalluru DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV, 317459ccf86fSSudarsana Reddy Kalluru "Scheduling slowpath task [Flag: %d]\n", 317559ccf86fSSudarsana Reddy Kalluru QED_SLOWPATH_MFW_TLV_REQ); 317659ccf86fSSudarsana Reddy Kalluru smp_mb__before_atomic(); 317759ccf86fSSudarsana Reddy Kalluru set_bit(QED_SLOWPATH_MFW_TLV_REQ, &hwfn->slowpath_task_flags); 317859ccf86fSSudarsana Reddy Kalluru smp_mb__after_atomic(); 317959ccf86fSSudarsana Reddy Kalluru queue_delayed_work(hwfn->slowpath_wq, &hwfn->slowpath_task, 0); 318059ccf86fSSudarsana Reddy Kalluru 318159ccf86fSSudarsana Reddy Kalluru return 0; 318259ccf86fSSudarsana Reddy Kalluru } 318359ccf86fSSudarsana Reddy Kalluru 318459ccf86fSSudarsana Reddy Kalluru static void 318559ccf86fSSudarsana Reddy Kalluru qed_fill_generic_tlv_data(struct qed_dev *cdev, struct qed_mfw_tlv_generic *tlv) 318659ccf86fSSudarsana Reddy Kalluru { 318759ccf86fSSudarsana Reddy Kalluru struct qed_common_cb_ops *op = cdev->protocol_ops.common; 318859ccf86fSSudarsana Reddy Kalluru struct qed_eth_stats_common *p_common; 318959ccf86fSSudarsana Reddy Kalluru struct qed_generic_tlvs gen_tlvs; 319059ccf86fSSudarsana Reddy Kalluru struct qed_eth_stats stats; 319159ccf86fSSudarsana Reddy Kalluru int i; 319259ccf86fSSudarsana Reddy Kalluru 319359ccf86fSSudarsana Reddy Kalluru memset(&gen_tlvs, 0, sizeof(gen_tlvs)); 319459ccf86fSSudarsana Reddy Kalluru op->get_generic_tlv_data(cdev->ops_cookie, &gen_tlvs); 319559ccf86fSSudarsana Reddy Kalluru 319659ccf86fSSudarsana Reddy Kalluru if (gen_tlvs.feat_flags & QED_TLV_IP_CSUM) 319759ccf86fSSudarsana Reddy Kalluru tlv->flags.ipv4_csum_offload = true; 319859ccf86fSSudarsana Reddy Kalluru if (gen_tlvs.feat_flags & QED_TLV_LSO) 319959ccf86fSSudarsana Reddy Kalluru tlv->flags.lso_supported = true; 320059ccf86fSSudarsana Reddy Kalluru tlv->flags.b_set = true; 320159ccf86fSSudarsana Reddy Kalluru 320259ccf86fSSudarsana Reddy Kalluru for (i = 0; i < QED_TLV_MAC_COUNT; i++) { 320359ccf86fSSudarsana Reddy Kalluru if (is_valid_ether_addr(gen_tlvs.mac[i])) { 320459ccf86fSSudarsana Reddy Kalluru ether_addr_copy(tlv->mac[i], gen_tlvs.mac[i]); 320559ccf86fSSudarsana Reddy Kalluru tlv->mac_set[i] = true; 320659ccf86fSSudarsana Reddy Kalluru } 320759ccf86fSSudarsana Reddy Kalluru } 320859ccf86fSSudarsana Reddy Kalluru 320959ccf86fSSudarsana Reddy Kalluru qed_get_vport_stats(cdev, &stats); 321059ccf86fSSudarsana Reddy Kalluru p_common = &stats.common; 321159ccf86fSSudarsana Reddy Kalluru tlv->rx_frames = p_common->rx_ucast_pkts + p_common->rx_mcast_pkts + 321259ccf86fSSudarsana Reddy Kalluru p_common->rx_bcast_pkts; 321359ccf86fSSudarsana Reddy Kalluru tlv->rx_frames_set = true; 321459ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes = p_common->rx_ucast_bytes + p_common->rx_mcast_bytes + 321559ccf86fSSudarsana Reddy Kalluru p_common->rx_bcast_bytes; 321659ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes_set = true; 321759ccf86fSSudarsana Reddy Kalluru tlv->tx_frames = p_common->tx_ucast_pkts + p_common->tx_mcast_pkts + 321859ccf86fSSudarsana Reddy Kalluru p_common->tx_bcast_pkts; 321959ccf86fSSudarsana Reddy Kalluru tlv->tx_frames_set = true; 322059ccf86fSSudarsana Reddy Kalluru tlv->tx_bytes = p_common->tx_ucast_bytes + p_common->tx_mcast_bytes + 322159ccf86fSSudarsana Reddy Kalluru p_common->tx_bcast_bytes; 322259ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes_set = true; 322359ccf86fSSudarsana Reddy Kalluru } 322459ccf86fSSudarsana Reddy Kalluru 32252528c389SSudarsana Reddy Kalluru int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn, enum qed_mfw_tlv_type type, 32262528c389SSudarsana Reddy Kalluru union qed_mfw_tlv_data *tlv_buf) 32272528c389SSudarsana Reddy Kalluru { 322859ccf86fSSudarsana Reddy Kalluru struct qed_dev *cdev = hwfn->cdev; 322959ccf86fSSudarsana Reddy Kalluru struct qed_common_cb_ops *ops; 323059ccf86fSSudarsana Reddy Kalluru 323159ccf86fSSudarsana Reddy Kalluru ops = cdev->protocol_ops.common; 323259ccf86fSSudarsana Reddy Kalluru if (!ops || !ops->get_protocol_tlv_data || !ops->get_generic_tlv_data) { 323359ccf86fSSudarsana Reddy Kalluru DP_NOTICE(hwfn, "Can't collect TLV management info\n"); 32342528c389SSudarsana Reddy Kalluru return -EINVAL; 32352528c389SSudarsana Reddy Kalluru } 323659ccf86fSSudarsana Reddy Kalluru 323759ccf86fSSudarsana Reddy Kalluru switch (type) { 323859ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_GENERIC: 323959ccf86fSSudarsana Reddy Kalluru qed_fill_generic_tlv_data(hwfn->cdev, &tlv_buf->generic); 324059ccf86fSSudarsana Reddy Kalluru break; 324159ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_ETH: 324259ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->eth); 324359ccf86fSSudarsana Reddy Kalluru break; 324459ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_FCOE: 324559ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->fcoe); 324659ccf86fSSudarsana Reddy Kalluru break; 324759ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_ISCSI: 324859ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->iscsi); 324959ccf86fSSudarsana Reddy Kalluru break; 325059ccf86fSSudarsana Reddy Kalluru default: 325159ccf86fSSudarsana Reddy Kalluru break; 325259ccf86fSSudarsana Reddy Kalluru } 325359ccf86fSSudarsana Reddy Kalluru 325459ccf86fSSudarsana Reddy Kalluru return 0; 325559ccf86fSSudarsana Reddy Kalluru } 3256