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); 447831bfb0eSYuval Mintz dev_info->tx_switching = true; 44814d39648SMintz, Yuval 449c851a9dcSKalderon, Michal if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME) 45014d39648SMintz, Yuval dev_info->wol_support = true; 4513c5da942SMintz, Yuval 452df9c716dSSudarsana Reddy Kalluru dev_info->smart_an = qed_mcp_is_smart_an_supported(p_hwfn); 453df9c716dSSudarsana Reddy Kalluru 4543c5da942SMintz, Yuval dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id; 4551408cc1fSYuval Mintz } else { 4561408cc1fSYuval Mintz qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, 4571408cc1fSYuval Mintz &dev_info->fw_minor, &dev_info->fw_rev, 4581408cc1fSYuval Mintz &dev_info->fw_eng); 4591408cc1fSYuval Mintz } 460fe56b9e6SYuval Mintz 4611408cc1fSYuval Mintz if (IS_PF(cdev)) { 462cee4d264SManish Chopra ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 463cee4d264SManish Chopra if (ptt) { 4641408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), ptt, 4651408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 4661408cc1fSYuval Mintz 467ae33666aSTomer Tayar qed_mcp_get_mbi_ver(QED_LEADING_HWFN(cdev), ptt, 468ae33666aSTomer Tayar &dev_info->mbi_version); 469ae33666aSTomer Tayar 470cee4d264SManish Chopra qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt, 471cee4d264SManish Chopra &dev_info->flash_size); 472cee4d264SManish Chopra 473cee4d264SManish Chopra qed_ptt_release(QED_LEADING_HWFN(cdev), ptt); 474cee4d264SManish Chopra } 4751408cc1fSYuval Mintz } else { 4761408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), NULL, 4771408cc1fSYuval Mintz &dev_info->mfw_rev, NULL); 4781408cc1fSYuval Mintz } 479cee4d264SManish Chopra 480c851a9dcSKalderon, Michal dev_info->mtu = hw_info->mtu; 4810fefbfbaSSudarsana Kalluru 482fe56b9e6SYuval Mintz return 0; 483fe56b9e6SYuval Mintz } 484fe56b9e6SYuval Mintz 485fe56b9e6SYuval Mintz static void qed_free_cdev(struct qed_dev *cdev) 486fe56b9e6SYuval Mintz { 487fe56b9e6SYuval Mintz kfree((void *)cdev); 488fe56b9e6SYuval Mintz } 489fe56b9e6SYuval Mintz 490fe56b9e6SYuval Mintz static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev) 491fe56b9e6SYuval Mintz { 492fe56b9e6SYuval Mintz struct qed_dev *cdev; 493fe56b9e6SYuval Mintz 494fe56b9e6SYuval Mintz cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 495fe56b9e6SYuval Mintz if (!cdev) 496fe56b9e6SYuval Mintz return cdev; 497fe56b9e6SYuval Mintz 498fe56b9e6SYuval Mintz qed_init_struct(cdev); 499fe56b9e6SYuval Mintz 500fe56b9e6SYuval Mintz return cdev; 501fe56b9e6SYuval Mintz } 502fe56b9e6SYuval Mintz 503fe56b9e6SYuval Mintz /* Sets the requested power state */ 5041a635e48SYuval Mintz static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state) 505fe56b9e6SYuval Mintz { 506fe56b9e6SYuval Mintz if (!cdev) 507fe56b9e6SYuval Mintz return -ENODEV; 508fe56b9e6SYuval Mintz 509fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n"); 510fe56b9e6SYuval Mintz return 0; 511fe56b9e6SYuval Mintz } 512fe56b9e6SYuval Mintz 51324e04879SMichal Kalderon struct qed_devlink { 51424e04879SMichal Kalderon struct qed_dev *cdev; 51524e04879SMichal Kalderon }; 51624e04879SMichal Kalderon 51724e04879SMichal Kalderon enum qed_devlink_param_id { 51824e04879SMichal Kalderon QED_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 51924e04879SMichal Kalderon QED_DEVLINK_PARAM_ID_IWARP_CMT, 52024e04879SMichal Kalderon }; 52124e04879SMichal Kalderon 52224e04879SMichal Kalderon static int qed_dl_param_get(struct devlink *dl, u32 id, 52324e04879SMichal Kalderon struct devlink_param_gset_ctx *ctx) 52424e04879SMichal Kalderon { 52524e04879SMichal Kalderon struct qed_devlink *qed_dl; 52624e04879SMichal Kalderon struct qed_dev *cdev; 52724e04879SMichal Kalderon 52824e04879SMichal Kalderon qed_dl = devlink_priv(dl); 52924e04879SMichal Kalderon cdev = qed_dl->cdev; 53024e04879SMichal Kalderon ctx->val.vbool = cdev->iwarp_cmt; 53124e04879SMichal Kalderon 53224e04879SMichal Kalderon return 0; 53324e04879SMichal Kalderon } 53424e04879SMichal Kalderon 53524e04879SMichal Kalderon static int qed_dl_param_set(struct devlink *dl, u32 id, 53624e04879SMichal Kalderon struct devlink_param_gset_ctx *ctx) 53724e04879SMichal Kalderon { 53824e04879SMichal Kalderon struct qed_devlink *qed_dl; 53924e04879SMichal Kalderon struct qed_dev *cdev; 54024e04879SMichal Kalderon 54124e04879SMichal Kalderon qed_dl = devlink_priv(dl); 54224e04879SMichal Kalderon cdev = qed_dl->cdev; 54324e04879SMichal Kalderon cdev->iwarp_cmt = ctx->val.vbool; 54424e04879SMichal Kalderon 54524e04879SMichal Kalderon return 0; 54624e04879SMichal Kalderon } 54724e04879SMichal Kalderon 54824e04879SMichal Kalderon static const struct devlink_param qed_devlink_params[] = { 54924e04879SMichal Kalderon DEVLINK_PARAM_DRIVER(QED_DEVLINK_PARAM_ID_IWARP_CMT, 55024e04879SMichal Kalderon "iwarp_cmt", DEVLINK_PARAM_TYPE_BOOL, 55124e04879SMichal Kalderon BIT(DEVLINK_PARAM_CMODE_RUNTIME), 55224e04879SMichal Kalderon qed_dl_param_get, qed_dl_param_set, NULL), 55324e04879SMichal Kalderon }; 55424e04879SMichal Kalderon 55524e04879SMichal Kalderon static const struct devlink_ops qed_dl_ops; 55624e04879SMichal Kalderon 55724e04879SMichal Kalderon static int qed_devlink_register(struct qed_dev *cdev) 55824e04879SMichal Kalderon { 55924e04879SMichal Kalderon union devlink_param_value value; 56024e04879SMichal Kalderon struct qed_devlink *qed_dl; 56124e04879SMichal Kalderon struct devlink *dl; 56224e04879SMichal Kalderon int rc; 56324e04879SMichal Kalderon 56424e04879SMichal Kalderon dl = devlink_alloc(&qed_dl_ops, sizeof(*qed_dl)); 56524e04879SMichal Kalderon if (!dl) 56624e04879SMichal Kalderon return -ENOMEM; 56724e04879SMichal Kalderon 56824e04879SMichal Kalderon qed_dl = devlink_priv(dl); 56924e04879SMichal Kalderon 57024e04879SMichal Kalderon cdev->dl = dl; 57124e04879SMichal Kalderon qed_dl->cdev = cdev; 57224e04879SMichal Kalderon 57324e04879SMichal Kalderon rc = devlink_register(dl, &cdev->pdev->dev); 57424e04879SMichal Kalderon if (rc) 57524e04879SMichal Kalderon goto err_free; 57624e04879SMichal Kalderon 57724e04879SMichal Kalderon rc = devlink_params_register(dl, qed_devlink_params, 57824e04879SMichal Kalderon ARRAY_SIZE(qed_devlink_params)); 57924e04879SMichal Kalderon if (rc) 58024e04879SMichal Kalderon goto err_unregister; 58124e04879SMichal Kalderon 58224e04879SMichal Kalderon value.vbool = false; 58324e04879SMichal Kalderon devlink_param_driverinit_value_set(dl, 58424e04879SMichal Kalderon QED_DEVLINK_PARAM_ID_IWARP_CMT, 58524e04879SMichal Kalderon value); 58624e04879SMichal Kalderon 58724e04879SMichal Kalderon devlink_params_publish(dl); 58824e04879SMichal Kalderon cdev->iwarp_cmt = false; 58924e04879SMichal Kalderon 59024e04879SMichal Kalderon return 0; 59124e04879SMichal Kalderon 59224e04879SMichal Kalderon err_unregister: 59324e04879SMichal Kalderon devlink_unregister(dl); 59424e04879SMichal Kalderon 59524e04879SMichal Kalderon err_free: 59624e04879SMichal Kalderon cdev->dl = NULL; 59724e04879SMichal Kalderon devlink_free(dl); 59824e04879SMichal Kalderon 59924e04879SMichal Kalderon return rc; 60024e04879SMichal Kalderon } 60124e04879SMichal Kalderon 60224e04879SMichal Kalderon static void qed_devlink_unregister(struct qed_dev *cdev) 60324e04879SMichal Kalderon { 60424e04879SMichal Kalderon if (!cdev->dl) 60524e04879SMichal Kalderon return; 60624e04879SMichal Kalderon 60724e04879SMichal Kalderon devlink_params_unregister(cdev->dl, qed_devlink_params, 60824e04879SMichal Kalderon ARRAY_SIZE(qed_devlink_params)); 60924e04879SMichal Kalderon 61024e04879SMichal Kalderon devlink_unregister(cdev->dl); 61124e04879SMichal Kalderon devlink_free(cdev->dl); 61224e04879SMichal Kalderon } 61324e04879SMichal Kalderon 614fe56b9e6SYuval Mintz /* probing */ 615fe56b9e6SYuval Mintz static struct qed_dev *qed_probe(struct pci_dev *pdev, 6161408cc1fSYuval Mintz struct qed_probe_params *params) 617fe56b9e6SYuval Mintz { 618fe56b9e6SYuval Mintz struct qed_dev *cdev; 619fe56b9e6SYuval Mintz int rc; 620fe56b9e6SYuval Mintz 621fe56b9e6SYuval Mintz cdev = qed_alloc_cdev(pdev); 622fe56b9e6SYuval Mintz if (!cdev) 623fe56b9e6SYuval Mintz goto err0; 624fe56b9e6SYuval Mintz 625712c3cbfSMintz, Yuval cdev->drv_type = DRV_ID_DRV_TYPE_LINUX; 6261408cc1fSYuval Mintz cdev->protocol = params->protocol; 627fe56b9e6SYuval Mintz 6281408cc1fSYuval Mintz if (params->is_vf) 6291408cc1fSYuval Mintz cdev->b_is_vf = true; 6301408cc1fSYuval Mintz 6311408cc1fSYuval Mintz qed_init_dp(cdev, params->dp_module, params->dp_level); 632fe56b9e6SYuval Mintz 63364515dc8STomer Tayar cdev->recov_in_prog = params->recov_in_prog; 63464515dc8STomer Tayar 635fe56b9e6SYuval Mintz rc = qed_init_pci(cdev, pdev); 636fe56b9e6SYuval Mintz if (rc) { 637fe56b9e6SYuval Mintz DP_ERR(cdev, "init pci failed\n"); 638fe56b9e6SYuval Mintz goto err1; 639fe56b9e6SYuval Mintz } 640fe56b9e6SYuval Mintz DP_INFO(cdev, "PCI init completed successfully\n"); 641fe56b9e6SYuval Mintz 64224e04879SMichal Kalderon rc = qed_devlink_register(cdev); 64324e04879SMichal Kalderon if (rc) { 64424e04879SMichal Kalderon DP_INFO(cdev, "Failed to register devlink.\n"); 64524e04879SMichal Kalderon goto err2; 64624e04879SMichal Kalderon } 64724e04879SMichal Kalderon 648fe56b9e6SYuval Mintz rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); 649fe56b9e6SYuval Mintz if (rc) { 650fe56b9e6SYuval Mintz DP_ERR(cdev, "hw prepare failed\n"); 651fe56b9e6SYuval Mintz goto err2; 652fe56b9e6SYuval Mintz } 653fe56b9e6SYuval Mintz 65420c4515aSEwan D. Milne DP_INFO(cdev, "qed_probe completed successfully\n"); 655fe56b9e6SYuval Mintz 656fe56b9e6SYuval Mintz return cdev; 657fe56b9e6SYuval Mintz 658fe56b9e6SYuval Mintz err2: 659fe56b9e6SYuval Mintz qed_free_pci(cdev); 660fe56b9e6SYuval Mintz err1: 661fe56b9e6SYuval Mintz qed_free_cdev(cdev); 662fe56b9e6SYuval Mintz err0: 663fe56b9e6SYuval Mintz return NULL; 664fe56b9e6SYuval Mintz } 665fe56b9e6SYuval Mintz 666fe56b9e6SYuval Mintz static void qed_remove(struct qed_dev *cdev) 667fe56b9e6SYuval Mintz { 668fe56b9e6SYuval Mintz if (!cdev) 669fe56b9e6SYuval Mintz return; 670fe56b9e6SYuval Mintz 671fe56b9e6SYuval Mintz qed_hw_remove(cdev); 672fe56b9e6SYuval Mintz 673fe56b9e6SYuval Mintz qed_free_pci(cdev); 674fe56b9e6SYuval Mintz 675fe56b9e6SYuval Mintz qed_set_power_state(cdev, PCI_D3hot); 676fe56b9e6SYuval Mintz 67724e04879SMichal Kalderon qed_devlink_unregister(cdev); 67824e04879SMichal Kalderon 679fe56b9e6SYuval Mintz qed_free_cdev(cdev); 680fe56b9e6SYuval Mintz } 681fe56b9e6SYuval Mintz 682fe56b9e6SYuval Mintz static void qed_disable_msix(struct qed_dev *cdev) 683fe56b9e6SYuval Mintz { 684fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 685fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 686fe56b9e6SYuval Mintz kfree(cdev->int_params.msix_table); 687fe56b9e6SYuval Mintz } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) { 688fe56b9e6SYuval Mintz pci_disable_msi(cdev->pdev); 689fe56b9e6SYuval Mintz } 690fe56b9e6SYuval Mintz 691fe56b9e6SYuval Mintz memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param)); 692fe56b9e6SYuval Mintz } 693fe56b9e6SYuval Mintz 694fe56b9e6SYuval Mintz static int qed_enable_msix(struct qed_dev *cdev, 695fe56b9e6SYuval Mintz struct qed_int_params *int_params) 696fe56b9e6SYuval Mintz { 697fe56b9e6SYuval Mintz int i, rc, cnt; 698fe56b9e6SYuval Mintz 699fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 700fe56b9e6SYuval Mintz 701fe56b9e6SYuval Mintz for (i = 0; i < cnt; i++) 702fe56b9e6SYuval Mintz int_params->msix_table[i].entry = i; 703fe56b9e6SYuval Mintz 704fe56b9e6SYuval Mintz rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table, 705fe56b9e6SYuval Mintz int_params->in.min_msix_cnt, cnt); 706fe56b9e6SYuval Mintz if (rc < cnt && rc >= int_params->in.min_msix_cnt && 707fe56b9e6SYuval Mintz (rc % cdev->num_hwfns)) { 708fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev); 709fe56b9e6SYuval Mintz 710fe56b9e6SYuval Mintz /* If fastpath is initialized, we need at least one interrupt 711fe56b9e6SYuval Mintz * per hwfn [and the slow path interrupts]. New requested number 712fe56b9e6SYuval Mintz * should be a multiple of the number of hwfns. 713fe56b9e6SYuval Mintz */ 714fe56b9e6SYuval Mintz cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns; 715fe56b9e6SYuval Mintz DP_NOTICE(cdev, 716fe56b9e6SYuval Mintz "Trying to enable MSI-X with less vectors (%d out of %d)\n", 717fe56b9e6SYuval Mintz cnt, int_params->in.num_vectors); 7181a635e48SYuval Mintz rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table, 7191a635e48SYuval Mintz cnt); 720fe56b9e6SYuval Mintz if (!rc) 721fe56b9e6SYuval Mintz rc = cnt; 722fe56b9e6SYuval Mintz } 723fe56b9e6SYuval Mintz 724fe56b9e6SYuval Mintz if (rc > 0) { 725fe56b9e6SYuval Mintz /* MSI-x configuration was achieved */ 726fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSIX; 727fe56b9e6SYuval Mintz int_params->out.num_vectors = rc; 728fe56b9e6SYuval Mintz rc = 0; 729fe56b9e6SYuval Mintz } else { 730fe56b9e6SYuval Mintz DP_NOTICE(cdev, 731fe56b9e6SYuval Mintz "Failed to enable MSI-X [Requested %d vectors][rc %d]\n", 732fe56b9e6SYuval Mintz cnt, rc); 733fe56b9e6SYuval Mintz } 734fe56b9e6SYuval Mintz 735fe56b9e6SYuval Mintz return rc; 736fe56b9e6SYuval Mintz } 737fe56b9e6SYuval Mintz 738fe56b9e6SYuval Mintz /* This function outputs the int mode and the number of enabled msix vector */ 739fe56b9e6SYuval Mintz static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) 740fe56b9e6SYuval Mintz { 741fe56b9e6SYuval Mintz struct qed_int_params *int_params = &cdev->int_params; 742fe56b9e6SYuval Mintz struct msix_entry *tbl; 743fe56b9e6SYuval Mintz int rc = 0, cnt; 744fe56b9e6SYuval Mintz 745fe56b9e6SYuval Mintz switch (int_params->in.int_mode) { 746fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX: 747fe56b9e6SYuval Mintz /* Allocate MSIX table */ 748fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors; 749fe56b9e6SYuval Mintz int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL); 750fe56b9e6SYuval Mintz if (!int_params->msix_table) { 751fe56b9e6SYuval Mintz rc = -ENOMEM; 752fe56b9e6SYuval Mintz goto out; 753fe56b9e6SYuval Mintz } 754fe56b9e6SYuval Mintz 755fe56b9e6SYuval Mintz /* Enable MSIX */ 756fe56b9e6SYuval Mintz rc = qed_enable_msix(cdev, int_params); 757fe56b9e6SYuval Mintz if (!rc) 758fe56b9e6SYuval Mintz goto out; 759fe56b9e6SYuval Mintz 760fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI-X\n"); 761fe56b9e6SYuval Mintz kfree(int_params->msix_table); 762fe56b9e6SYuval Mintz if (force_mode) 763fe56b9e6SYuval Mintz goto out; 764df561f66SGustavo A. R. Silva fallthrough; 765fe56b9e6SYuval Mintz 766fe56b9e6SYuval Mintz case QED_INT_MODE_MSI: 767bb13ace7SSudarsana Reddy Kalluru if (cdev->num_hwfns == 1) { 768fe56b9e6SYuval Mintz rc = pci_enable_msi(cdev->pdev); 769fe56b9e6SYuval Mintz if (!rc) { 770fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSI; 771fe56b9e6SYuval Mintz goto out; 772fe56b9e6SYuval Mintz } 773fe56b9e6SYuval Mintz 774fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI\n"); 775fe56b9e6SYuval Mintz if (force_mode) 776fe56b9e6SYuval Mintz goto out; 777bb13ace7SSudarsana Reddy Kalluru } 778df561f66SGustavo A. R. Silva fallthrough; 779fe56b9e6SYuval Mintz 780fe56b9e6SYuval Mintz case QED_INT_MODE_INTA: 781fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_INTA; 782fe56b9e6SYuval Mintz rc = 0; 783fe56b9e6SYuval Mintz goto out; 784fe56b9e6SYuval Mintz default: 785fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Unknown int_mode value %d\n", 786fe56b9e6SYuval Mintz int_params->in.int_mode); 787fe56b9e6SYuval Mintz rc = -EINVAL; 788fe56b9e6SYuval Mintz } 789fe56b9e6SYuval Mintz 790fe56b9e6SYuval Mintz out: 791525ef5c0SYuval Mintz if (!rc) 792525ef5c0SYuval Mintz DP_INFO(cdev, "Using %s interrupts\n", 793525ef5c0SYuval Mintz int_params->out.int_mode == QED_INT_MODE_INTA ? 794525ef5c0SYuval Mintz "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ? 795525ef5c0SYuval Mintz "MSI" : "MSIX"); 796fe56b9e6SYuval Mintz cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE; 797fe56b9e6SYuval Mintz 798fe56b9e6SYuval Mintz return rc; 799fe56b9e6SYuval Mintz } 800fe56b9e6SYuval Mintz 801fe56b9e6SYuval Mintz static void qed_simd_handler_config(struct qed_dev *cdev, void *token, 802fe56b9e6SYuval Mintz int index, void(*handler)(void *)) 803fe56b9e6SYuval Mintz { 804fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 805fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 806fe56b9e6SYuval Mintz 807fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].func = handler; 808fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].token = token; 809fe56b9e6SYuval Mintz } 810fe56b9e6SYuval Mintz 811fe56b9e6SYuval Mintz static void qed_simd_handler_clean(struct qed_dev *cdev, int index) 812fe56b9e6SYuval Mintz { 813fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; 814fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns; 815fe56b9e6SYuval Mintz 816fe56b9e6SYuval Mintz memset(&hwfn->simd_proto_handler[relative_idx], 0, 817fe56b9e6SYuval Mintz sizeof(struct qed_simd_fp_handler)); 818fe56b9e6SYuval Mintz } 819fe56b9e6SYuval Mintz 820fe56b9e6SYuval Mintz static irqreturn_t qed_msix_sp_int(int irq, void *tasklet) 821fe56b9e6SYuval Mintz { 822fe56b9e6SYuval Mintz tasklet_schedule((struct tasklet_struct *)tasklet); 823fe56b9e6SYuval Mintz return IRQ_HANDLED; 824fe56b9e6SYuval Mintz } 825fe56b9e6SYuval Mintz 826fe56b9e6SYuval Mintz static irqreturn_t qed_single_int(int irq, void *dev_instance) 827fe56b9e6SYuval Mintz { 828fe56b9e6SYuval Mintz struct qed_dev *cdev = (struct qed_dev *)dev_instance; 829fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 830fe56b9e6SYuval Mintz irqreturn_t rc = IRQ_NONE; 831fe56b9e6SYuval Mintz u64 status; 832fe56b9e6SYuval Mintz int i, j; 833fe56b9e6SYuval Mintz 834fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 835fe56b9e6SYuval Mintz status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]); 836fe56b9e6SYuval Mintz 837fe56b9e6SYuval Mintz if (!status) 838fe56b9e6SYuval Mintz continue; 839fe56b9e6SYuval Mintz 840fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 841fe56b9e6SYuval Mintz 842fe56b9e6SYuval Mintz /* Slowpath interrupt */ 843fe56b9e6SYuval Mintz if (unlikely(status & 0x1)) { 844fe56b9e6SYuval Mintz tasklet_schedule(hwfn->sp_dpc); 845fe56b9e6SYuval Mintz status &= ~0x1; 846fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 847fe56b9e6SYuval Mintz } 848fe56b9e6SYuval Mintz 849fe56b9e6SYuval Mintz /* Fastpath interrupts */ 850fe56b9e6SYuval Mintz for (j = 0; j < 64; j++) { 851fe56b9e6SYuval Mintz if ((0x2ULL << j) & status) { 8523935a709SSudarsana Reddy Kalluru struct qed_simd_fp_handler *p_handler = 8533935a709SSudarsana Reddy Kalluru &hwfn->simd_proto_handler[j]; 8543935a709SSudarsana Reddy Kalluru 8553935a709SSudarsana Reddy Kalluru if (p_handler->func) 8563935a709SSudarsana Reddy Kalluru p_handler->func(p_handler->token); 8573935a709SSudarsana Reddy Kalluru else 8583935a709SSudarsana Reddy Kalluru DP_NOTICE(hwfn, 8593935a709SSudarsana Reddy Kalluru "Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n", 8603935a709SSudarsana Reddy Kalluru j, status); 8613935a709SSudarsana Reddy Kalluru 862fe56b9e6SYuval Mintz status &= ~(0x2ULL << j); 863fe56b9e6SYuval Mintz rc = IRQ_HANDLED; 864fe56b9e6SYuval Mintz } 865fe56b9e6SYuval Mintz } 866fe56b9e6SYuval Mintz 867fe56b9e6SYuval Mintz if (unlikely(status)) 868fe56b9e6SYuval Mintz DP_VERBOSE(hwfn, NETIF_MSG_INTR, 869fe56b9e6SYuval Mintz "got an unknown interrupt status 0x%llx\n", 870fe56b9e6SYuval Mintz status); 871fe56b9e6SYuval Mintz } 872fe56b9e6SYuval Mintz 873fe56b9e6SYuval Mintz return rc; 874fe56b9e6SYuval Mintz } 875fe56b9e6SYuval Mintz 8768f16bc97SSudarsana Kalluru int qed_slowpath_irq_req(struct qed_hwfn *hwfn) 877fe56b9e6SYuval Mintz { 8788f16bc97SSudarsana Kalluru struct qed_dev *cdev = hwfn->cdev; 879525ef5c0SYuval Mintz u32 int_mode; 8808f16bc97SSudarsana Kalluru int rc = 0; 8818f16bc97SSudarsana Kalluru u8 id; 882fe56b9e6SYuval Mintz 883525ef5c0SYuval Mintz int_mode = cdev->int_params.out.int_mode; 884525ef5c0SYuval Mintz if (int_mode == QED_INT_MODE_MSIX) { 8858f16bc97SSudarsana Kalluru id = hwfn->my_id; 8868f16bc97SSudarsana Kalluru snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x", 8878f16bc97SSudarsana Kalluru id, cdev->pdev->bus->number, 8888f16bc97SSudarsana Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 8898f16bc97SSudarsana Kalluru rc = request_irq(cdev->int_params.msix_table[id].vector, 8908f16bc97SSudarsana Kalluru qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); 891fe56b9e6SYuval Mintz } else { 892fe56b9e6SYuval Mintz unsigned long flags = 0; 893fe56b9e6SYuval Mintz 894fe56b9e6SYuval Mintz snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x", 895fe56b9e6SYuval Mintz cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), 896fe56b9e6SYuval Mintz PCI_FUNC(cdev->pdev->devfn)); 897fe56b9e6SYuval Mintz 898fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA) 899fe56b9e6SYuval Mintz flags |= IRQF_SHARED; 900fe56b9e6SYuval Mintz 901fe56b9e6SYuval Mintz rc = request_irq(cdev->pdev->irq, qed_single_int, 902fe56b9e6SYuval Mintz flags, cdev->name, cdev); 903fe56b9e6SYuval Mintz } 904fe56b9e6SYuval Mintz 905525ef5c0SYuval Mintz if (rc) 906525ef5c0SYuval Mintz DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc); 907525ef5c0SYuval Mintz else 908525ef5c0SYuval Mintz DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP), 909525ef5c0SYuval Mintz "Requested slowpath %s\n", 910525ef5c0SYuval Mintz (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ"); 911525ef5c0SYuval Mintz 912fe56b9e6SYuval Mintz return rc; 913fe56b9e6SYuval Mintz } 914fe56b9e6SYuval Mintz 91506892f2eSTomer Tayar static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn) 91606892f2eSTomer Tayar { 91706892f2eSTomer Tayar /* Calling the disable function will make sure that any 91806892f2eSTomer Tayar * currently-running function is completed. The following call to the 91906892f2eSTomer Tayar * enable function makes this sequence a flush-like operation. 92006892f2eSTomer Tayar */ 92106892f2eSTomer Tayar if (p_hwfn->b_sp_dpc_enabled) { 92206892f2eSTomer Tayar tasklet_disable(p_hwfn->sp_dpc); 92306892f2eSTomer Tayar tasklet_enable(p_hwfn->sp_dpc); 92406892f2eSTomer Tayar } 92506892f2eSTomer Tayar } 92606892f2eSTomer Tayar 9271226337aSTomer Tayar void qed_slowpath_irq_sync(struct qed_hwfn *p_hwfn) 9281226337aSTomer Tayar { 9291226337aSTomer Tayar struct qed_dev *cdev = p_hwfn->cdev; 9301226337aSTomer Tayar u8 id = p_hwfn->my_id; 9311226337aSTomer Tayar u32 int_mode; 9321226337aSTomer Tayar 9331226337aSTomer Tayar int_mode = cdev->int_params.out.int_mode; 9341226337aSTomer Tayar if (int_mode == QED_INT_MODE_MSIX) 9351226337aSTomer Tayar synchronize_irq(cdev->int_params.msix_table[id].vector); 9361226337aSTomer Tayar else 9371226337aSTomer Tayar synchronize_irq(cdev->pdev->irq); 93806892f2eSTomer Tayar 93906892f2eSTomer Tayar qed_slowpath_tasklet_flush(p_hwfn); 9401226337aSTomer Tayar } 9411226337aSTomer Tayar 942fe56b9e6SYuval Mintz static void qed_slowpath_irq_free(struct qed_dev *cdev) 943fe56b9e6SYuval Mintz { 944fe56b9e6SYuval Mintz int i; 945fe56b9e6SYuval Mintz 946fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 947fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 9488f16bc97SSudarsana Kalluru if (!cdev->hwfns[i].b_int_requested) 9498f16bc97SSudarsana Kalluru break; 950fe56b9e6SYuval Mintz synchronize_irq(cdev->int_params.msix_table[i].vector); 951fe56b9e6SYuval Mintz free_irq(cdev->int_params.msix_table[i].vector, 952fe56b9e6SYuval Mintz cdev->hwfns[i].sp_dpc); 953fe56b9e6SYuval Mintz } 954fe56b9e6SYuval Mintz } else { 9558f16bc97SSudarsana Kalluru if (QED_LEADING_HWFN(cdev)->b_int_requested) 956fe56b9e6SYuval Mintz free_irq(cdev->pdev->irq, cdev); 957fe56b9e6SYuval Mintz } 9588f16bc97SSudarsana Kalluru qed_int_disable_post_isr_release(cdev); 959fe56b9e6SYuval Mintz } 960fe56b9e6SYuval Mintz 961fe56b9e6SYuval Mintz static int qed_nic_stop(struct qed_dev *cdev) 962fe56b9e6SYuval Mintz { 963fe56b9e6SYuval Mintz int i, rc; 964fe56b9e6SYuval Mintz 965fe56b9e6SYuval Mintz rc = qed_hw_stop(cdev); 966fe56b9e6SYuval Mintz 967fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 968fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 969fe56b9e6SYuval Mintz 970fe56b9e6SYuval Mintz if (p_hwfn->b_sp_dpc_enabled) { 971fe56b9e6SYuval Mintz tasklet_disable(p_hwfn->sp_dpc); 972fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = false; 973fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_IFDOWN, 9742fdae034SColin Ian King "Disabled sp tasklet [hwfn %d] at %p\n", 975fe56b9e6SYuval Mintz i, p_hwfn->sp_dpc); 976fe56b9e6SYuval Mintz } 977fe56b9e6SYuval Mintz } 978fe56b9e6SYuval Mintz 979c965db44STomer Tayar qed_dbg_pf_exit(cdev); 980c965db44STomer Tayar 981fe56b9e6SYuval Mintz return rc; 982fe56b9e6SYuval Mintz } 983fe56b9e6SYuval Mintz 984fe56b9e6SYuval Mintz static int qed_nic_setup(struct qed_dev *cdev) 985fe56b9e6SYuval Mintz { 9860a7fb11cSYuval Mintz int rc, i; 9870a7fb11cSYuval Mintz 9880a7fb11cSYuval Mintz /* Determine if interface is going to require LL2 */ 9890a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) { 9900a7fb11cSYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) { 9910a7fb11cSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 9920a7fb11cSYuval Mintz 9930a7fb11cSYuval Mintz p_hwfn->using_ll2 = true; 9940a7fb11cSYuval Mintz } 9950a7fb11cSYuval Mintz } 996fe56b9e6SYuval Mintz 997fe56b9e6SYuval Mintz rc = qed_resc_alloc(cdev); 998fe56b9e6SYuval Mintz if (rc) 999fe56b9e6SYuval Mintz return rc; 1000fe56b9e6SYuval Mintz 1001fe56b9e6SYuval Mintz DP_INFO(cdev, "Allocated qed resources\n"); 1002fe56b9e6SYuval Mintz 1003fe56b9e6SYuval Mintz qed_resc_setup(cdev); 1004fe56b9e6SYuval Mintz 1005fe56b9e6SYuval Mintz return rc; 1006fe56b9e6SYuval Mintz } 1007fe56b9e6SYuval Mintz 1008fe56b9e6SYuval Mintz static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt) 1009fe56b9e6SYuval Mintz { 1010fe56b9e6SYuval Mintz int limit = 0; 1011fe56b9e6SYuval Mintz 1012fe56b9e6SYuval Mintz /* Mark the fastpath as free/used */ 1013fe56b9e6SYuval Mintz cdev->int_params.fp_initialized = cnt ? true : false; 1014fe56b9e6SYuval Mintz 1015fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX) 1016fe56b9e6SYuval Mintz limit = cdev->num_hwfns * 63; 1017fe56b9e6SYuval Mintz else if (cdev->int_params.fp_msix_cnt) 1018fe56b9e6SYuval Mintz limit = cdev->int_params.fp_msix_cnt; 1019fe56b9e6SYuval Mintz 1020fe56b9e6SYuval Mintz if (!limit) 1021fe56b9e6SYuval Mintz return -ENOMEM; 1022fe56b9e6SYuval Mintz 1023fe56b9e6SYuval Mintz return min_t(int, cnt, limit); 1024fe56b9e6SYuval Mintz } 1025fe56b9e6SYuval Mintz 1026fe56b9e6SYuval Mintz static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info) 1027fe56b9e6SYuval Mintz { 1028fe56b9e6SYuval Mintz memset(info, 0, sizeof(struct qed_int_info)); 1029fe56b9e6SYuval Mintz 1030fe56b9e6SYuval Mintz if (!cdev->int_params.fp_initialized) { 1031fe56b9e6SYuval Mintz DP_INFO(cdev, 1032fe56b9e6SYuval Mintz "Protocol driver requested interrupt information, but its support is not yet configured\n"); 1033fe56b9e6SYuval Mintz return -EINVAL; 1034fe56b9e6SYuval Mintz } 1035fe56b9e6SYuval Mintz 1036fe56b9e6SYuval Mintz /* Need to expose only MSI-X information; Single IRQ is handled solely 1037fe56b9e6SYuval Mintz * by qed. 1038fe56b9e6SYuval Mintz */ 1039fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 1040fe56b9e6SYuval Mintz int msix_base = cdev->int_params.fp_msix_base; 1041fe56b9e6SYuval Mintz 1042fe56b9e6SYuval Mintz info->msix_cnt = cdev->int_params.fp_msix_cnt; 1043fe56b9e6SYuval Mintz info->msix = &cdev->int_params.msix_table[msix_base]; 1044fe56b9e6SYuval Mintz } 1045fe56b9e6SYuval Mintz 1046fe56b9e6SYuval Mintz return 0; 1047fe56b9e6SYuval Mintz } 1048fe56b9e6SYuval Mintz 1049fe56b9e6SYuval Mintz static int qed_slowpath_setup_int(struct qed_dev *cdev, 1050fe56b9e6SYuval Mintz enum qed_int_mode int_mode) 1051fe56b9e6SYuval Mintz { 10524ac801b7SYuval Mintz struct qed_sb_cnt_info sb_cnt_info; 10530189efb8SYuval Mintz int num_l2_queues = 0; 10544ac801b7SYuval Mintz int rc; 10554ac801b7SYuval Mintz int i; 1056fe56b9e6SYuval Mintz 10571d2c2024SSudarsana Reddy Kalluru if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { 10581d2c2024SSudarsana Reddy Kalluru DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); 10591d2c2024SSudarsana Reddy Kalluru return -EINVAL; 10601d2c2024SSudarsana Reddy Kalluru } 10611d2c2024SSudarsana Reddy Kalluru 10621d2c2024SSudarsana Reddy Kalluru memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 1063fe56b9e6SYuval Mintz cdev->int_params.in.int_mode = int_mode; 10644ac801b7SYuval Mintz for_each_hwfn(cdev, i) { 10654ac801b7SYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); 10664ac801b7SYuval Mintz qed_int_get_num_sbs(&cdev->hwfns[i], &sb_cnt_info); 1067726fdbe9SMintz, Yuval cdev->int_params.in.num_vectors += sb_cnt_info.cnt; 10684ac801b7SYuval Mintz cdev->int_params.in.num_vectors++; /* slowpath */ 10694ac801b7SYuval Mintz } 1070fe56b9e6SYuval Mintz 1071fe56b9e6SYuval Mintz /* We want a minimum of one slowpath and one fastpath vector per hwfn */ 1072fe56b9e6SYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; 1073fe56b9e6SYuval Mintz 1074bb7858baSSudarsana Reddy Kalluru if (is_kdump_kernel()) { 1075bb7858baSSudarsana Reddy Kalluru DP_INFO(cdev, 1076bb7858baSSudarsana Reddy Kalluru "Kdump kernel: Limit the max number of requested MSI-X vectors to %hd\n", 1077bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.min_msix_cnt); 1078bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.num_vectors = 1079bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.min_msix_cnt; 1080bb7858baSSudarsana Reddy Kalluru } 1081bb7858baSSudarsana Reddy Kalluru 1082fe56b9e6SYuval Mintz rc = qed_set_int_mode(cdev, false); 1083fe56b9e6SYuval Mintz if (rc) { 1084fe56b9e6SYuval Mintz DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); 1085fe56b9e6SYuval Mintz return rc; 1086fe56b9e6SYuval Mintz } 1087fe56b9e6SYuval Mintz 1088fe56b9e6SYuval Mintz cdev->int_params.fp_msix_base = cdev->num_hwfns; 1089fe56b9e6SYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors - 1090fe56b9e6SYuval Mintz cdev->num_hwfns; 1091fe56b9e6SYuval Mintz 10922f782278SMintz, Yuval if (!IS_ENABLED(CONFIG_QED_RDMA) || 1093c851a9dcSKalderon, Michal !QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) 10940189efb8SYuval Mintz return 0; 10950189efb8SYuval Mintz 109651ff1725SRam Amrani for_each_hwfn(cdev, i) 109751ff1725SRam Amrani num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE); 109851ff1725SRam Amrani 109951ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, 110051ff1725SRam Amrani "cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n", 110151ff1725SRam Amrani cdev->int_params.fp_msix_cnt, num_l2_queues); 110251ff1725SRam Amrani 110351ff1725SRam Amrani if (cdev->int_params.fp_msix_cnt > num_l2_queues) { 110451ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 110551ff1725SRam Amrani (cdev->int_params.fp_msix_cnt - num_l2_queues) 110651ff1725SRam Amrani / cdev->num_hwfns; 110751ff1725SRam Amrani cdev->int_params.rdma_msix_base = 110851ff1725SRam Amrani cdev->int_params.fp_msix_base + num_l2_queues; 110951ff1725SRam Amrani cdev->int_params.fp_msix_cnt = num_l2_queues; 111051ff1725SRam Amrani } else { 111151ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 0; 111251ff1725SRam Amrani } 111351ff1725SRam Amrani 111451ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n", 111551ff1725SRam Amrani cdev->int_params.rdma_msix_cnt, 111651ff1725SRam Amrani cdev->int_params.rdma_msix_base); 111751ff1725SRam Amrani 1118fe56b9e6SYuval Mintz return 0; 1119fe56b9e6SYuval Mintz } 1120fe56b9e6SYuval Mintz 11211408cc1fSYuval Mintz static int qed_slowpath_vf_setup_int(struct qed_dev *cdev) 11221408cc1fSYuval Mintz { 11231408cc1fSYuval Mintz int rc; 11241408cc1fSYuval Mintz 11251408cc1fSYuval Mintz memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); 11261408cc1fSYuval Mintz cdev->int_params.in.int_mode = QED_INT_MODE_MSIX; 11271408cc1fSYuval Mintz 11281408cc1fSYuval Mintz qed_vf_get_num_rxqs(QED_LEADING_HWFN(cdev), 11291408cc1fSYuval Mintz &cdev->int_params.in.num_vectors); 11301408cc1fSYuval Mintz if (cdev->num_hwfns > 1) { 11311408cc1fSYuval Mintz u8 vectors = 0; 11321408cc1fSYuval Mintz 11331408cc1fSYuval Mintz qed_vf_get_num_rxqs(&cdev->hwfns[1], &vectors); 11341408cc1fSYuval Mintz cdev->int_params.in.num_vectors += vectors; 11351408cc1fSYuval Mintz } 11361408cc1fSYuval Mintz 11371408cc1fSYuval Mintz /* We want a minimum of one fastpath vector per vf hwfn */ 11381408cc1fSYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns; 11391408cc1fSYuval Mintz 11401408cc1fSYuval Mintz rc = qed_set_int_mode(cdev, true); 11411408cc1fSYuval Mintz if (rc) 11421408cc1fSYuval Mintz return rc; 11431408cc1fSYuval Mintz 11441408cc1fSYuval Mintz cdev->int_params.fp_msix_base = 0; 11451408cc1fSYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors; 11461408cc1fSYuval Mintz 11471408cc1fSYuval Mintz return 0; 11481408cc1fSYuval Mintz } 11491408cc1fSYuval Mintz 1150fe56b9e6SYuval Mintz u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, 1151fe56b9e6SYuval Mintz u8 *input_buf, u32 max_size, u8 *unzip_buf) 1152fe56b9e6SYuval Mintz { 1153fe56b9e6SYuval Mintz int rc; 1154fe56b9e6SYuval Mintz 1155fe56b9e6SYuval Mintz p_hwfn->stream->next_in = input_buf; 1156fe56b9e6SYuval Mintz p_hwfn->stream->avail_in = input_len; 1157fe56b9e6SYuval Mintz p_hwfn->stream->next_out = unzip_buf; 1158fe56b9e6SYuval Mintz p_hwfn->stream->avail_out = max_size; 1159fe56b9e6SYuval Mintz 1160fe56b9e6SYuval Mintz rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS); 1161fe56b9e6SYuval Mintz 1162fe56b9e6SYuval Mintz if (rc != Z_OK) { 1163fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n", 1164fe56b9e6SYuval Mintz rc); 1165fe56b9e6SYuval Mintz return 0; 1166fe56b9e6SYuval Mintz } 1167fe56b9e6SYuval Mintz 1168fe56b9e6SYuval Mintz rc = zlib_inflate(p_hwfn->stream, Z_FINISH); 1169fe56b9e6SYuval Mintz zlib_inflateEnd(p_hwfn->stream); 1170fe56b9e6SYuval Mintz 1171fe56b9e6SYuval Mintz if (rc != Z_OK && rc != Z_STREAM_END) { 1172fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n", 1173fe56b9e6SYuval Mintz p_hwfn->stream->msg, rc); 1174fe56b9e6SYuval Mintz return 0; 1175fe56b9e6SYuval Mintz } 1176fe56b9e6SYuval Mintz 1177fe56b9e6SYuval Mintz return p_hwfn->stream->total_out / 4; 1178fe56b9e6SYuval Mintz } 1179fe56b9e6SYuval Mintz 1180fe56b9e6SYuval Mintz static int qed_alloc_stream_mem(struct qed_dev *cdev) 1181fe56b9e6SYuval Mintz { 1182fe56b9e6SYuval Mintz int i; 1183fe56b9e6SYuval Mintz void *workspace; 1184fe56b9e6SYuval Mintz 1185fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1186fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 1187fe56b9e6SYuval Mintz 1188fe56b9e6SYuval Mintz p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL); 1189fe56b9e6SYuval Mintz if (!p_hwfn->stream) 1190fe56b9e6SYuval Mintz return -ENOMEM; 1191fe56b9e6SYuval Mintz 1192fe56b9e6SYuval Mintz workspace = vzalloc(zlib_inflate_workspacesize()); 1193fe56b9e6SYuval Mintz if (!workspace) 1194fe56b9e6SYuval Mintz return -ENOMEM; 1195fe56b9e6SYuval Mintz p_hwfn->stream->workspace = workspace; 1196fe56b9e6SYuval Mintz } 1197fe56b9e6SYuval Mintz 1198fe56b9e6SYuval Mintz return 0; 1199fe56b9e6SYuval Mintz } 1200fe56b9e6SYuval Mintz 1201fe56b9e6SYuval Mintz static void qed_free_stream_mem(struct qed_dev *cdev) 1202fe56b9e6SYuval Mintz { 1203fe56b9e6SYuval Mintz int i; 1204fe56b9e6SYuval Mintz 1205fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 1206fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 1207fe56b9e6SYuval Mintz 1208fe56b9e6SYuval Mintz if (!p_hwfn->stream) 1209fe56b9e6SYuval Mintz return; 1210fe56b9e6SYuval Mintz 1211fe56b9e6SYuval Mintz vfree(p_hwfn->stream->workspace); 1212fe56b9e6SYuval Mintz kfree(p_hwfn->stream); 1213fe56b9e6SYuval Mintz } 1214fe56b9e6SYuval Mintz } 1215fe56b9e6SYuval Mintz 1216fe56b9e6SYuval Mintz static void qed_update_pf_params(struct qed_dev *cdev, 1217fe56b9e6SYuval Mintz struct qed_pf_params *params) 1218fe56b9e6SYuval Mintz { 1219fe56b9e6SYuval Mintz int i; 1220fe56b9e6SYuval Mintz 12215c5f2609SRam Amrani if (IS_ENABLED(CONFIG_QED_RDMA)) { 12220189efb8SYuval Mintz params->rdma_pf_params.num_qps = QED_ROCE_QPS; 12230189efb8SYuval Mintz params->rdma_pf_params.min_dpis = QED_ROCE_DPIS; 122439dbc646SYuval Bason params->rdma_pf_params.num_srqs = QED_RDMA_SRQS; 12250189efb8SYuval Mintz /* divide by 3 the MRs to avoid MF ILT overflow */ 12260189efb8SYuval Mintz params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX; 1227fe56b9e6SYuval Mintz } 1228fe56b9e6SYuval Mintz 1229d51e4af5SChopra, Manish if (cdev->num_hwfns > 1 || IS_VF(cdev)) 1230d51e4af5SChopra, Manish params->eth_pf_params.num_arfs_filters = 0; 1231d51e4af5SChopra, Manish 1232e1d32acbSMintz, Yuval /* In case we might support RDMA, don't allow qede to be greedy 12335e7baf0fSManish Chopra * with the L2 contexts. Allow for 64 queues [rx, tx cos, xdp] 12345e7baf0fSManish Chopra * per hwfn. 1235e1d32acbSMintz, Yuval */ 1236c851a9dcSKalderon, Michal if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) { 1237e1d32acbSMintz, Yuval u16 *num_cons; 1238e1d32acbSMintz, Yuval 1239e1d32acbSMintz, Yuval num_cons = ¶ms->eth_pf_params.num_cons; 12405e7baf0fSManish Chopra *num_cons = min_t(u16, *num_cons, QED_MAX_L2_CONS); 1241e1d32acbSMintz, Yuval } 1242e1d32acbSMintz, Yuval 12435c5f2609SRam Amrani for (i = 0; i < cdev->num_hwfns; i++) { 12445c5f2609SRam Amrani struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 12455c5f2609SRam Amrani 12465c5f2609SRam Amrani p_hwfn->pf_params = *params; 12475c5f2609SRam Amrani } 12485c5f2609SRam Amrani } 12495c5f2609SRam Amrani 1250d4476b8aSDenis Bolotin #define QED_PERIODIC_DB_REC_COUNT 10 1251a1b469b8SAriel Elior #define QED_PERIODIC_DB_REC_INTERVAL_MS 100 1252a1b469b8SAriel Elior #define QED_PERIODIC_DB_REC_INTERVAL \ 1253a1b469b8SAriel Elior msecs_to_jiffies(QED_PERIODIC_DB_REC_INTERVAL_MS) 1254a1b469b8SAriel Elior 1255a1b469b8SAriel Elior static int qed_slowpath_delayed_work(struct qed_hwfn *hwfn, 1256a1b469b8SAriel Elior enum qed_slowpath_wq_flag wq_flag, 1257a1b469b8SAriel Elior unsigned long delay) 1258a1b469b8SAriel Elior { 1259a1b469b8SAriel Elior if (!hwfn->slowpath_wq_active) 1260a1b469b8SAriel Elior return -EINVAL; 1261a1b469b8SAriel Elior 1262a1b469b8SAriel Elior /* Memory barrier for setting atomic bit */ 1263a1b469b8SAriel Elior smp_mb__before_atomic(); 1264a1b469b8SAriel Elior set_bit(wq_flag, &hwfn->slowpath_task_flags); 1265a1b469b8SAriel Elior smp_mb__after_atomic(); 1266a1b469b8SAriel Elior queue_delayed_work(hwfn->slowpath_wq, &hwfn->slowpath_task, delay); 1267a1b469b8SAriel Elior 1268a1b469b8SAriel Elior return 0; 1269a1b469b8SAriel Elior } 1270a1b469b8SAriel Elior 1271a1b469b8SAriel Elior void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn) 1272a1b469b8SAriel Elior { 1273a1b469b8SAriel Elior /* Reset periodic Doorbell Recovery counter */ 1274a1b469b8SAriel Elior p_hwfn->periodic_db_rec_count = QED_PERIODIC_DB_REC_COUNT; 1275a1b469b8SAriel Elior 1276a1b469b8SAriel Elior /* Don't schedule periodic Doorbell Recovery if already scheduled */ 1277a1b469b8SAriel Elior if (test_bit(QED_SLOWPATH_PERIODIC_DB_REC, 1278a1b469b8SAriel Elior &p_hwfn->slowpath_task_flags)) 1279a1b469b8SAriel Elior return; 1280a1b469b8SAriel Elior 1281a1b469b8SAriel Elior qed_slowpath_delayed_work(p_hwfn, QED_SLOWPATH_PERIODIC_DB_REC, 1282a1b469b8SAriel Elior QED_PERIODIC_DB_REC_INTERVAL); 1283a1b469b8SAriel Elior } 1284a1b469b8SAriel Elior 128559ccf86fSSudarsana Reddy Kalluru static void qed_slowpath_wq_stop(struct qed_dev *cdev) 128659ccf86fSSudarsana Reddy Kalluru { 12873b85720dSYuval Basson int i; 128859ccf86fSSudarsana Reddy Kalluru 128959ccf86fSSudarsana Reddy Kalluru if (IS_VF(cdev)) 129059ccf86fSSudarsana Reddy Kalluru return; 129159ccf86fSSudarsana Reddy Kalluru 129259ccf86fSSudarsana Reddy Kalluru for_each_hwfn(cdev, i) { 129359ccf86fSSudarsana Reddy Kalluru if (!cdev->hwfns[i].slowpath_wq) 129459ccf86fSSudarsana Reddy Kalluru continue; 129559ccf86fSSudarsana Reddy Kalluru 1296a1b469b8SAriel Elior /* Stop queuing new delayed works */ 1297a1b469b8SAriel Elior cdev->hwfns[i].slowpath_wq_active = false; 1298a1b469b8SAriel Elior 12993b85720dSYuval Basson cancel_delayed_work(&cdev->hwfns[i].slowpath_task); 130059ccf86fSSudarsana Reddy Kalluru destroy_workqueue(cdev->hwfns[i].slowpath_wq); 130159ccf86fSSudarsana Reddy Kalluru } 130259ccf86fSSudarsana Reddy Kalluru } 130359ccf86fSSudarsana Reddy Kalluru 130459ccf86fSSudarsana Reddy Kalluru static void qed_slowpath_task(struct work_struct *work) 130559ccf86fSSudarsana Reddy Kalluru { 130659ccf86fSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn, 130759ccf86fSSudarsana Reddy Kalluru slowpath_task.work); 130859ccf86fSSudarsana Reddy Kalluru struct qed_ptt *ptt = qed_ptt_acquire(hwfn); 130959ccf86fSSudarsana Reddy Kalluru 131059ccf86fSSudarsana Reddy Kalluru if (!ptt) { 1311a1b469b8SAriel Elior if (hwfn->slowpath_wq_active) 1312a1b469b8SAriel Elior queue_delayed_work(hwfn->slowpath_wq, 1313a1b469b8SAriel Elior &hwfn->slowpath_task, 0); 1314a1b469b8SAriel Elior 131559ccf86fSSudarsana Reddy Kalluru return; 131659ccf86fSSudarsana Reddy Kalluru } 131759ccf86fSSudarsana Reddy Kalluru 131859ccf86fSSudarsana Reddy Kalluru if (test_and_clear_bit(QED_SLOWPATH_MFW_TLV_REQ, 131959ccf86fSSudarsana Reddy Kalluru &hwfn->slowpath_task_flags)) 132059ccf86fSSudarsana Reddy Kalluru qed_mfw_process_tlv_req(hwfn, ptt); 132159ccf86fSSudarsana Reddy Kalluru 1322a1b469b8SAriel Elior if (test_and_clear_bit(QED_SLOWPATH_PERIODIC_DB_REC, 1323a1b469b8SAriel Elior &hwfn->slowpath_task_flags)) { 1324a1b469b8SAriel Elior qed_db_rec_handler(hwfn, ptt); 1325a1b469b8SAriel Elior if (hwfn->periodic_db_rec_count--) 1326a1b469b8SAriel Elior qed_slowpath_delayed_work(hwfn, 1327a1b469b8SAriel Elior QED_SLOWPATH_PERIODIC_DB_REC, 1328a1b469b8SAriel Elior QED_PERIODIC_DB_REC_INTERVAL); 1329a1b469b8SAriel Elior } 1330a1b469b8SAriel Elior 133159ccf86fSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 133259ccf86fSSudarsana Reddy Kalluru } 133359ccf86fSSudarsana Reddy Kalluru 133459ccf86fSSudarsana Reddy Kalluru static int qed_slowpath_wq_start(struct qed_dev *cdev) 133559ccf86fSSudarsana Reddy Kalluru { 133659ccf86fSSudarsana Reddy Kalluru struct qed_hwfn *hwfn; 133759ccf86fSSudarsana Reddy Kalluru char name[NAME_SIZE]; 133859ccf86fSSudarsana Reddy Kalluru int i; 133959ccf86fSSudarsana Reddy Kalluru 134059ccf86fSSudarsana Reddy Kalluru if (IS_VF(cdev)) 134159ccf86fSSudarsana Reddy Kalluru return 0; 134259ccf86fSSudarsana Reddy Kalluru 134359ccf86fSSudarsana Reddy Kalluru for_each_hwfn(cdev, i) { 134459ccf86fSSudarsana Reddy Kalluru hwfn = &cdev->hwfns[i]; 134559ccf86fSSudarsana Reddy Kalluru 134659ccf86fSSudarsana Reddy Kalluru snprintf(name, NAME_SIZE, "slowpath-%02x:%02x.%02x", 134759ccf86fSSudarsana Reddy Kalluru cdev->pdev->bus->number, 134859ccf86fSSudarsana Reddy Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); 134959ccf86fSSudarsana Reddy Kalluru 135059ccf86fSSudarsana Reddy Kalluru hwfn->slowpath_wq = alloc_workqueue(name, 0, 0); 135159ccf86fSSudarsana Reddy Kalluru if (!hwfn->slowpath_wq) { 135259ccf86fSSudarsana Reddy Kalluru DP_NOTICE(hwfn, "Cannot create slowpath workqueue\n"); 135359ccf86fSSudarsana Reddy Kalluru return -ENOMEM; 135459ccf86fSSudarsana Reddy Kalluru } 135559ccf86fSSudarsana Reddy Kalluru 135659ccf86fSSudarsana Reddy Kalluru INIT_DELAYED_WORK(&hwfn->slowpath_task, qed_slowpath_task); 1357a1b469b8SAriel Elior hwfn->slowpath_wq_active = true; 135859ccf86fSSudarsana Reddy Kalluru } 135959ccf86fSSudarsana Reddy Kalluru 136059ccf86fSSudarsana Reddy Kalluru return 0; 136159ccf86fSSudarsana Reddy Kalluru } 136259ccf86fSSudarsana Reddy Kalluru 1363fe56b9e6SYuval Mintz static int qed_slowpath_start(struct qed_dev *cdev, 1364fe56b9e6SYuval Mintz struct qed_slowpath_params *params) 1365fe56b9e6SYuval Mintz { 13665d24bcf1STomer Tayar struct qed_drv_load_params drv_load_params; 1367c0c2d0b4SMintz, Yuval struct qed_hw_init_params hw_init_params; 1368fe56b9e6SYuval Mintz struct qed_mcp_drv_version drv_version; 136919968430SChopra, Manish struct qed_tunnel_info tunn_info; 1370fe56b9e6SYuval Mintz const u8 *data = NULL; 1371fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 1372c78c70faSSudarsana Reddy Kalluru struct qed_ptt *p_ptt; 137337bff2b9SYuval Mintz int rc = -EINVAL; 137437bff2b9SYuval Mintz 137537bff2b9SYuval Mintz if (qed_iov_wq_start(cdev)) 137637bff2b9SYuval Mintz goto err; 1377fe56b9e6SYuval Mintz 137859ccf86fSSudarsana Reddy Kalluru if (qed_slowpath_wq_start(cdev)) 137959ccf86fSSudarsana Reddy Kalluru goto err; 138059ccf86fSSudarsana Reddy Kalluru 13811408cc1fSYuval Mintz if (IS_PF(cdev)) { 1382fe56b9e6SYuval Mintz rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME, 1383fe56b9e6SYuval Mintz &cdev->pdev->dev); 1384fe56b9e6SYuval Mintz if (rc) { 1385fe56b9e6SYuval Mintz DP_NOTICE(cdev, 1386fe56b9e6SYuval Mintz "Failed to find fw file - /lib/firmware/%s\n", 1387fe56b9e6SYuval Mintz QED_FW_FILE_NAME); 1388fe56b9e6SYuval Mintz goto err; 1389fe56b9e6SYuval Mintz } 1390c78c70faSSudarsana Reddy Kalluru 1391d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) { 1392d51e4af5SChopra, Manish p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); 1393d51e4af5SChopra, Manish if (p_ptt) { 1394d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt = p_ptt; 1395d51e4af5SChopra, Manish } else { 1396d51e4af5SChopra, Manish DP_NOTICE(cdev, 1397d51e4af5SChopra, Manish "Failed to acquire PTT for aRFS\n"); 1398d51e4af5SChopra, Manish goto err; 1399d51e4af5SChopra, Manish } 1400d51e4af5SChopra, Manish } 14011408cc1fSYuval Mintz } 1402fe56b9e6SYuval Mintz 14030e191827SSudarsana Reddy Kalluru cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS; 1404fe56b9e6SYuval Mintz rc = qed_nic_setup(cdev); 1405fe56b9e6SYuval Mintz if (rc) 1406fe56b9e6SYuval Mintz goto err; 1407fe56b9e6SYuval Mintz 14081408cc1fSYuval Mintz if (IS_PF(cdev)) 1409fe56b9e6SYuval Mintz rc = qed_slowpath_setup_int(cdev, params->int_mode); 14101408cc1fSYuval Mintz else 14111408cc1fSYuval Mintz rc = qed_slowpath_vf_setup_int(cdev); 1412fe56b9e6SYuval Mintz if (rc) 1413fe56b9e6SYuval Mintz goto err1; 1414fe56b9e6SYuval Mintz 14151408cc1fSYuval Mintz if (IS_PF(cdev)) { 1416fe56b9e6SYuval Mintz /* Allocate stream for unzipping */ 1417fe56b9e6SYuval Mintz rc = qed_alloc_stream_mem(cdev); 14182591c280SJoe Perches if (rc) 14198f16bc97SSudarsana Kalluru goto err2; 1420fe56b9e6SYuval Mintz 14218ac1ed79SJoe Perches /* First Dword used to differentiate between various sources */ 1422351a4dedSYuval Mintz data = cdev->firmware->data + sizeof(u32); 1423c965db44STomer Tayar 1424c965db44STomer Tayar qed_dbg_pf_init(cdev); 14251408cc1fSYuval Mintz } 1426fe56b9e6SYuval Mintz 14271408cc1fSYuval Mintz /* Start the slowpath */ 1428c0c2d0b4SMintz, Yuval memset(&hw_init_params, 0, sizeof(hw_init_params)); 142919968430SChopra, Manish memset(&tunn_info, 0, sizeof(tunn_info)); 143019968430SChopra, Manish tunn_info.vxlan.b_mode_enabled = true; 143119968430SChopra, Manish tunn_info.l2_gre.b_mode_enabled = true; 143219968430SChopra, Manish tunn_info.ip_gre.b_mode_enabled = true; 143319968430SChopra, Manish tunn_info.l2_geneve.b_mode_enabled = true; 143419968430SChopra, Manish tunn_info.ip_geneve.b_mode_enabled = true; 143519968430SChopra, Manish tunn_info.vxlan.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 143619968430SChopra, Manish tunn_info.l2_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 143719968430SChopra, Manish tunn_info.ip_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 143819968430SChopra, Manish tunn_info.l2_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 143919968430SChopra, Manish tunn_info.ip_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN; 1440c0c2d0b4SMintz, Yuval hw_init_params.p_tunn = &tunn_info; 1441c0c2d0b4SMintz, Yuval hw_init_params.b_hw_start = true; 1442c0c2d0b4SMintz, Yuval hw_init_params.int_mode = cdev->int_params.out.int_mode; 1443c0c2d0b4SMintz, Yuval hw_init_params.allow_npar_tx_switch = true; 1444c0c2d0b4SMintz, Yuval hw_init_params.bin_fw_data = data; 1445c0c2d0b4SMintz, Yuval 14465d24bcf1STomer Tayar memset(&drv_load_params, 0, sizeof(drv_load_params)); 14475d24bcf1STomer Tayar drv_load_params.is_crash_kernel = is_kdump_kernel(); 14485d24bcf1STomer Tayar drv_load_params.mfw_timeout_val = QED_LOAD_REQ_LOCK_TO_DEFAULT; 14495d24bcf1STomer Tayar drv_load_params.avoid_eng_reset = false; 14505d24bcf1STomer Tayar drv_load_params.override_force_load = QED_OVERRIDE_FORCE_LOAD_NONE; 14515d24bcf1STomer Tayar hw_init_params.p_drv_load_params = &drv_load_params; 14525d24bcf1STomer Tayar 1453c0c2d0b4SMintz, Yuval rc = qed_hw_init(cdev, &hw_init_params); 1454fe56b9e6SYuval Mintz if (rc) 14558c925c44SYuval Mintz goto err2; 1456fe56b9e6SYuval Mintz 1457fe56b9e6SYuval Mintz DP_INFO(cdev, 1458fe56b9e6SYuval Mintz "HW initialization and function start completed successfully\n"); 1459fe56b9e6SYuval Mintz 1460eaf3c0c6SChopra, Manish if (IS_PF(cdev)) { 1461eaf3c0c6SChopra, Manish cdev->tunn_feature_mask = (BIT(QED_MODE_VXLAN_TUNN) | 1462eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GENEVE_TUNN) | 1463eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGENEVE_TUNN) | 1464eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GRE_TUNN) | 1465eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGRE_TUNN)); 1466eaf3c0c6SChopra, Manish } 1467eaf3c0c6SChopra, Manish 14680a7fb11cSYuval Mintz /* Allocate LL2 interface if needed */ 14690a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->using_ll2) { 14700a7fb11cSYuval Mintz rc = qed_ll2_alloc_if(cdev); 14710a7fb11cSYuval Mintz if (rc) 14720a7fb11cSYuval Mintz goto err3; 14730a7fb11cSYuval Mintz } 14741408cc1fSYuval Mintz if (IS_PF(cdev)) { 1475fe56b9e6SYuval Mintz hwfn = QED_LEADING_HWFN(cdev); 1476fe56b9e6SYuval Mintz drv_version.version = (params->drv_major << 24) | 1477fe56b9e6SYuval Mintz (params->drv_minor << 16) | 1478fe56b9e6SYuval Mintz (params->drv_rev << 8) | 1479fe56b9e6SYuval Mintz (params->drv_eng); 1480fe56b9e6SYuval Mintz strlcpy(drv_version.name, params->name, 1481fe56b9e6SYuval Mintz MCP_DRV_VER_STR_SIZE - 4); 1482fe56b9e6SYuval Mintz rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt, 1483fe56b9e6SYuval Mintz &drv_version); 1484fe56b9e6SYuval Mintz if (rc) { 1485fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed sending drv version command\n"); 1486de0e4fd2SWenwen Wang goto err4; 1487fe56b9e6SYuval Mintz } 14881408cc1fSYuval Mintz } 1489fe56b9e6SYuval Mintz 14908c925c44SYuval Mintz qed_reset_vport_stats(cdev); 14918c925c44SYuval Mintz 1492fe56b9e6SYuval Mintz return 0; 1493fe56b9e6SYuval Mintz 1494de0e4fd2SWenwen Wang err4: 1495de0e4fd2SWenwen Wang qed_ll2_dealloc_if(cdev); 14960a7fb11cSYuval Mintz err3: 14970a7fb11cSYuval Mintz qed_hw_stop(cdev); 1498fe56b9e6SYuval Mintz err2: 14998c925c44SYuval Mintz qed_hw_timers_stop_all(cdev); 15001408cc1fSYuval Mintz if (IS_PF(cdev)) 15018c925c44SYuval Mintz qed_slowpath_irq_free(cdev); 15028c925c44SYuval Mintz qed_free_stream_mem(cdev); 1503fe56b9e6SYuval Mintz qed_disable_msix(cdev); 1504fe56b9e6SYuval Mintz err1: 1505fe56b9e6SYuval Mintz qed_resc_free(cdev); 1506fe56b9e6SYuval Mintz err: 15071408cc1fSYuval Mintz if (IS_PF(cdev)) 1508fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1509fe56b9e6SYuval Mintz 1510d51e4af5SChopra, Manish if (IS_PF(cdev) && (cdev->num_hwfns == 1) && 1511d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt) 1512d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1513d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1514c78c70faSSudarsana Reddy Kalluru 151537bff2b9SYuval Mintz qed_iov_wq_stop(cdev, false); 151637bff2b9SYuval Mintz 151759ccf86fSSudarsana Reddy Kalluru qed_slowpath_wq_stop(cdev); 151859ccf86fSSudarsana Reddy Kalluru 1519fe56b9e6SYuval Mintz return rc; 1520fe56b9e6SYuval Mintz } 1521fe56b9e6SYuval Mintz 1522fe56b9e6SYuval Mintz static int qed_slowpath_stop(struct qed_dev *cdev) 1523fe56b9e6SYuval Mintz { 1524fe56b9e6SYuval Mintz if (!cdev) 1525fe56b9e6SYuval Mintz return -ENODEV; 1526fe56b9e6SYuval Mintz 152759ccf86fSSudarsana Reddy Kalluru qed_slowpath_wq_stop(cdev); 152859ccf86fSSudarsana Reddy Kalluru 15290a7fb11cSYuval Mintz qed_ll2_dealloc_if(cdev); 15300a7fb11cSYuval Mintz 15311408cc1fSYuval Mintz if (IS_PF(cdev)) { 1532d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) 1533d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev), 1534d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt); 1535fe56b9e6SYuval Mintz qed_free_stream_mem(cdev); 1536c5ac9319SYuval Mintz if (IS_QED_ETH_IF(cdev)) 15370b55e27dSYuval Mintz qed_sriov_disable(cdev, true); 15385f027d7aSMintz, Yuval } 1539fe56b9e6SYuval Mintz 1540fe56b9e6SYuval Mintz qed_nic_stop(cdev); 15415f027d7aSMintz, Yuval 15425f027d7aSMintz, Yuval if (IS_PF(cdev)) 1543fe56b9e6SYuval Mintz qed_slowpath_irq_free(cdev); 1544fe56b9e6SYuval Mintz 1545fe56b9e6SYuval Mintz qed_disable_msix(cdev); 15461226337aSTomer Tayar 15471226337aSTomer Tayar qed_resc_free(cdev); 1548fe56b9e6SYuval Mintz 154937bff2b9SYuval Mintz qed_iov_wq_stop(cdev, true); 155037bff2b9SYuval Mintz 15511408cc1fSYuval Mintz if (IS_PF(cdev)) 1552fe56b9e6SYuval Mintz release_firmware(cdev->firmware); 1553fe56b9e6SYuval Mintz 1554fe56b9e6SYuval Mintz return 0; 1555fe56b9e6SYuval Mintz } 1556fe56b9e6SYuval Mintz 1557712c3cbfSMintz, Yuval static void qed_set_name(struct qed_dev *cdev, char name[NAME_SIZE]) 1558fe56b9e6SYuval Mintz { 1559fe56b9e6SYuval Mintz int i; 1560fe56b9e6SYuval Mintz 1561fe56b9e6SYuval Mintz memcpy(cdev->name, name, NAME_SIZE); 1562fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) 1563fe56b9e6SYuval Mintz snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i); 1564fe56b9e6SYuval Mintz } 1565fe56b9e6SYuval Mintz 1566fe56b9e6SYuval Mintz static u32 qed_sb_init(struct qed_dev *cdev, 1567fe56b9e6SYuval Mintz struct qed_sb_info *sb_info, 1568fe56b9e6SYuval Mintz void *sb_virt_addr, 1569fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, u16 sb_id, 1570fe56b9e6SYuval Mintz enum qed_sb_type type) 1571fe56b9e6SYuval Mintz { 1572fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 157385750d74SMintz, Yuval struct qed_ptt *p_ptt; 1574fe56b9e6SYuval Mintz u16 rel_sb_id; 1575fe56b9e6SYuval Mintz u32 rc; 1576fe56b9e6SYuval Mintz 157708eb1fb0SMichal Kalderon /* RoCE/Storage use a single engine in CMT mode while L2 uses both */ 157808eb1fb0SMichal Kalderon if (type == QED_SB_TYPE_L2_QUEUE) { 157908eb1fb0SMichal Kalderon p_hwfn = &cdev->hwfns[sb_id % cdev->num_hwfns]; 158008eb1fb0SMichal Kalderon rel_sb_id = sb_id / cdev->num_hwfns; 158108eb1fb0SMichal Kalderon } else { 158208eb1fb0SMichal Kalderon p_hwfn = QED_AFFIN_HWFN(cdev); 158308eb1fb0SMichal Kalderon rel_sb_id = sb_id; 158408eb1fb0SMichal Kalderon } 1585fe56b9e6SYuval Mintz 1586fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1587fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 158808eb1fb0SMichal Kalderon IS_LEAD_HWFN(p_hwfn) ? 0 : 1, rel_sb_id, sb_id); 1589fe56b9e6SYuval Mintz 159085750d74SMintz, Yuval if (IS_PF(p_hwfn->cdev)) { 159185750d74SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn); 159285750d74SMintz, Yuval if (!p_ptt) 159385750d74SMintz, Yuval return -EBUSY; 159485750d74SMintz, Yuval 159585750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, p_ptt, sb_info, sb_virt_addr, 159685750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 159785750d74SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt); 159885750d74SMintz, Yuval } else { 159985750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, NULL, sb_info, sb_virt_addr, 160085750d74SMintz, Yuval sb_phy_addr, rel_sb_id); 160185750d74SMintz, Yuval } 1602fe56b9e6SYuval Mintz 1603fe56b9e6SYuval Mintz return rc; 1604fe56b9e6SYuval Mintz } 1605fe56b9e6SYuval Mintz 1606fe56b9e6SYuval Mintz static u32 qed_sb_release(struct qed_dev *cdev, 160708eb1fb0SMichal Kalderon struct qed_sb_info *sb_info, 160808eb1fb0SMichal Kalderon u16 sb_id, 160908eb1fb0SMichal Kalderon enum qed_sb_type type) 1610fe56b9e6SYuval Mintz { 1611fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn; 1612fe56b9e6SYuval Mintz u16 rel_sb_id; 1613fe56b9e6SYuval Mintz u32 rc; 1614fe56b9e6SYuval Mintz 161508eb1fb0SMichal Kalderon /* RoCE/Storage use a single engine in CMT mode while L2 uses both */ 161608eb1fb0SMichal Kalderon if (type == QED_SB_TYPE_L2_QUEUE) { 161708eb1fb0SMichal Kalderon p_hwfn = &cdev->hwfns[sb_id % cdev->num_hwfns]; 1618fe56b9e6SYuval Mintz rel_sb_id = sb_id / cdev->num_hwfns; 161908eb1fb0SMichal Kalderon } else { 162008eb1fb0SMichal Kalderon p_hwfn = QED_AFFIN_HWFN(cdev); 162108eb1fb0SMichal Kalderon rel_sb_id = sb_id; 162208eb1fb0SMichal Kalderon } 1623fe56b9e6SYuval Mintz 1624fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR, 1625fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", 162608eb1fb0SMichal Kalderon IS_LEAD_HWFN(p_hwfn) ? 0 : 1, rel_sb_id, sb_id); 1627fe56b9e6SYuval Mintz 1628fe56b9e6SYuval Mintz rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id); 1629fe56b9e6SYuval Mintz 1630fe56b9e6SYuval Mintz return rc; 1631fe56b9e6SYuval Mintz } 1632fe56b9e6SYuval Mintz 1633fe7cd2bfSYuval Mintz static bool qed_can_link_change(struct qed_dev *cdev) 1634fe7cd2bfSYuval Mintz { 1635fe7cd2bfSYuval Mintz return true; 1636fe7cd2bfSYuval Mintz } 1637fe7cd2bfSYuval Mintz 163899785a87SAlexander Lobakin static void qed_set_ext_speed_params(struct qed_mcp_link_params *link_params, 163999785a87SAlexander Lobakin const struct qed_link_params *params) 164099785a87SAlexander Lobakin { 164199785a87SAlexander Lobakin struct qed_mcp_link_speed_params *ext_speed = &link_params->ext_speed; 164299785a87SAlexander Lobakin const struct qed_mfw_speed_map *map; 164399785a87SAlexander Lobakin u32 i; 164499785a87SAlexander Lobakin 164599785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 164699785a87SAlexander Lobakin ext_speed->autoneg = !!params->autoneg; 164799785a87SAlexander Lobakin 164899785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 164999785a87SAlexander Lobakin ext_speed->advertised_speeds = 0; 165099785a87SAlexander Lobakin 165199785a87SAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++) { 165299785a87SAlexander Lobakin map = qed_mfw_ext_maps + i; 165399785a87SAlexander Lobakin 165499785a87SAlexander Lobakin if (linkmode_intersects(params->adv_speeds, map->caps)) 165599785a87SAlexander Lobakin ext_speed->advertised_speeds |= map->mfw_val; 165699785a87SAlexander Lobakin } 165799785a87SAlexander Lobakin } 165899785a87SAlexander Lobakin 165999785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) { 166099785a87SAlexander Lobakin switch (params->forced_speed) { 166199785a87SAlexander Lobakin case SPEED_1000: 166299785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_1G; 166399785a87SAlexander Lobakin break; 166499785a87SAlexander Lobakin case SPEED_10000: 166599785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_10G; 166699785a87SAlexander Lobakin break; 166799785a87SAlexander Lobakin case SPEED_20000: 166899785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_20G; 166999785a87SAlexander Lobakin break; 167099785a87SAlexander Lobakin case SPEED_25000: 167199785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_25G; 167299785a87SAlexander Lobakin break; 167399785a87SAlexander Lobakin case SPEED_40000: 167499785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_40G; 167599785a87SAlexander Lobakin break; 167699785a87SAlexander Lobakin case SPEED_50000: 167799785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_50G_R | 167899785a87SAlexander Lobakin QED_EXT_SPEED_50G_R2; 167999785a87SAlexander Lobakin break; 168099785a87SAlexander Lobakin case SPEED_100000: 168199785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_100G_R2 | 168299785a87SAlexander Lobakin QED_EXT_SPEED_100G_R4 | 168399785a87SAlexander Lobakin QED_EXT_SPEED_100G_P4; 168499785a87SAlexander Lobakin break; 168599785a87SAlexander Lobakin default: 168699785a87SAlexander Lobakin break; 168799785a87SAlexander Lobakin } 168899785a87SAlexander Lobakin } 168999785a87SAlexander Lobakin 169099785a87SAlexander Lobakin if (!(params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG)) 169199785a87SAlexander Lobakin return; 169299785a87SAlexander Lobakin 169399785a87SAlexander Lobakin switch (params->forced_speed) { 169499785a87SAlexander Lobakin case SPEED_25000: 169599785a87SAlexander Lobakin switch (params->fec) { 169699785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 169799785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_NONE; 169899785a87SAlexander Lobakin break; 169999785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 170099785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_BASE_R; 170199785a87SAlexander Lobakin break; 170299785a87SAlexander Lobakin case FEC_FORCE_MODE_RS: 170399785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528; 170499785a87SAlexander Lobakin break; 170599785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 170699785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528 | 170799785a87SAlexander Lobakin ETH_EXT_FEC_25G_BASE_R | 170899785a87SAlexander Lobakin ETH_EXT_FEC_25G_NONE; 170999785a87SAlexander Lobakin break; 171099785a87SAlexander Lobakin default: 171199785a87SAlexander Lobakin break; 171299785a87SAlexander Lobakin } 171399785a87SAlexander Lobakin 171499785a87SAlexander Lobakin break; 171599785a87SAlexander Lobakin case SPEED_40000: 171699785a87SAlexander Lobakin switch (params->fec) { 171799785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 171899785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_NONE; 171999785a87SAlexander Lobakin break; 172099785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 172199785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R; 172299785a87SAlexander Lobakin break; 172399785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 172499785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R | 172599785a87SAlexander Lobakin ETH_EXT_FEC_40G_NONE; 172699785a87SAlexander Lobakin break; 172799785a87SAlexander Lobakin default: 172899785a87SAlexander Lobakin break; 172999785a87SAlexander Lobakin } 173099785a87SAlexander Lobakin 173199785a87SAlexander Lobakin break; 173299785a87SAlexander Lobakin case SPEED_50000: 173399785a87SAlexander Lobakin switch (params->fec) { 173499785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 173599785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_NONE; 173699785a87SAlexander Lobakin break; 173799785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 173899785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_BASE_R; 173999785a87SAlexander Lobakin break; 174099785a87SAlexander Lobakin case FEC_FORCE_MODE_RS: 174199785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528; 174299785a87SAlexander Lobakin break; 174399785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 174499785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528 | 174599785a87SAlexander Lobakin ETH_EXT_FEC_50G_BASE_R | 174699785a87SAlexander Lobakin ETH_EXT_FEC_50G_NONE; 174799785a87SAlexander Lobakin break; 174899785a87SAlexander Lobakin default: 174999785a87SAlexander Lobakin break; 175099785a87SAlexander Lobakin } 175199785a87SAlexander Lobakin 175299785a87SAlexander Lobakin break; 175399785a87SAlexander Lobakin case SPEED_100000: 175499785a87SAlexander Lobakin switch (params->fec) { 175599785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE: 175699785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_NONE; 175799785a87SAlexander Lobakin break; 175899785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE: 175999785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_BASE_R; 176099785a87SAlexander Lobakin break; 176199785a87SAlexander Lobakin case FEC_FORCE_MODE_RS: 176299785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528; 176399785a87SAlexander Lobakin break; 176499785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO: 176599785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528 | 176699785a87SAlexander Lobakin ETH_EXT_FEC_100G_BASE_R | 176799785a87SAlexander Lobakin ETH_EXT_FEC_100G_NONE; 176899785a87SAlexander Lobakin break; 176999785a87SAlexander Lobakin default: 177099785a87SAlexander Lobakin break; 177199785a87SAlexander Lobakin } 177299785a87SAlexander Lobakin 177399785a87SAlexander Lobakin break; 177499785a87SAlexander Lobakin default: 177599785a87SAlexander Lobakin break; 177699785a87SAlexander Lobakin } 177799785a87SAlexander Lobakin } 177899785a87SAlexander Lobakin 1779351a4dedSYuval Mintz static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params) 1780cc875c2eSYuval Mintz { 1781cc875c2eSYuval Mintz struct qed_mcp_link_params *link_params; 1782097818fcSAlexander Lobakin struct qed_mcp_link_speed_params *speed; 1783097818fcSAlexander Lobakin const struct qed_mfw_speed_map *map; 1784bdb5d8ecSAlexander Lobakin struct qed_hwfn *hwfn; 1785cc875c2eSYuval Mintz struct qed_ptt *ptt; 1786cc875c2eSYuval Mintz int rc; 1787097818fcSAlexander Lobakin u32 i; 1788cc875c2eSYuval Mintz 1789cc875c2eSYuval Mintz if (!cdev) 1790cc875c2eSYuval Mintz return -ENODEV; 1791cc875c2eSYuval Mintz 1792cc875c2eSYuval Mintz /* The link should be set only once per PF */ 1793cc875c2eSYuval Mintz hwfn = &cdev->hwfns[0]; 1794cc875c2eSYuval Mintz 179565ed2ffdSMintz, Yuval /* When VF wants to set link, force it to read the bulletin instead. 179665ed2ffdSMintz, Yuval * This mimics the PF behavior, where a noitification [both immediate 179765ed2ffdSMintz, Yuval * and possible later] would be generated when changing properties. 179865ed2ffdSMintz, Yuval */ 179965ed2ffdSMintz, Yuval if (IS_VF(cdev)) { 180065ed2ffdSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG); 180165ed2ffdSMintz, Yuval return 0; 180265ed2ffdSMintz, Yuval } 180365ed2ffdSMintz, Yuval 1804cc875c2eSYuval Mintz ptt = qed_ptt_acquire(hwfn); 1805cc875c2eSYuval Mintz if (!ptt) 1806cc875c2eSYuval Mintz return -EBUSY; 1807cc875c2eSYuval Mintz 1808cc875c2eSYuval Mintz link_params = qed_mcp_get_link_params(hwfn); 1809bdb5d8ecSAlexander Lobakin if (!link_params) 1810bdb5d8ecSAlexander Lobakin return -ENODATA; 1811bdb5d8ecSAlexander Lobakin 1812097818fcSAlexander Lobakin speed = &link_params->speed; 1813097818fcSAlexander Lobakin 1814cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) 1815097818fcSAlexander Lobakin speed->autoneg = !!params->autoneg; 1816bdb5d8ecSAlexander Lobakin 1817cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { 1818097818fcSAlexander Lobakin speed->advertised_speeds = 0; 1819bdb5d8ecSAlexander Lobakin 1820097818fcSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++) { 1821097818fcSAlexander Lobakin map = qed_mfw_legacy_maps + i; 1822bdb5d8ecSAlexander Lobakin 1823097818fcSAlexander Lobakin if (linkmode_intersects(params->adv_speeds, map->caps)) 1824097818fcSAlexander Lobakin speed->advertised_speeds |= map->mfw_val; 1825097818fcSAlexander Lobakin } 1826cc875c2eSYuval Mintz } 1827bdb5d8ecSAlexander Lobakin 1828cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) 1829097818fcSAlexander Lobakin speed->forced_speed = params->forced_speed; 1830097818fcSAlexander Lobakin 183199785a87SAlexander Lobakin if (qed_mcp_is_ext_speed_supported(hwfn)) 183299785a87SAlexander Lobakin qed_set_ext_speed_params(link_params, params); 183399785a87SAlexander Lobakin 1834a43f235fSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) { 1835a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 1836a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = true; 1837a43f235fSSudarsana Reddy Kalluru else 1838a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = false; 1839a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE) 1840a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = true; 1841a43f235fSSudarsana Reddy Kalluru else 1842a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = false; 1843a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE) 1844a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = true; 1845a43f235fSSudarsana Reddy Kalluru else 1846a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = false; 1847a43f235fSSudarsana Reddy Kalluru } 1848097818fcSAlexander Lobakin 184903dc76caSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) { 185003dc76caSSudarsana Reddy Kalluru switch (params->loopback_mode) { 185103dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_INT_PHY: 1852351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_INT_PHY; 185303dc76caSSudarsana Reddy Kalluru break; 185403dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT_PHY: 1855351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT_PHY; 185603dc76caSSudarsana Reddy Kalluru break; 185703dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT: 1858351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT; 185903dc76caSSudarsana Reddy Kalluru break; 186003dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_MAC: 1861351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_MAC; 186203dc76caSSudarsana Reddy Kalluru break; 186398e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_CNIG_AH_ONLY_0123: 186498e675ecSAlexander Lobakin link_params->loopback_mode = 186598e675ecSAlexander Lobakin ETH_LOOPBACK_CNIG_AH_ONLY_0123; 186698e675ecSAlexander Lobakin break; 186798e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_CNIG_AH_ONLY_2301: 186898e675ecSAlexander Lobakin link_params->loopback_mode = 186998e675ecSAlexander Lobakin ETH_LOOPBACK_CNIG_AH_ONLY_2301; 187098e675ecSAlexander Lobakin break; 187198e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_PCS_AH_ONLY: 187298e675ecSAlexander Lobakin link_params->loopback_mode = ETH_LOOPBACK_PCS_AH_ONLY; 187398e675ecSAlexander Lobakin break; 187498e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_REVERSE_MAC_AH_ONLY: 187598e675ecSAlexander Lobakin link_params->loopback_mode = 187698e675ecSAlexander Lobakin ETH_LOOPBACK_REVERSE_MAC_AH_ONLY; 187798e675ecSAlexander Lobakin break; 187898e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_INT_PHY_FEA_AH_ONLY: 187998e675ecSAlexander Lobakin link_params->loopback_mode = 188098e675ecSAlexander Lobakin ETH_LOOPBACK_INT_PHY_FEA_AH_ONLY; 188198e675ecSAlexander Lobakin break; 188203dc76caSSudarsana Reddy Kalluru default: 1883351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_NONE; 188403dc76caSSudarsana Reddy Kalluru break; 188503dc76caSSudarsana Reddy Kalluru } 188603dc76caSSudarsana Reddy Kalluru } 1887cc875c2eSYuval Mintz 1888645874e5SSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG) 1889645874e5SSudarsana Reddy Kalluru memcpy(&link_params->eee, ¶ms->eee, 1890645874e5SSudarsana Reddy Kalluru sizeof(link_params->eee)); 1891645874e5SSudarsana Reddy Kalluru 1892ae7e6937SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG) 1893ae7e6937SAlexander Lobakin link_params->fec = params->fec; 1894ae7e6937SAlexander Lobakin 1895cc875c2eSYuval Mintz rc = qed_mcp_set_link(hwfn, ptt, params->link_up); 1896cc875c2eSYuval Mintz 1897cc875c2eSYuval Mintz qed_ptt_release(hwfn, ptt); 1898cc875c2eSYuval Mintz 1899cc875c2eSYuval Mintz return rc; 1900cc875c2eSYuval Mintz } 1901cc875c2eSYuval Mintz 1902cc875c2eSYuval Mintz static int qed_get_port_type(u32 media_type) 1903cc875c2eSYuval Mintz { 1904cc875c2eSYuval Mintz int port_type; 1905cc875c2eSYuval Mintz 1906cc875c2eSYuval Mintz switch (media_type) { 1907cc875c2eSYuval Mintz case MEDIA_SFPP_10G_FIBER: 1908cc875c2eSYuval Mintz case MEDIA_SFP_1G_FIBER: 1909cc875c2eSYuval Mintz case MEDIA_XFP_FIBER: 1910b639f197SYuval Mintz case MEDIA_MODULE_FIBER: 1911cc875c2eSYuval Mintz port_type = PORT_FIBRE; 1912cc875c2eSYuval Mintz break; 1913cc875c2eSYuval Mintz case MEDIA_DA_TWINAX: 1914cc875c2eSYuval Mintz port_type = PORT_DA; 1915cc875c2eSYuval Mintz break; 1916cc875c2eSYuval Mintz case MEDIA_BASE_T: 1917cc875c2eSYuval Mintz port_type = PORT_TP; 1918cc875c2eSYuval Mintz break; 191999785a87SAlexander Lobakin case MEDIA_KR: 1920cc875c2eSYuval Mintz case MEDIA_NOT_PRESENT: 1921cc875c2eSYuval Mintz port_type = PORT_NONE; 1922cc875c2eSYuval Mintz break; 1923cc875c2eSYuval Mintz case MEDIA_UNSPECIFIED: 1924cc875c2eSYuval Mintz default: 1925cc875c2eSYuval Mintz port_type = PORT_OTHER; 1926cc875c2eSYuval Mintz break; 1927cc875c2eSYuval Mintz } 1928cc875c2eSYuval Mintz return port_type; 1929cc875c2eSYuval Mintz } 1930cc875c2eSYuval Mintz 193114b84e86SArnd Bergmann static int qed_get_link_data(struct qed_hwfn *hwfn, 193214b84e86SArnd Bergmann struct qed_mcp_link_params *params, 193314b84e86SArnd Bergmann struct qed_mcp_link_state *link, 193414b84e86SArnd Bergmann struct qed_mcp_link_capabilities *link_caps) 193514b84e86SArnd Bergmann { 193614b84e86SArnd Bergmann void *p; 193714b84e86SArnd Bergmann 193814b84e86SArnd Bergmann if (!IS_PF(hwfn->cdev)) { 193914b84e86SArnd Bergmann qed_vf_get_link_params(hwfn, params); 194014b84e86SArnd Bergmann qed_vf_get_link_state(hwfn, link); 194114b84e86SArnd Bergmann qed_vf_get_link_caps(hwfn, link_caps); 194214b84e86SArnd Bergmann 194314b84e86SArnd Bergmann return 0; 194414b84e86SArnd Bergmann } 194514b84e86SArnd Bergmann 194614b84e86SArnd Bergmann p = qed_mcp_get_link_params(hwfn); 194714b84e86SArnd Bergmann if (!p) 194814b84e86SArnd Bergmann return -ENXIO; 194914b84e86SArnd Bergmann memcpy(params, p, sizeof(*params)); 195014b84e86SArnd Bergmann 195114b84e86SArnd Bergmann p = qed_mcp_get_link_state(hwfn); 195214b84e86SArnd Bergmann if (!p) 195314b84e86SArnd Bergmann return -ENXIO; 195414b84e86SArnd Bergmann memcpy(link, p, sizeof(*link)); 195514b84e86SArnd Bergmann 195614b84e86SArnd Bergmann p = qed_mcp_get_link_capabilities(hwfn); 195714b84e86SArnd Bergmann if (!p) 195814b84e86SArnd Bergmann return -ENXIO; 195914b84e86SArnd Bergmann memcpy(link_caps, p, sizeof(*link_caps)); 196014b84e86SArnd Bergmann 196114b84e86SArnd Bergmann return 0; 196214b84e86SArnd Bergmann } 196314b84e86SArnd Bergmann 1964c56a8be7SRahul Verma static void qed_fill_link_capability(struct qed_hwfn *hwfn, 1965c56a8be7SRahul Verma struct qed_ptt *ptt, u32 capability, 1966bdb5d8ecSAlexander Lobakin unsigned long *if_caps) 1967c56a8be7SRahul Verma { 1968c56a8be7SRahul Verma u32 media_type, tcvr_state, tcvr_type; 1969c56a8be7SRahul Verma u32 speed_mask, board_cfg; 1970c56a8be7SRahul Verma 1971c56a8be7SRahul Verma if (qed_mcp_get_media_type(hwfn, ptt, &media_type)) 1972c56a8be7SRahul Verma media_type = MEDIA_UNSPECIFIED; 1973c56a8be7SRahul Verma 1974c56a8be7SRahul Verma if (qed_mcp_get_transceiver_data(hwfn, ptt, &tcvr_state, &tcvr_type)) 1975c56a8be7SRahul Verma tcvr_type = ETH_TRANSCEIVER_STATE_UNPLUGGED; 1976c56a8be7SRahul Verma 1977c56a8be7SRahul Verma if (qed_mcp_trans_speed_mask(hwfn, ptt, &speed_mask)) 1978c56a8be7SRahul Verma speed_mask = 0xFFFFFFFF; 1979c56a8be7SRahul Verma 1980c56a8be7SRahul Verma if (qed_mcp_get_board_config(hwfn, ptt, &board_cfg)) 1981c56a8be7SRahul Verma board_cfg = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED; 1982c56a8be7SRahul Verma 1983c56a8be7SRahul Verma DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV, 1984c56a8be7SRahul Verma "Media_type = 0x%x tcvr_state = 0x%x tcvr_type = 0x%x speed_mask = 0x%x board_cfg = 0x%x\n", 1985c56a8be7SRahul Verma media_type, tcvr_state, tcvr_type, speed_mask, board_cfg); 1986c56a8be7SRahul Verma 1987c56a8be7SRahul Verma switch (media_type) { 1988c56a8be7SRahul Verma case MEDIA_DA_TWINAX: 1989bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE); 1990bdb5d8ecSAlexander Lobakin 1991c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) 1992bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full); 1993bdb5d8ecSAlexander Lobakin 1994c56a8be7SRahul Verma /* For DAC media multiple speed capabilities are supported */ 19959228b7c1SAlexander Lobakin capability |= speed_mask; 19969228b7c1SAlexander Lobakin 1997c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 1998bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full); 1999c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 2000bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseCR_Full); 20019228b7c1SAlexander Lobakin 2002c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 20039228b7c1SAlexander Lobakin switch (tcvr_type) { 20049228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_CR4: 20059228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR: 20069228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR: 2007bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseCR4_Full); 20089228b7c1SAlexander Lobakin break; 20099228b7c1SAlexander Lobakin default: 20109228b7c1SAlexander Lobakin break; 20119228b7c1SAlexander Lobakin } 20129228b7c1SAlexander Lobakin 2013c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 2014bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseCR_Full); 2015c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 2016bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseCR2_Full); 20179228b7c1SAlexander Lobakin 2018c56a8be7SRahul Verma if (capability & 2019c56a8be7SRahul Verma NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 20209228b7c1SAlexander Lobakin switch (tcvr_type) { 20219228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_100G_CR4: 20229228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR: 2023bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseCR4_Full); 20249228b7c1SAlexander Lobakin break; 20259228b7c1SAlexander Lobakin default: 20269228b7c1SAlexander Lobakin break; 20279228b7c1SAlexander Lobakin } 2028bdb5d8ecSAlexander Lobakin 2029c56a8be7SRahul Verma break; 2030c56a8be7SRahul Verma case MEDIA_BASE_T: 2031bdb5d8ecSAlexander Lobakin phylink_set(if_caps, TP); 2032bdb5d8ecSAlexander Lobakin 2033c56a8be7SRahul Verma if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) { 2034c56a8be7SRahul Verma if (capability & 2035bdb5d8ecSAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 2036bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseT_Full); 2037c56a8be7SRahul Verma if (capability & 2038bdb5d8ecSAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 2039bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseT_Full); 2040c56a8be7SRahul Verma } 2041bdb5d8ecSAlexander Lobakin 2042c56a8be7SRahul Verma if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) { 2043bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE); 2044bdb5d8ecSAlexander Lobakin 20459228b7c1SAlexander Lobakin switch (tcvr_type) { 20469228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1000BASET: 2047bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseT_Full); 20489228b7c1SAlexander Lobakin break; 20499228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_BASET: 2050bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseT_Full); 20519228b7c1SAlexander Lobakin break; 20529228b7c1SAlexander Lobakin default: 20539228b7c1SAlexander Lobakin break; 20549228b7c1SAlexander Lobakin } 2055c56a8be7SRahul Verma } 2056bdb5d8ecSAlexander Lobakin 2057c56a8be7SRahul Verma break; 2058c56a8be7SRahul Verma case MEDIA_SFP_1G_FIBER: 2059c56a8be7SRahul Verma case MEDIA_SFPP_10G_FIBER: 2060c56a8be7SRahul Verma case MEDIA_XFP_FIBER: 2061c56a8be7SRahul Verma case MEDIA_MODULE_FIBER: 2062bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE); 20639228b7c1SAlexander Lobakin capability |= speed_mask; 2064bdb5d8ecSAlexander Lobakin 20659228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 20669228b7c1SAlexander Lobakin switch (tcvr_type) { 20679228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1G_LX: 20689228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1G_SX: 20699228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR: 20709228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR: 2071bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full); 20729228b7c1SAlexander Lobakin break; 20739228b7c1SAlexander Lobakin default: 20749228b7c1SAlexander Lobakin break; 2075c56a8be7SRahul Verma } 2076bdb5d8ecSAlexander Lobakin 20779228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 20789228b7c1SAlexander Lobakin switch (tcvr_type) { 20799228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_SR: 20809228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR: 20819228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR: 20829228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR: 2083bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseSR_Full); 20849228b7c1SAlexander Lobakin break; 20859228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_LR: 20869228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR: 20879228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR: 20889228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR: 2089bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseLR_Full); 20909228b7c1SAlexander Lobakin break; 20919228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_LRM: 2092bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseLRM_Full); 20939228b7c1SAlexander Lobakin break; 20949228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_ER: 2095bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseR_FEC); 20969228b7c1SAlexander Lobakin break; 20979228b7c1SAlexander Lobakin default: 20989228b7c1SAlexander Lobakin break; 2099c56a8be7SRahul Verma } 2100bdb5d8ecSAlexander Lobakin 2101c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) 2102bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full); 2103bdb5d8ecSAlexander Lobakin 21049228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 21059228b7c1SAlexander Lobakin switch (tcvr_type) { 21069228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_25G_SR: 21079228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR: 2108bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseSR_Full); 21099228b7c1SAlexander Lobakin break; 21109228b7c1SAlexander Lobakin default: 21119228b7c1SAlexander Lobakin break; 2112c56a8be7SRahul Verma } 2113bdb5d8ecSAlexander Lobakin 21149228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 21159228b7c1SAlexander Lobakin switch (tcvr_type) { 21169228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_LR4: 21179228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR: 21189228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR: 2119bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseLR4_Full); 21209228b7c1SAlexander Lobakin break; 21219228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_SR4: 21229228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR: 21239228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR: 2124bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseSR4_Full); 21259228b7c1SAlexander Lobakin break; 21269228b7c1SAlexander Lobakin default: 21279228b7c1SAlexander Lobakin break; 2128c56a8be7SRahul Verma } 2129bdb5d8ecSAlexander Lobakin 2130bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 2131bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseKR2_Full); 2132bdb5d8ecSAlexander Lobakin 2133c56a8be7SRahul Verma if (capability & 21349228b7c1SAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 21359228b7c1SAlexander Lobakin switch (tcvr_type) { 21369228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_100G_SR4: 21379228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR: 2138bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseSR4_Full); 21399228b7c1SAlexander Lobakin break; 21409228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR: 21419228b7c1SAlexander Lobakin phylink_set(if_caps, 100000baseLR4_ER4_Full); 21429228b7c1SAlexander Lobakin break; 21439228b7c1SAlexander Lobakin default: 21449228b7c1SAlexander Lobakin break; 2145c56a8be7SRahul Verma } 2146c56a8be7SRahul Verma 2147c56a8be7SRahul Verma break; 2148c56a8be7SRahul Verma case MEDIA_KR: 2149bdb5d8ecSAlexander Lobakin phylink_set(if_caps, Backplane); 2150bdb5d8ecSAlexander Lobakin 2151c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) 2152bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full); 2153bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) 2154bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full); 2155bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) 2156bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseKR_Full); 2157bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) 2158bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseKR_Full); 2159bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) 2160bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseKR4_Full); 2161bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) 2162bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseKR2_Full); 2163c56a8be7SRahul Verma if (capability & 2164c56a8be7SRahul Verma NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) 2165bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseKR4_Full); 2166bdb5d8ecSAlexander Lobakin 2167c56a8be7SRahul Verma break; 2168c56a8be7SRahul Verma case MEDIA_UNSPECIFIED: 2169c56a8be7SRahul Verma case MEDIA_NOT_PRESENT: 21709228b7c1SAlexander Lobakin default: 2171c56a8be7SRahul Verma DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG, 2172c56a8be7SRahul Verma "Unknown media and transceiver type;\n"); 2173c56a8be7SRahul Verma break; 2174c56a8be7SRahul Verma } 2175c56a8be7SRahul Verma } 2176c56a8be7SRahul Verma 21773c41486eSAlexander Lobakin static void qed_lp_caps_to_speed_mask(u32 caps, u32 *speed_mask) 21783c41486eSAlexander Lobakin { 21793c41486eSAlexander Lobakin *speed_mask = 0; 21803c41486eSAlexander Lobakin 21813c41486eSAlexander Lobakin if (caps & 21823c41486eSAlexander Lobakin (QED_LINK_PARTNER_SPEED_1G_FD | QED_LINK_PARTNER_SPEED_1G_HD)) 21833c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G; 21843c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_10G) 21853c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G; 21863c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_20G) 21873c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G; 21883c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_25G) 21893c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G; 21903c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_40G) 21913c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G; 21923c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_50G) 21933c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G; 21943c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_100G) 21953c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G; 21963c41486eSAlexander Lobakin } 21973c41486eSAlexander Lobakin 2198cc875c2eSYuval Mintz static void qed_fill_link(struct qed_hwfn *hwfn, 2199706d0891SRahul Verma struct qed_ptt *ptt, 2200cc875c2eSYuval Mintz struct qed_link_output *if_link) 2201cc875c2eSYuval Mintz { 2202c56a8be7SRahul Verma struct qed_mcp_link_capabilities link_caps; 2203cc875c2eSYuval Mintz struct qed_mcp_link_params params; 2204cc875c2eSYuval Mintz struct qed_mcp_link_state link; 22053c41486eSAlexander Lobakin u32 media_type, speed_mask; 2206cc875c2eSYuval Mintz 2207cc875c2eSYuval Mintz memset(if_link, 0, sizeof(*if_link)); 2208cc875c2eSYuval Mintz 2209cc875c2eSYuval Mintz /* Prepare source inputs */ 221014b84e86SArnd Bergmann if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) { 221114b84e86SArnd Bergmann dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n"); 221214b84e86SArnd Bergmann return; 22131408cc1fSYuval Mintz } 2214cc875c2eSYuval Mintz 2215cc875c2eSYuval Mintz /* Set the link parameters to pass to protocol driver */ 2216cc875c2eSYuval Mintz if (link.link_up) 2217cc875c2eSYuval Mintz if_link->link_up = true; 2218cc875c2eSYuval Mintz 221999785a87SAlexander Lobakin if (IS_PF(hwfn->cdev) && qed_mcp_is_ext_speed_supported(hwfn)) { 222099785a87SAlexander Lobakin if (link_caps.default_ext_autoneg) 222199785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Autoneg); 222299785a87SAlexander Lobakin 222399785a87SAlexander Lobakin linkmode_copy(if_link->advertised_caps, if_link->supported_caps); 222499785a87SAlexander Lobakin 222599785a87SAlexander Lobakin if (params.ext_speed.autoneg) 222699785a87SAlexander Lobakin phylink_set(if_link->advertised_caps, Autoneg); 222799785a87SAlexander Lobakin else 222899785a87SAlexander Lobakin phylink_clear(if_link->advertised_caps, Autoneg); 222999785a87SAlexander Lobakin 223099785a87SAlexander Lobakin qed_fill_link_capability(hwfn, ptt, 223199785a87SAlexander Lobakin params.ext_speed.advertised_speeds, 223299785a87SAlexander Lobakin if_link->advertised_caps); 223399785a87SAlexander Lobakin } else { 223434f9199cSsudarsana.kalluru@cavium.com if (link_caps.default_speed_autoneg) 2235bdb5d8ecSAlexander Lobakin phylink_set(if_link->supported_caps, Autoneg); 2236cc875c2eSYuval Mintz 2237bdb5d8ecSAlexander Lobakin linkmode_copy(if_link->advertised_caps, if_link->supported_caps); 2238bdb5d8ecSAlexander Lobakin 223934f9199cSsudarsana.kalluru@cavium.com if (params.speed.autoneg) 2240bdb5d8ecSAlexander Lobakin phylink_set(if_link->advertised_caps, Autoneg); 224134f9199cSsudarsana.kalluru@cavium.com else 2242bdb5d8ecSAlexander Lobakin phylink_clear(if_link->advertised_caps, Autoneg); 224399785a87SAlexander Lobakin } 224499785a87SAlexander Lobakin 224599785a87SAlexander Lobakin if (params.pause.autoneg || 224699785a87SAlexander Lobakin (params.pause.forced_rx && params.pause.forced_tx)) 224799785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Asym_Pause); 224899785a87SAlexander Lobakin if (params.pause.autoneg || params.pause.forced_rx || 224999785a87SAlexander Lobakin params.pause.forced_tx) 225099785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Pause); 2251cc875c2eSYuval Mintz 2252ae7e6937SAlexander Lobakin if_link->sup_fec = link_caps.fec_default; 2253ae7e6937SAlexander Lobakin if_link->active_fec = params.fec; 2254ae7e6937SAlexander Lobakin 2255c56a8be7SRahul Verma /* Fill link advertised capability */ 2256c56a8be7SRahul Verma qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds, 2257bdb5d8ecSAlexander Lobakin if_link->advertised_caps); 22583c41486eSAlexander Lobakin 2259c56a8be7SRahul Verma /* Fill link supported capability */ 2260c56a8be7SRahul Verma qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities, 2261bdb5d8ecSAlexander Lobakin if_link->supported_caps); 2262cc875c2eSYuval Mintz 22633c41486eSAlexander Lobakin /* Fill partner advertised capability */ 22643c41486eSAlexander Lobakin qed_lp_caps_to_speed_mask(link.partner_adv_speed, &speed_mask); 22653c41486eSAlexander Lobakin qed_fill_link_capability(hwfn, ptt, speed_mask, if_link->lp_caps); 22663c41486eSAlexander Lobakin 2267cc875c2eSYuval Mintz if (link.link_up) 2268cc875c2eSYuval Mintz if_link->speed = link.speed; 2269cc875c2eSYuval Mintz 2270cc875c2eSYuval Mintz /* TODO - fill duplex properly */ 2271cc875c2eSYuval Mintz if_link->duplex = DUPLEX_FULL; 2272706d0891SRahul Verma qed_mcp_get_media_type(hwfn, ptt, &media_type); 2273cc875c2eSYuval Mintz if_link->port = qed_get_port_type(media_type); 2274cc875c2eSYuval Mintz 2275cc875c2eSYuval Mintz if_link->autoneg = params.speed.autoneg; 2276cc875c2eSYuval Mintz 2277cc875c2eSYuval Mintz if (params.pause.autoneg) 2278cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 2279cc875c2eSYuval Mintz if (params.pause.forced_rx) 2280cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE; 2281cc875c2eSYuval Mintz if (params.pause.forced_tx) 2282cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE; 2283cc875c2eSYuval Mintz 2284cc875c2eSYuval Mintz if (link.an_complete) 2285bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Autoneg); 2286cc875c2eSYuval Mintz if (link.partner_adv_pause) 2287bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Pause); 2288cc875c2eSYuval Mintz if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE || 2289cc875c2eSYuval Mintz link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE) 2290bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Asym_Pause); 2291645874e5SSudarsana Reddy Kalluru 2292645874e5SSudarsana Reddy Kalluru if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) { 2293645874e5SSudarsana Reddy Kalluru if_link->eee_supported = false; 2294645874e5SSudarsana Reddy Kalluru } else { 2295645874e5SSudarsana Reddy Kalluru if_link->eee_supported = true; 2296645874e5SSudarsana Reddy Kalluru if_link->eee_active = link.eee_active; 2297645874e5SSudarsana Reddy Kalluru if_link->sup_caps = link_caps.eee_speed_caps; 2298645874e5SSudarsana Reddy Kalluru /* MFW clears adv_caps on eee disable; use configured value */ 2299645874e5SSudarsana Reddy Kalluru if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps : 2300645874e5SSudarsana Reddy Kalluru params.eee.adv_caps; 2301645874e5SSudarsana Reddy Kalluru if_link->eee.lp_adv_caps = link.eee_lp_adv_caps; 2302645874e5SSudarsana Reddy Kalluru if_link->eee.enable = params.eee.enable; 2303645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable; 2304645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer; 2305645874e5SSudarsana Reddy Kalluru } 2306cc875c2eSYuval Mintz } 2307cc875c2eSYuval Mintz 2308cc875c2eSYuval Mintz static void qed_get_current_link(struct qed_dev *cdev, 2309cc875c2eSYuval Mintz struct qed_link_output *if_link) 2310cc875c2eSYuval Mintz { 2311706d0891SRahul Verma struct qed_hwfn *hwfn; 2312706d0891SRahul Verma struct qed_ptt *ptt; 231336558c3dSYuval Mintz int i; 231436558c3dSYuval Mintz 2315706d0891SRahul Verma hwfn = &cdev->hwfns[0]; 2316706d0891SRahul Verma if (IS_PF(cdev)) { 2317706d0891SRahul Verma ptt = qed_ptt_acquire(hwfn); 2318706d0891SRahul Verma if (ptt) { 2319706d0891SRahul Verma qed_fill_link(hwfn, ptt, if_link); 2320706d0891SRahul Verma qed_ptt_release(hwfn, ptt); 2321706d0891SRahul Verma } else { 2322706d0891SRahul Verma DP_NOTICE(hwfn, "Failed to fill link; No PTT\n"); 2323706d0891SRahul Verma } 2324706d0891SRahul Verma } else { 2325706d0891SRahul Verma qed_fill_link(hwfn, NULL, if_link); 2326706d0891SRahul Verma } 232736558c3dSYuval Mintz 232836558c3dSYuval Mintz for_each_hwfn(cdev, i) 232936558c3dSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]); 2330cc875c2eSYuval Mintz } 2331cc875c2eSYuval Mintz 2332706d0891SRahul Verma void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt) 2333cc875c2eSYuval Mintz { 2334cc875c2eSYuval Mintz void *cookie = hwfn->cdev->ops_cookie; 2335cc875c2eSYuval Mintz struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 2336cc875c2eSYuval Mintz struct qed_link_output if_link; 2337cc875c2eSYuval Mintz 2338706d0891SRahul Verma qed_fill_link(hwfn, ptt, &if_link); 233936558c3dSYuval Mintz qed_inform_vf_link_state(hwfn); 2340cc875c2eSYuval Mintz 2341cc875c2eSYuval Mintz if (IS_LEAD_HWFN(hwfn) && cookie) 2342cc875c2eSYuval Mintz op->link_update(cookie, &if_link); 2343cc875c2eSYuval Mintz } 2344cc875c2eSYuval Mintz 2345699fed4aSSudarsana Reddy Kalluru void qed_bw_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt) 2346699fed4aSSudarsana Reddy Kalluru { 2347699fed4aSSudarsana Reddy Kalluru void *cookie = hwfn->cdev->ops_cookie; 2348699fed4aSSudarsana Reddy Kalluru struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; 2349699fed4aSSudarsana Reddy Kalluru 2350699fed4aSSudarsana Reddy Kalluru if (IS_LEAD_HWFN(hwfn) && cookie && op && op->bw_update) 2351699fed4aSSudarsana Reddy Kalluru op->bw_update(cookie); 2352699fed4aSSudarsana Reddy Kalluru } 2353699fed4aSSudarsana Reddy Kalluru 2354fe56b9e6SYuval Mintz static int qed_drain(struct qed_dev *cdev) 2355fe56b9e6SYuval Mintz { 2356fe56b9e6SYuval Mintz struct qed_hwfn *hwfn; 2357fe56b9e6SYuval Mintz struct qed_ptt *ptt; 2358fe56b9e6SYuval Mintz int i, rc; 2359fe56b9e6SYuval Mintz 23601408cc1fSYuval Mintz if (IS_VF(cdev)) 23611408cc1fSYuval Mintz return 0; 23621408cc1fSYuval Mintz 2363fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) { 2364fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i]; 2365fe56b9e6SYuval Mintz ptt = qed_ptt_acquire(hwfn); 2366fe56b9e6SYuval Mintz if (!ptt) { 2367fe56b9e6SYuval Mintz DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n"); 2368fe56b9e6SYuval Mintz return -EBUSY; 2369fe56b9e6SYuval Mintz } 2370fe56b9e6SYuval Mintz rc = qed_mcp_drain(hwfn, ptt); 23719aaa4e8bSDenis Bolotin qed_ptt_release(hwfn, ptt); 2372fe56b9e6SYuval Mintz if (rc) 2373fe56b9e6SYuval Mintz return rc; 2374fe56b9e6SYuval Mintz } 2375fe56b9e6SYuval Mintz 2376fe56b9e6SYuval Mintz return 0; 2377fe56b9e6SYuval Mintz } 2378fe56b9e6SYuval Mintz 23793a69cae8SSudarsana Reddy Kalluru static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev, 23803a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att *nvm_image, 23813a69cae8SSudarsana Reddy Kalluru u32 *crc) 23823a69cae8SSudarsana Reddy Kalluru { 23833a69cae8SSudarsana Reddy Kalluru u8 *buf = NULL; 23845ab90341SAlexander Lobakin int rc; 23853a69cae8SSudarsana Reddy Kalluru 23863a69cae8SSudarsana Reddy Kalluru /* Allocate a buffer for holding the nvram image */ 23873a69cae8SSudarsana Reddy Kalluru buf = kzalloc(nvm_image->length, GFP_KERNEL); 23883a69cae8SSudarsana Reddy Kalluru if (!buf) 23893a69cae8SSudarsana Reddy Kalluru return -ENOMEM; 23903a69cae8SSudarsana Reddy Kalluru 23913a69cae8SSudarsana Reddy Kalluru /* Read image into buffer */ 23923a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr, 23933a69cae8SSudarsana Reddy Kalluru buf, nvm_image->length); 23943a69cae8SSudarsana Reddy Kalluru if (rc) { 23953a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading image from nvm\n"); 23963a69cae8SSudarsana Reddy Kalluru goto out; 23973a69cae8SSudarsana Reddy Kalluru } 23983a69cae8SSudarsana Reddy Kalluru 23993a69cae8SSudarsana Reddy Kalluru /* Convert the buffer into big-endian format (excluding the 24003a69cae8SSudarsana Reddy Kalluru * closing 4 bytes of CRC). 24013a69cae8SSudarsana Reddy Kalluru */ 24025ab90341SAlexander Lobakin cpu_to_be32_array((__force __be32 *)buf, (const u32 *)buf, 24035ab90341SAlexander Lobakin DIV_ROUND_UP(nvm_image->length - 4, 4)); 24043a69cae8SSudarsana Reddy Kalluru 24053a69cae8SSudarsana Reddy Kalluru /* Calc CRC for the "actual" image buffer, i.e. not including 24063a69cae8SSudarsana Reddy Kalluru * the last 4 CRC bytes. 24073a69cae8SSudarsana Reddy Kalluru */ 24085ab90341SAlexander Lobakin *crc = ~crc32(~0U, buf, nvm_image->length - 4); 24095ab90341SAlexander Lobakin *crc = (__force u32)cpu_to_be32p(crc); 24103a69cae8SSudarsana Reddy Kalluru 24113a69cae8SSudarsana Reddy Kalluru out: 24123a69cae8SSudarsana Reddy Kalluru kfree(buf); 24133a69cae8SSudarsana Reddy Kalluru 24143a69cae8SSudarsana Reddy Kalluru return rc; 24153a69cae8SSudarsana Reddy Kalluru } 24163a69cae8SSudarsana Reddy Kalluru 24173a69cae8SSudarsana Reddy Kalluru /* Binary file format - 24183a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 24193a69cae8SSudarsana Reddy Kalluru * 0B | 0x4 [command index] | 24203a69cae8SSudarsana Reddy Kalluru * 4B | image_type | Options | Number of register settings | 24213a69cae8SSudarsana Reddy Kalluru * 8B | Value | 24223a69cae8SSudarsana Reddy Kalluru * 12B | Mask | 24233a69cae8SSudarsana Reddy Kalluru * 16B | Offset | 24243a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 24253a69cae8SSudarsana Reddy Kalluru * There can be several Value-Mask-Offset sets as specified by 'Number of...'. 24263a69cae8SSudarsana Reddy Kalluru * Options - 0'b - Calculate & Update CRC for image 24273a69cae8SSudarsana Reddy Kalluru */ 24283a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data, 24293a69cae8SSudarsana Reddy Kalluru bool *check_resp) 24303a69cae8SSudarsana Reddy Kalluru { 24313a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att nvm_image; 24323a69cae8SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn; 24333a69cae8SSudarsana Reddy Kalluru bool is_crc = false; 24343a69cae8SSudarsana Reddy Kalluru u32 image_type; 24353a69cae8SSudarsana Reddy Kalluru int rc = 0, i; 24363a69cae8SSudarsana Reddy Kalluru u16 len; 24373a69cae8SSudarsana Reddy Kalluru 24383a69cae8SSudarsana Reddy Kalluru *data += 4; 24393a69cae8SSudarsana Reddy Kalluru image_type = **data; 24403a69cae8SSudarsana Reddy Kalluru p_hwfn = QED_LEADING_HWFN(cdev); 24413a69cae8SSudarsana Reddy Kalluru for (i = 0; i < p_hwfn->nvm_info.num_images; i++) 24423a69cae8SSudarsana Reddy Kalluru if (image_type == p_hwfn->nvm_info.image_att[i].image_type) 24433a69cae8SSudarsana Reddy Kalluru break; 24443a69cae8SSudarsana Reddy Kalluru if (i == p_hwfn->nvm_info.num_images) { 24453a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find nvram image of type %08x\n", 24463a69cae8SSudarsana Reddy Kalluru image_type); 24473a69cae8SSudarsana Reddy Kalluru return -ENOENT; 24483a69cae8SSudarsana Reddy Kalluru } 24493a69cae8SSudarsana Reddy Kalluru 24503a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr; 24513a69cae8SSudarsana Reddy Kalluru nvm_image.length = p_hwfn->nvm_info.image_att[i].len; 24523a69cae8SSudarsana Reddy Kalluru 24533a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 24543a69cae8SSudarsana Reddy Kalluru "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n", 24553a69cae8SSudarsana Reddy Kalluru **data, image_type, nvm_image.start_addr, 24563a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 1); 24573a69cae8SSudarsana Reddy Kalluru (*data)++; 24583a69cae8SSudarsana Reddy Kalluru is_crc = !!(**data & BIT(0)); 24593a69cae8SSudarsana Reddy Kalluru (*data)++; 24603a69cae8SSudarsana Reddy Kalluru len = *((u16 *)*data); 24613a69cae8SSudarsana Reddy Kalluru *data += 2; 24623a69cae8SSudarsana Reddy Kalluru if (is_crc) { 24633a69cae8SSudarsana Reddy Kalluru u32 crc = 0; 24643a69cae8SSudarsana Reddy Kalluru 24653a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc); 24663a69cae8SSudarsana Reddy Kalluru if (rc) { 24673a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc); 24683a69cae8SSudarsana Reddy Kalluru goto exit; 24693a69cae8SSudarsana Reddy Kalluru } 24703a69cae8SSudarsana Reddy Kalluru 24713a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM, 24723a69cae8SSudarsana Reddy Kalluru (nvm_image.start_addr + 24733a69cae8SSudarsana Reddy Kalluru nvm_image.length - 4), (u8 *)&crc, 4); 24743a69cae8SSudarsana Reddy Kalluru if (rc) 24753a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x, rc = %d\n", 24763a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 4, rc); 24773a69cae8SSudarsana Reddy Kalluru goto exit; 24783a69cae8SSudarsana Reddy Kalluru } 24793a69cae8SSudarsana Reddy Kalluru 24803a69cae8SSudarsana Reddy Kalluru /* Iterate over the values for setting */ 24813a69cae8SSudarsana Reddy Kalluru while (len) { 24823a69cae8SSudarsana Reddy Kalluru u32 offset, mask, value, cur_value; 24833a69cae8SSudarsana Reddy Kalluru u8 buf[4]; 24843a69cae8SSudarsana Reddy Kalluru 24853a69cae8SSudarsana Reddy Kalluru value = *((u32 *)*data); 24863a69cae8SSudarsana Reddy Kalluru *data += 4; 24873a69cae8SSudarsana Reddy Kalluru mask = *((u32 *)*data); 24883a69cae8SSudarsana Reddy Kalluru *data += 4; 24893a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)*data); 24903a69cae8SSudarsana Reddy Kalluru *data += 4; 24913a69cae8SSudarsana Reddy Kalluru 24923a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf, 24933a69cae8SSudarsana Reddy Kalluru 4); 24943a69cae8SSudarsana Reddy Kalluru if (rc) { 24953a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading from %08x\n", 24963a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset); 24973a69cae8SSudarsana Reddy Kalluru goto exit; 24983a69cae8SSudarsana Reddy Kalluru } 24993a69cae8SSudarsana Reddy Kalluru 25003a69cae8SSudarsana Reddy Kalluru cur_value = le32_to_cpu(*((__le32 *)buf)); 25013a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 25023a69cae8SSudarsana Reddy Kalluru "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n", 25033a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, cur_value, 25043a69cae8SSudarsana Reddy Kalluru (cur_value & ~mask) | (value & mask), value, mask); 25053a69cae8SSudarsana Reddy Kalluru value = (value & mask) | (cur_value & ~mask); 25063a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM, 25073a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, 25083a69cae8SSudarsana Reddy Kalluru (u8 *)&value, 4); 25093a69cae8SSudarsana Reddy Kalluru if (rc) { 25103a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x\n", 25113a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset); 25123a69cae8SSudarsana Reddy Kalluru goto exit; 25133a69cae8SSudarsana Reddy Kalluru } 25143a69cae8SSudarsana Reddy Kalluru 25153a69cae8SSudarsana Reddy Kalluru len--; 25163a69cae8SSudarsana Reddy Kalluru } 25173a69cae8SSudarsana Reddy Kalluru exit: 25183a69cae8SSudarsana Reddy Kalluru return rc; 25193a69cae8SSudarsana Reddy Kalluru } 25203a69cae8SSudarsana Reddy Kalluru 25213a69cae8SSudarsana Reddy Kalluru /* Binary file format - 25223a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 25233a69cae8SSudarsana Reddy Kalluru * 0B | 0x3 [command index] | 25243a69cae8SSudarsana Reddy Kalluru * 4B | b'0: check_response? | b'1-31 reserved | 25253a69cae8SSudarsana Reddy Kalluru * 8B | File-type | reserved | 2526057d2b19SSudarsana Reddy Kalluru * 12B | Image length in bytes | 25273a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 25283a69cae8SSudarsana Reddy Kalluru * Start a new file of the provided type 25293a69cae8SSudarsana Reddy Kalluru */ 25303a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_start(struct qed_dev *cdev, 25313a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp) 25323a69cae8SSudarsana Reddy Kalluru { 2533057d2b19SSudarsana Reddy Kalluru u32 file_type, file_size = 0; 25343a69cae8SSudarsana Reddy Kalluru int rc; 25353a69cae8SSudarsana Reddy Kalluru 25363a69cae8SSudarsana Reddy Kalluru *data += 4; 25373a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0)); 25383a69cae8SSudarsana Reddy Kalluru *data += 4; 2539057d2b19SSudarsana Reddy Kalluru file_type = **data; 25403a69cae8SSudarsana Reddy Kalluru 25413a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 2542057d2b19SSudarsana Reddy Kalluru "About to start a new file of type %02x\n", file_type); 2543057d2b19SSudarsana Reddy Kalluru if (file_type == DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MBI) { 2544057d2b19SSudarsana Reddy Kalluru *data += 4; 2545057d2b19SSudarsana Reddy Kalluru file_size = *((u32 *)(*data)); 2546057d2b19SSudarsana Reddy Kalluru } 2547057d2b19SSudarsana Reddy Kalluru 2548057d2b19SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_BEGIN, file_type, 2549057d2b19SSudarsana Reddy Kalluru (u8 *)(&file_size), 4); 25503a69cae8SSudarsana Reddy Kalluru *data += 4; 25513a69cae8SSudarsana Reddy Kalluru 25523a69cae8SSudarsana Reddy Kalluru return rc; 25533a69cae8SSudarsana Reddy Kalluru } 25543a69cae8SSudarsana Reddy Kalluru 25553a69cae8SSudarsana Reddy Kalluru /* Binary file format - 25563a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 25573a69cae8SSudarsana Reddy Kalluru * 0B | 0x2 [command index] | 25583a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes | 25593a69cae8SSudarsana Reddy Kalluru * 8B | b'0: check_response? | b'1-31 reserved | 25603a69cae8SSudarsana Reddy Kalluru * 12B | Offset in bytes | 25613a69cae8SSudarsana Reddy Kalluru * 16B | Data ... | 25623a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 25633a69cae8SSudarsana Reddy Kalluru * Write data as part of a file that was previously started. Data should be 25643a69cae8SSudarsana Reddy Kalluru * of length equal to that provided in the message 25653a69cae8SSudarsana Reddy Kalluru */ 25663a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_data(struct qed_dev *cdev, 25673a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp) 25683a69cae8SSudarsana Reddy Kalluru { 25693a69cae8SSudarsana Reddy Kalluru u32 offset, len; 25703a69cae8SSudarsana Reddy Kalluru int rc; 25713a69cae8SSudarsana Reddy Kalluru 25723a69cae8SSudarsana Reddy Kalluru *data += 4; 25733a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data)); 25743a69cae8SSudarsana Reddy Kalluru *data += 4; 25753a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0)); 25763a69cae8SSudarsana Reddy Kalluru *data += 4; 25773a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)(*data)); 25783a69cae8SSudarsana Reddy Kalluru *data += 4; 25793a69cae8SSudarsana Reddy Kalluru 25803a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 25813a69cae8SSudarsana Reddy Kalluru "About to write File-data: %08x bytes to offset %08x\n", 25823a69cae8SSudarsana Reddy Kalluru len, offset); 25833a69cae8SSudarsana Reddy Kalluru 25843a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset, 25853a69cae8SSudarsana Reddy Kalluru (char *)(*data), len); 25863a69cae8SSudarsana Reddy Kalluru *data += len; 25873a69cae8SSudarsana Reddy Kalluru 25883a69cae8SSudarsana Reddy Kalluru return rc; 25893a69cae8SSudarsana Reddy Kalluru } 25903a69cae8SSudarsana Reddy Kalluru 25913a69cae8SSudarsana Reddy Kalluru /* Binary file format [General header] - 25923a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 25933a69cae8SSudarsana Reddy Kalluru * 0B | QED_NVM_SIGNATURE | 25943a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes | 25953a69cae8SSudarsana Reddy Kalluru * 8B | Highest command in this batchfile | Reserved | 25963a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 25973a69cae8SSudarsana Reddy Kalluru */ 25983a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_validate(struct qed_dev *cdev, 25993a69cae8SSudarsana Reddy Kalluru const struct firmware *image, 26003a69cae8SSudarsana Reddy Kalluru const u8 **data) 26013a69cae8SSudarsana Reddy Kalluru { 26023a69cae8SSudarsana Reddy Kalluru u32 signature, len; 26033a69cae8SSudarsana Reddy Kalluru 26043a69cae8SSudarsana Reddy Kalluru /* Check minimum size */ 26053a69cae8SSudarsana Reddy Kalluru if (image->size < 12) { 26063a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size); 26073a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26083a69cae8SSudarsana Reddy Kalluru } 26093a69cae8SSudarsana Reddy Kalluru 26103a69cae8SSudarsana Reddy Kalluru /* Check signature */ 26113a69cae8SSudarsana Reddy Kalluru signature = *((u32 *)(*data)); 26123a69cae8SSudarsana Reddy Kalluru if (signature != QED_NVM_SIGNATURE) { 26133a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Wrong signature '%08x'\n", signature); 26143a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26153a69cae8SSudarsana Reddy Kalluru } 26163a69cae8SSudarsana Reddy Kalluru 26173a69cae8SSudarsana Reddy Kalluru *data += 4; 26183a69cae8SSudarsana Reddy Kalluru /* Validate internal size equals the image-size */ 26193a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data)); 26203a69cae8SSudarsana Reddy Kalluru if (len != image->size) { 26213a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n", 26223a69cae8SSudarsana Reddy Kalluru len, (u32)image->size); 26233a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26243a69cae8SSudarsana Reddy Kalluru } 26253a69cae8SSudarsana Reddy Kalluru 26263a69cae8SSudarsana Reddy Kalluru *data += 4; 26273a69cae8SSudarsana Reddy Kalluru /* Make sure driver familiar with all commands necessary for this */ 26283a69cae8SSudarsana Reddy Kalluru if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) { 26293a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n", 26303a69cae8SSudarsana Reddy Kalluru *((u16 *)(*data))); 26313a69cae8SSudarsana Reddy Kalluru return -EINVAL; 26323a69cae8SSudarsana Reddy Kalluru } 26333a69cae8SSudarsana Reddy Kalluru 26343a69cae8SSudarsana Reddy Kalluru *data += 4; 26353a69cae8SSudarsana Reddy Kalluru 26363a69cae8SSudarsana Reddy Kalluru return 0; 26373a69cae8SSudarsana Reddy Kalluru } 26383a69cae8SSudarsana Reddy Kalluru 26390dabbe1bSSudarsana Reddy Kalluru /* Binary file format - 26400dabbe1bSSudarsana Reddy Kalluru * /----------------------------------------------------------------------\ 26410dabbe1bSSudarsana Reddy Kalluru * 0B | 0x5 [command index] | 26422da244a5SSudarsana Reddy Kalluru * 4B | Number of config attributes | Reserved | 26432da244a5SSudarsana Reddy Kalluru * 4B | Config ID | Entity ID | Length | 26442da244a5SSudarsana Reddy Kalluru * 4B | Value | 26450dabbe1bSSudarsana Reddy Kalluru * | | 26460dabbe1bSSudarsana Reddy Kalluru * \----------------------------------------------------------------------/ 26472da244a5SSudarsana Reddy Kalluru * There can be several cfg_id-entity_id-Length-Value sets as specified by 26482da244a5SSudarsana Reddy Kalluru * 'Number of config attributes'. 26490dabbe1bSSudarsana Reddy Kalluru * 26500dabbe1bSSudarsana Reddy Kalluru * The API parses config attributes from the user provided buffer and flashes 26510dabbe1bSSudarsana Reddy Kalluru * them to the respective NVM path using Management FW inerface. 26520dabbe1bSSudarsana Reddy Kalluru */ 26530dabbe1bSSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data) 26540dabbe1bSSudarsana Reddy Kalluru { 26550dabbe1bSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 26560dabbe1bSSudarsana Reddy Kalluru u8 entity_id, len, buf[32]; 2657c63b0968SSudarsana Reddy Kalluru bool need_nvm_init = true; 26580dabbe1bSSudarsana Reddy Kalluru struct qed_ptt *ptt; 26590dabbe1bSSudarsana Reddy Kalluru u16 cfg_id, count; 26600dabbe1bSSudarsana Reddy Kalluru int rc = 0, i; 26610dabbe1bSSudarsana Reddy Kalluru u32 flags; 26620dabbe1bSSudarsana Reddy Kalluru 26630dabbe1bSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 26640dabbe1bSSudarsana Reddy Kalluru if (!ptt) 26650dabbe1bSSudarsana Reddy Kalluru return -EAGAIN; 26660dabbe1bSSudarsana Reddy Kalluru 26670dabbe1bSSudarsana Reddy Kalluru /* NVM CFG ID attribute header */ 26680dabbe1bSSudarsana Reddy Kalluru *data += 4; 26690dabbe1bSSudarsana Reddy Kalluru count = *((u16 *)*data); 26702da244a5SSudarsana Reddy Kalluru *data += 4; 26710dabbe1bSSudarsana Reddy Kalluru 26720dabbe1bSSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 26732da244a5SSudarsana Reddy Kalluru "Read config ids: num_attrs = %0d\n", count); 2674c63b0968SSudarsana Reddy Kalluru /* NVM CFG ID attributes. Start loop index from 1 to avoid additional 2675c63b0968SSudarsana Reddy Kalluru * arithmetic operations in the implementation. 2676c63b0968SSudarsana Reddy Kalluru */ 2677c63b0968SSudarsana Reddy Kalluru for (i = 1; i <= count; i++) { 26780dabbe1bSSudarsana Reddy Kalluru cfg_id = *((u16 *)*data); 26790dabbe1bSSudarsana Reddy Kalluru *data += 2; 26802da244a5SSudarsana Reddy Kalluru entity_id = **data; 26812da244a5SSudarsana Reddy Kalluru (*data)++; 26820dabbe1bSSudarsana Reddy Kalluru len = **data; 26830dabbe1bSSudarsana Reddy Kalluru (*data)++; 26840dabbe1bSSudarsana Reddy Kalluru memcpy(buf, *data, len); 26850dabbe1bSSudarsana Reddy Kalluru *data += len; 26860dabbe1bSSudarsana Reddy Kalluru 2687c63b0968SSudarsana Reddy Kalluru flags = 0; 2688c63b0968SSudarsana Reddy Kalluru if (need_nvm_init) { 2689c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_INIT; 2690c63b0968SSudarsana Reddy Kalluru need_nvm_init = false; 2691c63b0968SSudarsana Reddy Kalluru } 2692c63b0968SSudarsana Reddy Kalluru 2693c63b0968SSudarsana Reddy Kalluru /* Commit to flash and free the resources */ 2694c63b0968SSudarsana Reddy Kalluru if (!(i % QED_NVM_CFG_MAX_ATTRS) || i == count) { 2695c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_COMMIT | 2696c63b0968SSudarsana Reddy Kalluru QED_NVM_CFG_OPTION_FREE; 2697c63b0968SSudarsana Reddy Kalluru need_nvm_init = true; 2698c63b0968SSudarsana Reddy Kalluru } 2699c63b0968SSudarsana Reddy Kalluru 2700c63b0968SSudarsana Reddy Kalluru if (entity_id) 2701c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_ENTITY_SEL; 27020dabbe1bSSudarsana Reddy Kalluru 27030dabbe1bSSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 27042da244a5SSudarsana Reddy Kalluru "cfg_id = %d entity = %d len = %d\n", cfg_id, 27052da244a5SSudarsana Reddy Kalluru entity_id, len); 27060dabbe1bSSudarsana Reddy Kalluru rc = qed_mcp_nvm_set_cfg(hwfn, ptt, cfg_id, entity_id, flags, 27070dabbe1bSSudarsana Reddy Kalluru buf, len); 27080dabbe1bSSudarsana Reddy Kalluru if (rc) { 27090dabbe1bSSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d configuring %d\n", rc, cfg_id); 27100dabbe1bSSudarsana Reddy Kalluru break; 27110dabbe1bSSudarsana Reddy Kalluru } 27120dabbe1bSSudarsana Reddy Kalluru } 27130dabbe1bSSudarsana Reddy Kalluru 27140dabbe1bSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 27150dabbe1bSSudarsana Reddy Kalluru 27160dabbe1bSSudarsana Reddy Kalluru return rc; 27170dabbe1bSSudarsana Reddy Kalluru } 27180dabbe1bSSudarsana Reddy Kalluru 27199e54ba7cSSudarsana Reddy Kalluru #define QED_MAX_NVM_BUF_LEN 32 27209e54ba7cSSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_len(struct qed_dev *cdev, u32 cmd) 27219e54ba7cSSudarsana Reddy Kalluru { 27229e54ba7cSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 27239e54ba7cSSudarsana Reddy Kalluru u8 buf[QED_MAX_NVM_BUF_LEN]; 27249e54ba7cSSudarsana Reddy Kalluru struct qed_ptt *ptt; 27259e54ba7cSSudarsana Reddy Kalluru u32 len; 27269e54ba7cSSudarsana Reddy Kalluru int rc; 27279e54ba7cSSudarsana Reddy Kalluru 27289e54ba7cSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 27299e54ba7cSSudarsana Reddy Kalluru if (!ptt) 27309e54ba7cSSudarsana Reddy Kalluru return QED_MAX_NVM_BUF_LEN; 27319e54ba7cSSudarsana Reddy Kalluru 27329e54ba7cSSudarsana Reddy Kalluru rc = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, 0, QED_NVM_CFG_GET_FLAGS, buf, 27339e54ba7cSSudarsana Reddy Kalluru &len); 27349e54ba7cSSudarsana Reddy Kalluru if (rc || !len) { 27359e54ba7cSSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d reading %d\n", rc, cmd); 27369e54ba7cSSudarsana Reddy Kalluru len = QED_MAX_NVM_BUF_LEN; 27379e54ba7cSSudarsana Reddy Kalluru } 27389e54ba7cSSudarsana Reddy Kalluru 27399e54ba7cSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 27409e54ba7cSSudarsana Reddy Kalluru 27419e54ba7cSSudarsana Reddy Kalluru return len; 27429e54ba7cSSudarsana Reddy Kalluru } 27439e54ba7cSSudarsana Reddy Kalluru 27442d4c8495SSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_read(struct qed_dev *cdev, u8 **data, 27452d4c8495SSudarsana Reddy Kalluru u32 cmd, u32 entity_id) 27462d4c8495SSudarsana Reddy Kalluru { 27472d4c8495SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 27482d4c8495SSudarsana Reddy Kalluru struct qed_ptt *ptt; 27492d4c8495SSudarsana Reddy Kalluru u32 flags, len; 27502d4c8495SSudarsana Reddy Kalluru int rc = 0; 27512d4c8495SSudarsana Reddy Kalluru 27522d4c8495SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 27532d4c8495SSudarsana Reddy Kalluru if (!ptt) 27542d4c8495SSudarsana Reddy Kalluru return -EAGAIN; 27552d4c8495SSudarsana Reddy Kalluru 27562d4c8495SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 27572d4c8495SSudarsana Reddy Kalluru "Read config cmd = %d entity id %d\n", cmd, entity_id); 27582d4c8495SSudarsana Reddy Kalluru flags = entity_id ? QED_NVM_CFG_GET_PF_FLAGS : QED_NVM_CFG_GET_FLAGS; 27592d4c8495SSudarsana Reddy Kalluru rc = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, entity_id, flags, *data, &len); 27602d4c8495SSudarsana Reddy Kalluru if (rc) 27612d4c8495SSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d reading %d\n", rc, cmd); 27622d4c8495SSudarsana Reddy Kalluru 27632d4c8495SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 27642d4c8495SSudarsana Reddy Kalluru 27652d4c8495SSudarsana Reddy Kalluru return rc; 27662d4c8495SSudarsana Reddy Kalluru } 27672d4c8495SSudarsana Reddy Kalluru 27683a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash(struct qed_dev *cdev, const char *name) 27693a69cae8SSudarsana Reddy Kalluru { 27703a69cae8SSudarsana Reddy Kalluru const struct firmware *image; 27713a69cae8SSudarsana Reddy Kalluru const u8 *data, *data_end; 27723a69cae8SSudarsana Reddy Kalluru u32 cmd_type; 27733a69cae8SSudarsana Reddy Kalluru int rc; 27743a69cae8SSudarsana Reddy Kalluru 27753a69cae8SSudarsana Reddy Kalluru rc = request_firmware(&image, name, &cdev->pdev->dev); 27763a69cae8SSudarsana Reddy Kalluru if (rc) { 27773a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find '%s'\n", name); 27783a69cae8SSudarsana Reddy Kalluru return rc; 27793a69cae8SSudarsana Reddy Kalluru } 27803a69cae8SSudarsana Reddy Kalluru 27813a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV, 27823a69cae8SSudarsana Reddy Kalluru "Flashing '%s' - firmware's data at %p, size is %08x\n", 27833a69cae8SSudarsana Reddy Kalluru name, image->data, (u32)image->size); 27843a69cae8SSudarsana Reddy Kalluru data = image->data; 27853a69cae8SSudarsana Reddy Kalluru data_end = data + image->size; 27863a69cae8SSudarsana Reddy Kalluru 27873a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_validate(cdev, image, &data); 27883a69cae8SSudarsana Reddy Kalluru if (rc) 27893a69cae8SSudarsana Reddy Kalluru goto exit; 27903a69cae8SSudarsana Reddy Kalluru 27913a69cae8SSudarsana Reddy Kalluru while (data < data_end) { 27923a69cae8SSudarsana Reddy Kalluru bool check_resp = false; 27933a69cae8SSudarsana Reddy Kalluru 27943a69cae8SSudarsana Reddy Kalluru /* Parse the actual command */ 27953a69cae8SSudarsana Reddy Kalluru cmd_type = *((u32 *)data); 27963a69cae8SSudarsana Reddy Kalluru switch (cmd_type) { 27973a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_DATA: 27983a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_data(cdev, &data, 27993a69cae8SSudarsana Reddy Kalluru &check_resp); 28003a69cae8SSudarsana Reddy Kalluru break; 28013a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_START: 28023a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_start(cdev, &data, 28033a69cae8SSudarsana Reddy Kalluru &check_resp); 28043a69cae8SSudarsana Reddy Kalluru break; 28053a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CHANGE: 28063a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access(cdev, &data, 28073a69cae8SSudarsana Reddy Kalluru &check_resp); 28083a69cae8SSudarsana Reddy Kalluru break; 28090dabbe1bSSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CFG_ID: 28100dabbe1bSSudarsana Reddy Kalluru rc = qed_nvm_flash_cfg_write(cdev, &data); 28110dabbe1bSSudarsana Reddy Kalluru break; 28123a69cae8SSudarsana Reddy Kalluru default: 28133a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Unknown command %08x\n", cmd_type); 28143a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 28153a69cae8SSudarsana Reddy Kalluru goto exit; 28163a69cae8SSudarsana Reddy Kalluru } 28173a69cae8SSudarsana Reddy Kalluru 28183a69cae8SSudarsana Reddy Kalluru if (rc) { 28193a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Command %08x failed\n", cmd_type); 28203a69cae8SSudarsana Reddy Kalluru goto exit; 28213a69cae8SSudarsana Reddy Kalluru } 28223a69cae8SSudarsana Reddy Kalluru 28233a69cae8SSudarsana Reddy Kalluru /* Check response if needed */ 28243a69cae8SSudarsana Reddy Kalluru if (check_resp) { 28253a69cae8SSudarsana Reddy Kalluru u32 mcp_response = 0; 28263a69cae8SSudarsana Reddy Kalluru 28273a69cae8SSudarsana Reddy Kalluru if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) { 28283a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed getting MCP response\n"); 28293a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 28303a69cae8SSudarsana Reddy Kalluru goto exit; 28313a69cae8SSudarsana Reddy Kalluru } 28323a69cae8SSudarsana Reddy Kalluru 28333a69cae8SSudarsana Reddy Kalluru switch (mcp_response & FW_MSG_CODE_MASK) { 28343a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_OK: 28353a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_OK: 28363a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK: 28373a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_PHY_OK: 28383a69cae8SSudarsana Reddy Kalluru break; 28393a69cae8SSudarsana Reddy Kalluru default: 28403a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "MFW returns error: %08x\n", 28413a69cae8SSudarsana Reddy Kalluru mcp_response); 28423a69cae8SSudarsana Reddy Kalluru rc = -EINVAL; 28433a69cae8SSudarsana Reddy Kalluru goto exit; 28443a69cae8SSudarsana Reddy Kalluru } 28453a69cae8SSudarsana Reddy Kalluru } 28463a69cae8SSudarsana Reddy Kalluru } 28473a69cae8SSudarsana Reddy Kalluru 28483a69cae8SSudarsana Reddy Kalluru exit: 28493a69cae8SSudarsana Reddy Kalluru release_firmware(image); 28503a69cae8SSudarsana Reddy Kalluru 28513a69cae8SSudarsana Reddy Kalluru return rc; 28523a69cae8SSudarsana Reddy Kalluru } 28533a69cae8SSudarsana Reddy Kalluru 285420675b37SMintz, Yuval static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type, 285520675b37SMintz, Yuval u8 *buf, u16 len) 285620675b37SMintz, Yuval { 285720675b37SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 285820675b37SMintz, Yuval 2859b60bfdfeSDenis Bolotin return qed_mcp_get_nvm_image(hwfn, type, buf, len); 286020675b37SMintz, Yuval } 286120675b37SMintz, Yuval 286264515dc8STomer Tayar void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn) 286364515dc8STomer Tayar { 286464515dc8STomer Tayar struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common; 286564515dc8STomer Tayar void *cookie = p_hwfn->cdev->ops_cookie; 286664515dc8STomer Tayar 286764515dc8STomer Tayar if (ops && ops->schedule_recovery_handler) 286864515dc8STomer Tayar ops->schedule_recovery_handler(cookie); 286964515dc8STomer Tayar } 287064515dc8STomer Tayar 2871c6b7314dSAlexander Lobakin static const char * const qed_hw_err_type_descr[] = { 2872d639836aSIgor Russkikh [QED_HW_ERR_FAN_FAIL] = "Fan Failure", 2873d639836aSIgor Russkikh [QED_HW_ERR_MFW_RESP_FAIL] = "MFW Response Failure", 2874d639836aSIgor Russkikh [QED_HW_ERR_HW_ATTN] = "HW Attention", 2875d639836aSIgor Russkikh [QED_HW_ERR_DMAE_FAIL] = "DMAE Failure", 2876d639836aSIgor Russkikh [QED_HW_ERR_RAMROD_FAIL] = "Ramrod Failure", 2877d639836aSIgor Russkikh [QED_HW_ERR_FW_ASSERT] = "FW Assertion", 2878d639836aSIgor Russkikh [QED_HW_ERR_LAST] = "Unknown", 2879d639836aSIgor Russkikh }; 2880d639836aSIgor Russkikh 2881d639836aSIgor Russkikh void qed_hw_error_occurred(struct qed_hwfn *p_hwfn, 2882d639836aSIgor Russkikh enum qed_hw_err_type err_type) 2883d639836aSIgor Russkikh { 2884d639836aSIgor Russkikh struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common; 2885d639836aSIgor Russkikh void *cookie = p_hwfn->cdev->ops_cookie; 2886c6b7314dSAlexander Lobakin const char *err_str; 2887d639836aSIgor Russkikh 2888d639836aSIgor Russkikh if (err_type > QED_HW_ERR_LAST) 2889d639836aSIgor Russkikh err_type = QED_HW_ERR_LAST; 2890d639836aSIgor Russkikh err_str = qed_hw_err_type_descr[err_type]; 2891d639836aSIgor Russkikh 2892d639836aSIgor Russkikh DP_NOTICE(p_hwfn, "HW error occurred [%s]\n", err_str); 2893d639836aSIgor Russkikh 2894936c7ba4SIgor Russkikh /* Call the HW error handler of the protocol driver. 2895936c7ba4SIgor Russkikh * If it is not available - perform a minimal handling of preventing 2896936c7ba4SIgor Russkikh * HW attentions from being reasserted. 2897d639836aSIgor Russkikh */ 2898d639836aSIgor Russkikh if (ops && ops->schedule_hw_err_handler) 2899d639836aSIgor Russkikh ops->schedule_hw_err_handler(cookie, err_type); 2900936c7ba4SIgor Russkikh else 2901936c7ba4SIgor Russkikh qed_int_attn_clr_enable(p_hwfn->cdev, true); 2902d639836aSIgor Russkikh } 2903d639836aSIgor Russkikh 2904722003acSSudarsana Reddy Kalluru static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, 2905477f2d14SRahul Verma void *handle) 2906722003acSSudarsana Reddy Kalluru { 2907477f2d14SRahul Verma return qed_set_queue_coalesce(rx_coal, tx_coal, handle); 2908722003acSSudarsana Reddy Kalluru } 2909722003acSSudarsana Reddy Kalluru 291091420b83SSudarsana Kalluru static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) 291191420b83SSudarsana Kalluru { 291291420b83SSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 291391420b83SSudarsana Kalluru struct qed_ptt *ptt; 291491420b83SSudarsana Kalluru int status = 0; 291591420b83SSudarsana Kalluru 291691420b83SSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 291791420b83SSudarsana Kalluru if (!ptt) 291891420b83SSudarsana Kalluru return -EAGAIN; 291991420b83SSudarsana Kalluru 292091420b83SSudarsana Kalluru status = qed_mcp_set_led(hwfn, ptt, mode); 292191420b83SSudarsana Kalluru 292291420b83SSudarsana Kalluru qed_ptt_release(hwfn, ptt); 292391420b83SSudarsana Kalluru 292491420b83SSudarsana Kalluru return status; 292591420b83SSudarsana Kalluru } 292691420b83SSudarsana Kalluru 292764515dc8STomer Tayar static int qed_recovery_process(struct qed_dev *cdev) 292864515dc8STomer Tayar { 292964515dc8STomer Tayar struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 293064515dc8STomer Tayar struct qed_ptt *p_ptt; 293164515dc8STomer Tayar int rc = 0; 293264515dc8STomer Tayar 293364515dc8STomer Tayar p_ptt = qed_ptt_acquire(p_hwfn); 293464515dc8STomer Tayar if (!p_ptt) 293564515dc8STomer Tayar return -EAGAIN; 293664515dc8STomer Tayar 293764515dc8STomer Tayar rc = qed_start_recovery_process(p_hwfn, p_ptt); 293864515dc8STomer Tayar 293964515dc8STomer Tayar qed_ptt_release(p_hwfn, p_ptt); 294064515dc8STomer Tayar 294164515dc8STomer Tayar return rc; 294264515dc8STomer Tayar } 294364515dc8STomer Tayar 294414d39648SMintz, Yuval static int qed_update_wol(struct qed_dev *cdev, bool enabled) 294514d39648SMintz, Yuval { 294614d39648SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 294714d39648SMintz, Yuval struct qed_ptt *ptt; 294814d39648SMintz, Yuval int rc = 0; 294914d39648SMintz, Yuval 295014d39648SMintz, Yuval if (IS_VF(cdev)) 295114d39648SMintz, Yuval return 0; 295214d39648SMintz, Yuval 295314d39648SMintz, Yuval ptt = qed_ptt_acquire(hwfn); 295414d39648SMintz, Yuval if (!ptt) 295514d39648SMintz, Yuval return -EAGAIN; 295614d39648SMintz, Yuval 295714d39648SMintz, Yuval rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED 295814d39648SMintz, Yuval : QED_OV_WOL_DISABLED); 295914d39648SMintz, Yuval if (rc) 296014d39648SMintz, Yuval goto out; 296114d39648SMintz, Yuval rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 296214d39648SMintz, Yuval 296314d39648SMintz, Yuval out: 296414d39648SMintz, Yuval qed_ptt_release(hwfn, ptt); 296514d39648SMintz, Yuval return rc; 296614d39648SMintz, Yuval } 296714d39648SMintz, Yuval 29680fefbfbaSSudarsana Kalluru static int qed_update_drv_state(struct qed_dev *cdev, bool active) 29690fefbfbaSSudarsana Kalluru { 29700fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 29710fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 29720fefbfbaSSudarsana Kalluru int status = 0; 29730fefbfbaSSudarsana Kalluru 29740fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 29750fefbfbaSSudarsana Kalluru return 0; 29760fefbfbaSSudarsana Kalluru 29770fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 29780fefbfbaSSudarsana Kalluru if (!ptt) 29790fefbfbaSSudarsana Kalluru return -EAGAIN; 29800fefbfbaSSudarsana Kalluru 29810fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ? 29820fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_ACTIVE : 29830fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_DISABLED); 29840fefbfbaSSudarsana Kalluru 29850fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 29860fefbfbaSSudarsana Kalluru 29870fefbfbaSSudarsana Kalluru return status; 29880fefbfbaSSudarsana Kalluru } 29890fefbfbaSSudarsana Kalluru 29900fefbfbaSSudarsana Kalluru static int qed_update_mac(struct qed_dev *cdev, u8 *mac) 29910fefbfbaSSudarsana Kalluru { 29920fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 29930fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 29940fefbfbaSSudarsana Kalluru int status = 0; 29950fefbfbaSSudarsana Kalluru 29960fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 29970fefbfbaSSudarsana Kalluru return 0; 29980fefbfbaSSudarsana Kalluru 29990fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 30000fefbfbaSSudarsana Kalluru if (!ptt) 30010fefbfbaSSudarsana Kalluru return -EAGAIN; 30020fefbfbaSSudarsana Kalluru 30030fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mac(hwfn, ptt, mac); 30040fefbfbaSSudarsana Kalluru if (status) 30050fefbfbaSSudarsana Kalluru goto out; 30060fefbfbaSSudarsana Kalluru 30070fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 30080fefbfbaSSudarsana Kalluru 30090fefbfbaSSudarsana Kalluru out: 30100fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 30110fefbfbaSSudarsana Kalluru return status; 30120fefbfbaSSudarsana Kalluru } 30130fefbfbaSSudarsana Kalluru 30140fefbfbaSSudarsana Kalluru static int qed_update_mtu(struct qed_dev *cdev, u16 mtu) 30150fefbfbaSSudarsana Kalluru { 30160fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 30170fefbfbaSSudarsana Kalluru struct qed_ptt *ptt; 30180fefbfbaSSudarsana Kalluru int status = 0; 30190fefbfbaSSudarsana Kalluru 30200fefbfbaSSudarsana Kalluru if (IS_VF(cdev)) 30210fefbfbaSSudarsana Kalluru return 0; 30220fefbfbaSSudarsana Kalluru 30230fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn); 30240fefbfbaSSudarsana Kalluru if (!ptt) 30250fefbfbaSSudarsana Kalluru return -EAGAIN; 30260fefbfbaSSudarsana Kalluru 30270fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu); 30280fefbfbaSSudarsana Kalluru if (status) 30290fefbfbaSSudarsana Kalluru goto out; 30300fefbfbaSSudarsana Kalluru 30310fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV); 30320fefbfbaSSudarsana Kalluru 30330fefbfbaSSudarsana Kalluru out: 30340fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt); 30350fefbfbaSSudarsana Kalluru return status; 30360fefbfbaSSudarsana Kalluru } 30370fefbfbaSSudarsana Kalluru 3038b51dab46SSudarsana Reddy Kalluru static int qed_read_module_eeprom(struct qed_dev *cdev, char *buf, 3039b51dab46SSudarsana Reddy Kalluru u8 dev_addr, u32 offset, u32 len) 3040b51dab46SSudarsana Reddy Kalluru { 3041b51dab46SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 3042b51dab46SSudarsana Reddy Kalluru struct qed_ptt *ptt; 3043b51dab46SSudarsana Reddy Kalluru int rc = 0; 3044b51dab46SSudarsana Reddy Kalluru 3045b51dab46SSudarsana Reddy Kalluru if (IS_VF(cdev)) 3046b51dab46SSudarsana Reddy Kalluru return 0; 3047b51dab46SSudarsana Reddy Kalluru 3048b51dab46SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 3049b51dab46SSudarsana Reddy Kalluru if (!ptt) 3050b51dab46SSudarsana Reddy Kalluru return -EAGAIN; 3051b51dab46SSudarsana Reddy Kalluru 3052b51dab46SSudarsana Reddy Kalluru rc = qed_mcp_phy_sfp_read(hwfn, ptt, MFW_PORT(hwfn), dev_addr, 3053b51dab46SSudarsana Reddy Kalluru offset, len, buf); 3054b51dab46SSudarsana Reddy Kalluru 3055b51dab46SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 3056b51dab46SSudarsana Reddy Kalluru 3057b51dab46SSudarsana Reddy Kalluru return rc; 3058b51dab46SSudarsana Reddy Kalluru } 3059b51dab46SSudarsana Reddy Kalluru 30603b86bd07SSudarsana Reddy Kalluru static int qed_set_grc_config(struct qed_dev *cdev, u32 cfg_id, u32 val) 30613b86bd07SSudarsana Reddy Kalluru { 30623b86bd07SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); 30633b86bd07SSudarsana Reddy Kalluru struct qed_ptt *ptt; 30643b86bd07SSudarsana Reddy Kalluru int rc = 0; 30653b86bd07SSudarsana Reddy Kalluru 30663b86bd07SSudarsana Reddy Kalluru if (IS_VF(cdev)) 30673b86bd07SSudarsana Reddy Kalluru return 0; 30683b86bd07SSudarsana Reddy Kalluru 30693b86bd07SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn); 30703b86bd07SSudarsana Reddy Kalluru if (!ptt) 30713b86bd07SSudarsana Reddy Kalluru return -EAGAIN; 30723b86bd07SSudarsana Reddy Kalluru 30732d22bc83SMichal Kalderon rc = qed_dbg_grc_config(hwfn, cfg_id, val); 30743b86bd07SSudarsana Reddy Kalluru 30753b86bd07SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt); 30763b86bd07SSudarsana Reddy Kalluru 30773b86bd07SSudarsana Reddy Kalluru return rc; 30783b86bd07SSudarsana Reddy Kalluru } 30793b86bd07SSudarsana Reddy Kalluru 308008eb1fb0SMichal Kalderon static u8 qed_get_affin_hwfn_idx(struct qed_dev *cdev) 308108eb1fb0SMichal Kalderon { 308208eb1fb0SMichal Kalderon return QED_AFFIN_HWFN_IDX(cdev); 308308eb1fb0SMichal Kalderon } 308408eb1fb0SMichal Kalderon 30858c93beafSYuval Mintz static struct qed_selftest_ops qed_selftest_ops_pass = { 308603dc76caSSudarsana Reddy Kalluru .selftest_memory = &qed_selftest_memory, 308703dc76caSSudarsana Reddy Kalluru .selftest_interrupt = &qed_selftest_interrupt, 308803dc76caSSudarsana Reddy Kalluru .selftest_register = &qed_selftest_register, 308903dc76caSSudarsana Reddy Kalluru .selftest_clock = &qed_selftest_clock, 30907a4b21b7SMintz, Yuval .selftest_nvram = &qed_selftest_nvram, 309103dc76caSSudarsana Reddy Kalluru }; 309203dc76caSSudarsana Reddy Kalluru 3093fe56b9e6SYuval Mintz const struct qed_common_ops qed_common_ops_pass = { 309403dc76caSSudarsana Reddy Kalluru .selftest = &qed_selftest_ops_pass, 3095fe56b9e6SYuval Mintz .probe = &qed_probe, 3096fe56b9e6SYuval Mintz .remove = &qed_remove, 3097fe56b9e6SYuval Mintz .set_power_state = &qed_set_power_state, 3098712c3cbfSMintz, Yuval .set_name = &qed_set_name, 3099fe56b9e6SYuval Mintz .update_pf_params = &qed_update_pf_params, 3100fe56b9e6SYuval Mintz .slowpath_start = &qed_slowpath_start, 3101fe56b9e6SYuval Mintz .slowpath_stop = &qed_slowpath_stop, 3102fe56b9e6SYuval Mintz .set_fp_int = &qed_set_int_fp, 3103fe56b9e6SYuval Mintz .get_fp_int = &qed_get_int_fp, 3104fe56b9e6SYuval Mintz .sb_init = &qed_sb_init, 3105fe56b9e6SYuval Mintz .sb_release = &qed_sb_release, 3106fe56b9e6SYuval Mintz .simd_handler_config = &qed_simd_handler_config, 3107fe56b9e6SYuval Mintz .simd_handler_clean = &qed_simd_handler_clean, 31081e128c81SArun Easi .dbg_grc = &qed_dbg_grc, 31091e128c81SArun Easi .dbg_grc_size = &qed_dbg_grc_size, 3110fe7cd2bfSYuval Mintz .can_link_change = &qed_can_link_change, 3111cc875c2eSYuval Mintz .set_link = &qed_set_link, 3112cc875c2eSYuval Mintz .get_link = &qed_get_current_link, 3113fe56b9e6SYuval Mintz .drain = &qed_drain, 3114fe56b9e6SYuval Mintz .update_msglvl = &qed_init_dp, 3115e0971c83STomer Tayar .dbg_all_data = &qed_dbg_all_data, 3116e0971c83STomer Tayar .dbg_all_data_size = &qed_dbg_all_data_size, 3117fe56b9e6SYuval Mintz .chain_alloc = &qed_chain_alloc, 3118fe56b9e6SYuval Mintz .chain_free = &qed_chain_free, 31193a69cae8SSudarsana Reddy Kalluru .nvm_flash = &qed_nvm_flash, 312020675b37SMintz, Yuval .nvm_get_image = &qed_nvm_get_image, 3121722003acSSudarsana Reddy Kalluru .set_coalesce = &qed_set_coalesce, 312291420b83SSudarsana Kalluru .set_led = &qed_set_led, 312364515dc8STomer Tayar .recovery_process = &qed_recovery_process, 312464515dc8STomer Tayar .recovery_prolog = &qed_recovery_prolog, 3125936c7ba4SIgor Russkikh .attn_clr_enable = &qed_int_attn_clr_enable, 31260fefbfbaSSudarsana Kalluru .update_drv_state = &qed_update_drv_state, 31270fefbfbaSSudarsana Kalluru .update_mac = &qed_update_mac, 31280fefbfbaSSudarsana Kalluru .update_mtu = &qed_update_mtu, 312914d39648SMintz, Yuval .update_wol = &qed_update_wol, 31300e1f1044SAriel Elior .db_recovery_add = &qed_db_recovery_add, 31310e1f1044SAriel Elior .db_recovery_del = &qed_db_recovery_del, 3132b51dab46SSudarsana Reddy Kalluru .read_module_eeprom = &qed_read_module_eeprom, 313308eb1fb0SMichal Kalderon .get_affin_hwfn_idx = &qed_get_affin_hwfn_idx, 31342d4c8495SSudarsana Reddy Kalluru .read_nvm_cfg = &qed_nvm_flash_cfg_read, 31359e54ba7cSSudarsana Reddy Kalluru .read_nvm_cfg_len = &qed_nvm_flash_cfg_len, 31363b86bd07SSudarsana Reddy Kalluru .set_grc_config = &qed_set_grc_config, 3137fe56b9e6SYuval Mintz }; 31386c754246SSudarsana Reddy Kalluru 31396c754246SSudarsana Reddy Kalluru void qed_get_protocol_stats(struct qed_dev *cdev, 31406c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type type, 31416c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats *stats) 31426c754246SSudarsana Reddy Kalluru { 31436c754246SSudarsana Reddy Kalluru struct qed_eth_stats eth_stats; 31446c754246SSudarsana Reddy Kalluru 31456c754246SSudarsana Reddy Kalluru memset(stats, 0, sizeof(*stats)); 31466c754246SSudarsana Reddy Kalluru 31476c754246SSudarsana Reddy Kalluru switch (type) { 31486c754246SSudarsana Reddy Kalluru case QED_MCP_LAN_STATS: 31496c754246SSudarsana Reddy Kalluru qed_get_vport_stats(cdev, ð_stats); 31509c79ddaaSMintz, Yuval stats->lan_stats.ucast_rx_pkts = 31519c79ddaaSMintz, Yuval eth_stats.common.rx_ucast_pkts; 31529c79ddaaSMintz, Yuval stats->lan_stats.ucast_tx_pkts = 31539c79ddaaSMintz, Yuval eth_stats.common.tx_ucast_pkts; 31546c754246SSudarsana Reddy Kalluru stats->lan_stats.fcs_err = -1; 31556c754246SSudarsana Reddy Kalluru break; 31561e128c81SArun Easi case QED_MCP_FCOE_STATS: 31571e128c81SArun Easi qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats); 31581e128c81SArun Easi break; 31592f2b2614SMintz, Yuval case QED_MCP_ISCSI_STATS: 31602f2b2614SMintz, Yuval qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); 31612f2b2614SMintz, Yuval break; 31626c754246SSudarsana Reddy Kalluru default: 3163512c7840SMintz, Yuval DP_VERBOSE(cdev, QED_MSG_SP, 3164512c7840SMintz, Yuval "Invalid protocol type = %d\n", type); 31656c754246SSudarsana Reddy Kalluru return; 31666c754246SSudarsana Reddy Kalluru } 31676c754246SSudarsana Reddy Kalluru } 31682528c389SSudarsana Reddy Kalluru 316959ccf86fSSudarsana Reddy Kalluru int qed_mfw_tlv_req(struct qed_hwfn *hwfn) 317059ccf86fSSudarsana Reddy Kalluru { 317159ccf86fSSudarsana Reddy Kalluru DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV, 317259ccf86fSSudarsana Reddy Kalluru "Scheduling slowpath task [Flag: %d]\n", 317359ccf86fSSudarsana Reddy Kalluru QED_SLOWPATH_MFW_TLV_REQ); 317459ccf86fSSudarsana Reddy Kalluru smp_mb__before_atomic(); 317559ccf86fSSudarsana Reddy Kalluru set_bit(QED_SLOWPATH_MFW_TLV_REQ, &hwfn->slowpath_task_flags); 317659ccf86fSSudarsana Reddy Kalluru smp_mb__after_atomic(); 317759ccf86fSSudarsana Reddy Kalluru queue_delayed_work(hwfn->slowpath_wq, &hwfn->slowpath_task, 0); 317859ccf86fSSudarsana Reddy Kalluru 317959ccf86fSSudarsana Reddy Kalluru return 0; 318059ccf86fSSudarsana Reddy Kalluru } 318159ccf86fSSudarsana Reddy Kalluru 318259ccf86fSSudarsana Reddy Kalluru static void 318359ccf86fSSudarsana Reddy Kalluru qed_fill_generic_tlv_data(struct qed_dev *cdev, struct qed_mfw_tlv_generic *tlv) 318459ccf86fSSudarsana Reddy Kalluru { 318559ccf86fSSudarsana Reddy Kalluru struct qed_common_cb_ops *op = cdev->protocol_ops.common; 318659ccf86fSSudarsana Reddy Kalluru struct qed_eth_stats_common *p_common; 318759ccf86fSSudarsana Reddy Kalluru struct qed_generic_tlvs gen_tlvs; 318859ccf86fSSudarsana Reddy Kalluru struct qed_eth_stats stats; 318959ccf86fSSudarsana Reddy Kalluru int i; 319059ccf86fSSudarsana Reddy Kalluru 319159ccf86fSSudarsana Reddy Kalluru memset(&gen_tlvs, 0, sizeof(gen_tlvs)); 319259ccf86fSSudarsana Reddy Kalluru op->get_generic_tlv_data(cdev->ops_cookie, &gen_tlvs); 319359ccf86fSSudarsana Reddy Kalluru 319459ccf86fSSudarsana Reddy Kalluru if (gen_tlvs.feat_flags & QED_TLV_IP_CSUM) 319559ccf86fSSudarsana Reddy Kalluru tlv->flags.ipv4_csum_offload = true; 319659ccf86fSSudarsana Reddy Kalluru if (gen_tlvs.feat_flags & QED_TLV_LSO) 319759ccf86fSSudarsana Reddy Kalluru tlv->flags.lso_supported = true; 319859ccf86fSSudarsana Reddy Kalluru tlv->flags.b_set = true; 319959ccf86fSSudarsana Reddy Kalluru 320059ccf86fSSudarsana Reddy Kalluru for (i = 0; i < QED_TLV_MAC_COUNT; i++) { 320159ccf86fSSudarsana Reddy Kalluru if (is_valid_ether_addr(gen_tlvs.mac[i])) { 320259ccf86fSSudarsana Reddy Kalluru ether_addr_copy(tlv->mac[i], gen_tlvs.mac[i]); 320359ccf86fSSudarsana Reddy Kalluru tlv->mac_set[i] = true; 320459ccf86fSSudarsana Reddy Kalluru } 320559ccf86fSSudarsana Reddy Kalluru } 320659ccf86fSSudarsana Reddy Kalluru 320759ccf86fSSudarsana Reddy Kalluru qed_get_vport_stats(cdev, &stats); 320859ccf86fSSudarsana Reddy Kalluru p_common = &stats.common; 320959ccf86fSSudarsana Reddy Kalluru tlv->rx_frames = p_common->rx_ucast_pkts + p_common->rx_mcast_pkts + 321059ccf86fSSudarsana Reddy Kalluru p_common->rx_bcast_pkts; 321159ccf86fSSudarsana Reddy Kalluru tlv->rx_frames_set = true; 321259ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes = p_common->rx_ucast_bytes + p_common->rx_mcast_bytes + 321359ccf86fSSudarsana Reddy Kalluru p_common->rx_bcast_bytes; 321459ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes_set = true; 321559ccf86fSSudarsana Reddy Kalluru tlv->tx_frames = p_common->tx_ucast_pkts + p_common->tx_mcast_pkts + 321659ccf86fSSudarsana Reddy Kalluru p_common->tx_bcast_pkts; 321759ccf86fSSudarsana Reddy Kalluru tlv->tx_frames_set = true; 321859ccf86fSSudarsana Reddy Kalluru tlv->tx_bytes = p_common->tx_ucast_bytes + p_common->tx_mcast_bytes + 321959ccf86fSSudarsana Reddy Kalluru p_common->tx_bcast_bytes; 322059ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes_set = true; 322159ccf86fSSudarsana Reddy Kalluru } 322259ccf86fSSudarsana Reddy Kalluru 32232528c389SSudarsana Reddy Kalluru int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn, enum qed_mfw_tlv_type type, 32242528c389SSudarsana Reddy Kalluru union qed_mfw_tlv_data *tlv_buf) 32252528c389SSudarsana Reddy Kalluru { 322659ccf86fSSudarsana Reddy Kalluru struct qed_dev *cdev = hwfn->cdev; 322759ccf86fSSudarsana Reddy Kalluru struct qed_common_cb_ops *ops; 322859ccf86fSSudarsana Reddy Kalluru 322959ccf86fSSudarsana Reddy Kalluru ops = cdev->protocol_ops.common; 323059ccf86fSSudarsana Reddy Kalluru if (!ops || !ops->get_protocol_tlv_data || !ops->get_generic_tlv_data) { 323159ccf86fSSudarsana Reddy Kalluru DP_NOTICE(hwfn, "Can't collect TLV management info\n"); 32322528c389SSudarsana Reddy Kalluru return -EINVAL; 32332528c389SSudarsana Reddy Kalluru } 323459ccf86fSSudarsana Reddy Kalluru 323559ccf86fSSudarsana Reddy Kalluru switch (type) { 323659ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_GENERIC: 323759ccf86fSSudarsana Reddy Kalluru qed_fill_generic_tlv_data(hwfn->cdev, &tlv_buf->generic); 323859ccf86fSSudarsana Reddy Kalluru break; 323959ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_ETH: 324059ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->eth); 324159ccf86fSSudarsana Reddy Kalluru break; 324259ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_FCOE: 324359ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->fcoe); 324459ccf86fSSudarsana Reddy Kalluru break; 324559ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_ISCSI: 324659ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->iscsi); 324759ccf86fSSudarsana Reddy Kalluru break; 324859ccf86fSSudarsana Reddy Kalluru default: 324959ccf86fSSudarsana Reddy Kalluru break; 325059ccf86fSSudarsana Reddy Kalluru } 325159ccf86fSSudarsana Reddy Kalluru 325259ccf86fSSudarsana Reddy Kalluru return 0; 325359ccf86fSSudarsana Reddy Kalluru } 3254