162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2018, Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "ice_common.h" 562306a36Sopenharmony_ci#include "ice_sched.h" 662306a36Sopenharmony_ci#include "ice_adminq_cmd.h" 762306a36Sopenharmony_ci#include "ice_flow.h" 862306a36Sopenharmony_ci#include "ice_ptp_hw.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define ICE_PF_RESET_WAIT_COUNT 300 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistatic const char * const ice_link_mode_str_low[] = { 1362306a36Sopenharmony_ci [0] = "100BASE_TX", 1462306a36Sopenharmony_ci [1] = "100M_SGMII", 1562306a36Sopenharmony_ci [2] = "1000BASE_T", 1662306a36Sopenharmony_ci [3] = "1000BASE_SX", 1762306a36Sopenharmony_ci [4] = "1000BASE_LX", 1862306a36Sopenharmony_ci [5] = "1000BASE_KX", 1962306a36Sopenharmony_ci [6] = "1G_SGMII", 2062306a36Sopenharmony_ci [7] = "2500BASE_T", 2162306a36Sopenharmony_ci [8] = "2500BASE_X", 2262306a36Sopenharmony_ci [9] = "2500BASE_KX", 2362306a36Sopenharmony_ci [10] = "5GBASE_T", 2462306a36Sopenharmony_ci [11] = "5GBASE_KR", 2562306a36Sopenharmony_ci [12] = "10GBASE_T", 2662306a36Sopenharmony_ci [13] = "10G_SFI_DA", 2762306a36Sopenharmony_ci [14] = "10GBASE_SR", 2862306a36Sopenharmony_ci [15] = "10GBASE_LR", 2962306a36Sopenharmony_ci [16] = "10GBASE_KR_CR1", 3062306a36Sopenharmony_ci [17] = "10G_SFI_AOC_ACC", 3162306a36Sopenharmony_ci [18] = "10G_SFI_C2C", 3262306a36Sopenharmony_ci [19] = "25GBASE_T", 3362306a36Sopenharmony_ci [20] = "25GBASE_CR", 3462306a36Sopenharmony_ci [21] = "25GBASE_CR_S", 3562306a36Sopenharmony_ci [22] = "25GBASE_CR1", 3662306a36Sopenharmony_ci [23] = "25GBASE_SR", 3762306a36Sopenharmony_ci [24] = "25GBASE_LR", 3862306a36Sopenharmony_ci [25] = "25GBASE_KR", 3962306a36Sopenharmony_ci [26] = "25GBASE_KR_S", 4062306a36Sopenharmony_ci [27] = "25GBASE_KR1", 4162306a36Sopenharmony_ci [28] = "25G_AUI_AOC_ACC", 4262306a36Sopenharmony_ci [29] = "25G_AUI_C2C", 4362306a36Sopenharmony_ci [30] = "40GBASE_CR4", 4462306a36Sopenharmony_ci [31] = "40GBASE_SR4", 4562306a36Sopenharmony_ci [32] = "40GBASE_LR4", 4662306a36Sopenharmony_ci [33] = "40GBASE_KR4", 4762306a36Sopenharmony_ci [34] = "40G_XLAUI_AOC_ACC", 4862306a36Sopenharmony_ci [35] = "40G_XLAUI", 4962306a36Sopenharmony_ci [36] = "50GBASE_CR2", 5062306a36Sopenharmony_ci [37] = "50GBASE_SR2", 5162306a36Sopenharmony_ci [38] = "50GBASE_LR2", 5262306a36Sopenharmony_ci [39] = "50GBASE_KR2", 5362306a36Sopenharmony_ci [40] = "50G_LAUI2_AOC_ACC", 5462306a36Sopenharmony_ci [41] = "50G_LAUI2", 5562306a36Sopenharmony_ci [42] = "50G_AUI2_AOC_ACC", 5662306a36Sopenharmony_ci [43] = "50G_AUI2", 5762306a36Sopenharmony_ci [44] = "50GBASE_CP", 5862306a36Sopenharmony_ci [45] = "50GBASE_SR", 5962306a36Sopenharmony_ci [46] = "50GBASE_FR", 6062306a36Sopenharmony_ci [47] = "50GBASE_LR", 6162306a36Sopenharmony_ci [48] = "50GBASE_KR_PAM4", 6262306a36Sopenharmony_ci [49] = "50G_AUI1_AOC_ACC", 6362306a36Sopenharmony_ci [50] = "50G_AUI1", 6462306a36Sopenharmony_ci [51] = "100GBASE_CR4", 6562306a36Sopenharmony_ci [52] = "100GBASE_SR4", 6662306a36Sopenharmony_ci [53] = "100GBASE_LR4", 6762306a36Sopenharmony_ci [54] = "100GBASE_KR4", 6862306a36Sopenharmony_ci [55] = "100G_CAUI4_AOC_ACC", 6962306a36Sopenharmony_ci [56] = "100G_CAUI4", 7062306a36Sopenharmony_ci [57] = "100G_AUI4_AOC_ACC", 7162306a36Sopenharmony_ci [58] = "100G_AUI4", 7262306a36Sopenharmony_ci [59] = "100GBASE_CR_PAM4", 7362306a36Sopenharmony_ci [60] = "100GBASE_KR_PAM4", 7462306a36Sopenharmony_ci [61] = "100GBASE_CP2", 7562306a36Sopenharmony_ci [62] = "100GBASE_SR2", 7662306a36Sopenharmony_ci [63] = "100GBASE_DR", 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic const char * const ice_link_mode_str_high[] = { 8062306a36Sopenharmony_ci [0] = "100GBASE_KR2_PAM4", 8162306a36Sopenharmony_ci [1] = "100G_CAUI2_AOC_ACC", 8262306a36Sopenharmony_ci [2] = "100G_CAUI2", 8362306a36Sopenharmony_ci [3] = "100G_AUI2_AOC_ACC", 8462306a36Sopenharmony_ci [4] = "100G_AUI2", 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/** 8862306a36Sopenharmony_ci * ice_dump_phy_type - helper function to dump phy_type 8962306a36Sopenharmony_ci * @hw: pointer to the HW structure 9062306a36Sopenharmony_ci * @low: 64 bit value for phy_type_low 9162306a36Sopenharmony_ci * @high: 64 bit value for phy_type_high 9262306a36Sopenharmony_ci * @prefix: prefix string to differentiate multiple dumps 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_cistatic void 9562306a36Sopenharmony_ciice_dump_phy_type(struct ice_hw *hw, u64 low, u64 high, const char *prefix) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix, low); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci for (u32 i = 0; i < BITS_PER_TYPE(typeof(low)); i++) { 10062306a36Sopenharmony_ci if (low & BIT_ULL(i)) 10162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "%s: bit(%d): %s\n", 10262306a36Sopenharmony_ci prefix, i, ice_link_mode_str_low[i]); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix, high); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci for (u32 i = 0; i < BITS_PER_TYPE(typeof(high)); i++) { 10862306a36Sopenharmony_ci if (high & BIT_ULL(i)) 10962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "%s: bit(%d): %s\n", 11062306a36Sopenharmony_ci prefix, i, ice_link_mode_str_high[i]); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * ice_set_mac_type - Sets MAC type 11662306a36Sopenharmony_ci * @hw: pointer to the HW structure 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * This function sets the MAC type of the adapter based on the 11962306a36Sopenharmony_ci * vendor ID and device ID stored in the HW structure. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_cistatic int ice_set_mac_type(struct ice_hw *hw) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci if (hw->vendor_id != PCI_VENDOR_ID_INTEL) 12462306a36Sopenharmony_ci return -ENODEV; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci switch (hw->device_id) { 12762306a36Sopenharmony_ci case ICE_DEV_ID_E810C_BACKPLANE: 12862306a36Sopenharmony_ci case ICE_DEV_ID_E810C_QSFP: 12962306a36Sopenharmony_ci case ICE_DEV_ID_E810C_SFP: 13062306a36Sopenharmony_ci case ICE_DEV_ID_E810_XXV_BACKPLANE: 13162306a36Sopenharmony_ci case ICE_DEV_ID_E810_XXV_QSFP: 13262306a36Sopenharmony_ci case ICE_DEV_ID_E810_XXV_SFP: 13362306a36Sopenharmony_ci hw->mac_type = ICE_MAC_E810; 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci case ICE_DEV_ID_E823C_10G_BASE_T: 13662306a36Sopenharmony_ci case ICE_DEV_ID_E823C_BACKPLANE: 13762306a36Sopenharmony_ci case ICE_DEV_ID_E823C_QSFP: 13862306a36Sopenharmony_ci case ICE_DEV_ID_E823C_SFP: 13962306a36Sopenharmony_ci case ICE_DEV_ID_E823C_SGMII: 14062306a36Sopenharmony_ci case ICE_DEV_ID_E822C_10G_BASE_T: 14162306a36Sopenharmony_ci case ICE_DEV_ID_E822C_BACKPLANE: 14262306a36Sopenharmony_ci case ICE_DEV_ID_E822C_QSFP: 14362306a36Sopenharmony_ci case ICE_DEV_ID_E822C_SFP: 14462306a36Sopenharmony_ci case ICE_DEV_ID_E822C_SGMII: 14562306a36Sopenharmony_ci case ICE_DEV_ID_E822L_10G_BASE_T: 14662306a36Sopenharmony_ci case ICE_DEV_ID_E822L_BACKPLANE: 14762306a36Sopenharmony_ci case ICE_DEV_ID_E822L_SFP: 14862306a36Sopenharmony_ci case ICE_DEV_ID_E822L_SGMII: 14962306a36Sopenharmony_ci case ICE_DEV_ID_E823L_10G_BASE_T: 15062306a36Sopenharmony_ci case ICE_DEV_ID_E823L_1GBE: 15162306a36Sopenharmony_ci case ICE_DEV_ID_E823L_BACKPLANE: 15262306a36Sopenharmony_ci case ICE_DEV_ID_E823L_QSFP: 15362306a36Sopenharmony_ci case ICE_DEV_ID_E823L_SFP: 15462306a36Sopenharmony_ci hw->mac_type = ICE_MAC_GENERIC; 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci default: 15762306a36Sopenharmony_ci hw->mac_type = ICE_MAC_UNKNOWN; 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type); 16262306a36Sopenharmony_ci return 0; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/** 16662306a36Sopenharmony_ci * ice_is_e810 16762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * returns true if the device is E810 based, false if not. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cibool ice_is_e810(struct ice_hw *hw) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci return hw->mac_type == ICE_MAC_E810; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/** 17762306a36Sopenharmony_ci * ice_is_e810t 17862306a36Sopenharmony_ci * @hw: pointer to the hardware structure 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * returns true if the device is E810T based, false if not. 18162306a36Sopenharmony_ci */ 18262306a36Sopenharmony_cibool ice_is_e810t(struct ice_hw *hw) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci switch (hw->device_id) { 18562306a36Sopenharmony_ci case ICE_DEV_ID_E810C_SFP: 18662306a36Sopenharmony_ci switch (hw->subsystem_device_id) { 18762306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T: 18862306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T2: 18962306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T3: 19062306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T4: 19162306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T6: 19262306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T7: 19362306a36Sopenharmony_ci return true; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci break; 19662306a36Sopenharmony_ci case ICE_DEV_ID_E810C_QSFP: 19762306a36Sopenharmony_ci switch (hw->subsystem_device_id) { 19862306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T2: 19962306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T3: 20062306a36Sopenharmony_ci case ICE_SUBDEV_ID_E810T5: 20162306a36Sopenharmony_ci return true; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci break; 20462306a36Sopenharmony_ci default: 20562306a36Sopenharmony_ci break; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci return false; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/** 21262306a36Sopenharmony_ci * ice_is_e823 21362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 21462306a36Sopenharmony_ci * 21562306a36Sopenharmony_ci * returns true if the device is E823-L or E823-C based, false if not. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_cibool ice_is_e823(struct ice_hw *hw) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci switch (hw->device_id) { 22062306a36Sopenharmony_ci case ICE_DEV_ID_E823L_BACKPLANE: 22162306a36Sopenharmony_ci case ICE_DEV_ID_E823L_SFP: 22262306a36Sopenharmony_ci case ICE_DEV_ID_E823L_10G_BASE_T: 22362306a36Sopenharmony_ci case ICE_DEV_ID_E823L_1GBE: 22462306a36Sopenharmony_ci case ICE_DEV_ID_E823L_QSFP: 22562306a36Sopenharmony_ci case ICE_DEV_ID_E823C_BACKPLANE: 22662306a36Sopenharmony_ci case ICE_DEV_ID_E823C_QSFP: 22762306a36Sopenharmony_ci case ICE_DEV_ID_E823C_SFP: 22862306a36Sopenharmony_ci case ICE_DEV_ID_E823C_10G_BASE_T: 22962306a36Sopenharmony_ci case ICE_DEV_ID_E823C_SGMII: 23062306a36Sopenharmony_ci return true; 23162306a36Sopenharmony_ci default: 23262306a36Sopenharmony_ci return false; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci/** 23762306a36Sopenharmony_ci * ice_clear_pf_cfg - Clear PF configuration 23862306a36Sopenharmony_ci * @hw: pointer to the hardware structure 23962306a36Sopenharmony_ci * 24062306a36Sopenharmony_ci * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port 24162306a36Sopenharmony_ci * configuration, flow director filters, etc.). 24262306a36Sopenharmony_ci */ 24362306a36Sopenharmony_ciint ice_clear_pf_cfg(struct ice_hw *hw) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct ice_aq_desc desc; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/** 25362306a36Sopenharmony_ci * ice_aq_manage_mac_read - manage MAC address read command 25462306a36Sopenharmony_ci * @hw: pointer to the HW struct 25562306a36Sopenharmony_ci * @buf: a virtual buffer to hold the manage MAC read response 25662306a36Sopenharmony_ci * @buf_size: Size of the virtual buffer 25762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 25862306a36Sopenharmony_ci * 25962306a36Sopenharmony_ci * This function is used to return per PF station MAC address (0x0107). 26062306a36Sopenharmony_ci * NOTE: Upon successful completion of this command, MAC address information 26162306a36Sopenharmony_ci * is returned in user specified buffer. Please interpret user specified 26262306a36Sopenharmony_ci * buffer as "manage_mac_read" response. 26362306a36Sopenharmony_ci * Response such as various MAC addresses are stored in HW struct (port.mac) 26462306a36Sopenharmony_ci * ice_discover_dev_caps is expected to be called before this function is 26562306a36Sopenharmony_ci * called. 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_cistatic int 26862306a36Sopenharmony_ciice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size, 26962306a36Sopenharmony_ci struct ice_sq_cd *cd) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct ice_aqc_manage_mac_read_resp *resp; 27262306a36Sopenharmony_ci struct ice_aqc_manage_mac_read *cmd; 27362306a36Sopenharmony_ci struct ice_aq_desc desc; 27462306a36Sopenharmony_ci int status; 27562306a36Sopenharmony_ci u16 flags; 27662306a36Sopenharmony_ci u8 i; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci cmd = &desc.params.mac_read; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci if (buf_size < sizeof(*resp)) 28162306a36Sopenharmony_ci return -EINVAL; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 28662306a36Sopenharmony_ci if (status) 28762306a36Sopenharmony_ci return status; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci resp = buf; 29062306a36Sopenharmony_ci flags = le16_to_cpu(cmd->flags) & ICE_AQC_MAN_MAC_READ_M; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) { 29362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n"); 29462306a36Sopenharmony_ci return -EIO; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* A single port can report up to two (LAN and WoL) addresses */ 29862306a36Sopenharmony_ci for (i = 0; i < cmd->num_addr; i++) 29962306a36Sopenharmony_ci if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) { 30062306a36Sopenharmony_ci ether_addr_copy(hw->port_info->mac.lan_addr, 30162306a36Sopenharmony_ci resp[i].mac_addr); 30262306a36Sopenharmony_ci ether_addr_copy(hw->port_info->mac.perm_addr, 30362306a36Sopenharmony_ci resp[i].mac_addr); 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci/** 31162306a36Sopenharmony_ci * ice_aq_get_phy_caps - returns PHY capabilities 31262306a36Sopenharmony_ci * @pi: port information structure 31362306a36Sopenharmony_ci * @qual_mods: report qualified modules 31462306a36Sopenharmony_ci * @report_mode: report mode capabilities 31562306a36Sopenharmony_ci * @pcaps: structure for PHY capabilities to be filled 31662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 31762306a36Sopenharmony_ci * 31862306a36Sopenharmony_ci * Returns the various PHY capabilities supported on the Port (0x0600) 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ciint 32162306a36Sopenharmony_ciice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, 32262306a36Sopenharmony_ci struct ice_aqc_get_phy_caps_data *pcaps, 32362306a36Sopenharmony_ci struct ice_sq_cd *cd) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct ice_aqc_get_phy_caps *cmd; 32662306a36Sopenharmony_ci u16 pcaps_size = sizeof(*pcaps); 32762306a36Sopenharmony_ci struct ice_aq_desc desc; 32862306a36Sopenharmony_ci const char *prefix; 32962306a36Sopenharmony_ci struct ice_hw *hw; 33062306a36Sopenharmony_ci int status; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci cmd = &desc.params.get_phy; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi) 33562306a36Sopenharmony_ci return -EINVAL; 33662306a36Sopenharmony_ci hw = pi->hw; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci if (report_mode == ICE_AQC_REPORT_DFLT_CFG && 33962306a36Sopenharmony_ci !ice_fw_supports_report_dflt_cfg(hw)) 34062306a36Sopenharmony_ci return -EINVAL; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (qual_mods) 34562306a36Sopenharmony_ci cmd->param0 |= cpu_to_le16(ICE_AQC_GET_PHY_RQM); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci cmd->param0 |= cpu_to_le16(report_mode); 34862306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n"); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci switch (report_mode) { 35362306a36Sopenharmony_ci case ICE_AQC_REPORT_TOPO_CAP_MEDIA: 35462306a36Sopenharmony_ci prefix = "phy_caps_media"; 35562306a36Sopenharmony_ci break; 35662306a36Sopenharmony_ci case ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA: 35762306a36Sopenharmony_ci prefix = "phy_caps_no_media"; 35862306a36Sopenharmony_ci break; 35962306a36Sopenharmony_ci case ICE_AQC_REPORT_ACTIVE_CFG: 36062306a36Sopenharmony_ci prefix = "phy_caps_active"; 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci case ICE_AQC_REPORT_DFLT_CFG: 36362306a36Sopenharmony_ci prefix = "phy_caps_default"; 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci default: 36662306a36Sopenharmony_ci prefix = "phy_caps_invalid"; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ice_dump_phy_type(hw, le64_to_cpu(pcaps->phy_type_low), 37062306a36Sopenharmony_ci le64_to_cpu(pcaps->phy_type_high), prefix); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n", 37362306a36Sopenharmony_ci prefix, report_mode); 37462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps); 37562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix, 37662306a36Sopenharmony_ci pcaps->low_power_ctrl_an); 37762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix, 37862306a36Sopenharmony_ci pcaps->eee_cap); 37962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix, 38062306a36Sopenharmony_ci pcaps->eeer_value); 38162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix, 38262306a36Sopenharmony_ci pcaps->link_fec_options); 38362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n", 38462306a36Sopenharmony_ci prefix, pcaps->module_compliance_enforcement); 38562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n", 38662306a36Sopenharmony_ci prefix, pcaps->extended_compliance_code); 38762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix, 38862306a36Sopenharmony_ci pcaps->module_type[0]); 38962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix, 39062306a36Sopenharmony_ci pcaps->module_type[1]); 39162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix, 39262306a36Sopenharmony_ci pcaps->module_type[2]); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) { 39562306a36Sopenharmony_ci pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low); 39662306a36Sopenharmony_ci pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high); 39762306a36Sopenharmony_ci memcpy(pi->phy.link_info.module_type, &pcaps->module_type, 39862306a36Sopenharmony_ci sizeof(pi->phy.link_info.module_type)); 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return status; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci/** 40562306a36Sopenharmony_ci * ice_aq_get_link_topo_handle - get link topology node return status 40662306a36Sopenharmony_ci * @pi: port information structure 40762306a36Sopenharmony_ci * @node_type: requested node type 40862306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 40962306a36Sopenharmony_ci * 41062306a36Sopenharmony_ci * Get link topology node return status for specified node type (0x06E0) 41162306a36Sopenharmony_ci * 41262306a36Sopenharmony_ci * Node type cage can be used to determine if cage is present. If AQC 41362306a36Sopenharmony_ci * returns error (ENOENT), then no cage present. If no cage present, then 41462306a36Sopenharmony_ci * connection type is backplane or BASE-T. 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_cistatic int 41762306a36Sopenharmony_ciice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type, 41862306a36Sopenharmony_ci struct ice_sq_cd *cd) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct ice_aqc_get_link_topo *cmd; 42162306a36Sopenharmony_ci struct ice_aq_desc desc; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci cmd = &desc.params.get_link_topo; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci cmd->addr.topo_params.node_type_ctx = 42862306a36Sopenharmony_ci (ICE_AQC_LINK_TOPO_NODE_CTX_PORT << 42962306a36Sopenharmony_ci ICE_AQC_LINK_TOPO_NODE_CTX_S); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* set node type */ 43262306a36Sopenharmony_ci cmd->addr.topo_params.node_type_ctx |= 43362306a36Sopenharmony_ci (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci/** 43962306a36Sopenharmony_ci * ice_is_media_cage_present 44062306a36Sopenharmony_ci * @pi: port information structure 44162306a36Sopenharmony_ci * 44262306a36Sopenharmony_ci * Returns true if media cage is present, else false. If no cage, then 44362306a36Sopenharmony_ci * media type is backplane or BASE-T. 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_cistatic bool ice_is_media_cage_present(struct ice_port_info *pi) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci /* Node type cage can be used to determine if cage is present. If AQC 44862306a36Sopenharmony_ci * returns error (ENOENT), then no cage present. If no cage present then 44962306a36Sopenharmony_ci * connection type is backplane or BASE-T. 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_ci return !ice_aq_get_link_topo_handle(pi, 45262306a36Sopenharmony_ci ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE, 45362306a36Sopenharmony_ci NULL); 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci/** 45762306a36Sopenharmony_ci * ice_get_media_type - Gets media type 45862306a36Sopenharmony_ci * @pi: port information structure 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_cistatic enum ice_media_type ice_get_media_type(struct ice_port_info *pi) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci struct ice_link_status *hw_link_info; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci if (!pi) 46562306a36Sopenharmony_ci return ICE_MEDIA_UNKNOWN; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci hw_link_info = &pi->phy.link_info; 46862306a36Sopenharmony_ci if (hw_link_info->phy_type_low && hw_link_info->phy_type_high) 46962306a36Sopenharmony_ci /* If more than one media type is selected, report unknown */ 47062306a36Sopenharmony_ci return ICE_MEDIA_UNKNOWN; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (hw_link_info->phy_type_low) { 47362306a36Sopenharmony_ci /* 1G SGMII is a special case where some DA cable PHYs 47462306a36Sopenharmony_ci * may show this as an option when it really shouldn't 47562306a36Sopenharmony_ci * be since SGMII is meant to be between a MAC and a PHY 47662306a36Sopenharmony_ci * in a backplane. Try to detect this case and handle it 47762306a36Sopenharmony_ci */ 47862306a36Sopenharmony_ci if (hw_link_info->phy_type_low == ICE_PHY_TYPE_LOW_1G_SGMII && 47962306a36Sopenharmony_ci (hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] == 48062306a36Sopenharmony_ci ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE || 48162306a36Sopenharmony_ci hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] == 48262306a36Sopenharmony_ci ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE)) 48362306a36Sopenharmony_ci return ICE_MEDIA_DA; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci switch (hw_link_info->phy_type_low) { 48662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_SX: 48762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_LX: 48862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_SR: 48962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_LR: 49062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 49162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_SR: 49262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_LR: 49362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_SR4: 49462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_LR4: 49562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_SR2: 49662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_LR2: 49762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_SR: 49862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_FR: 49962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_LR: 50062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_SR4: 50162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_LR4: 50262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_SR2: 50362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_DR: 50462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC: 50562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC: 50662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC: 50762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: 50862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: 50962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: 51062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: 51162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: 51262306a36Sopenharmony_ci return ICE_MEDIA_FIBER; 51362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100BASE_TX: 51462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_T: 51562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_2500BASE_T: 51662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_5GBASE_T: 51762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_T: 51862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_T: 51962306a36Sopenharmony_ci return ICE_MEDIA_BASET; 52062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10G_SFI_DA: 52162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_CR: 52262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 52362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_CR1: 52462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_CR4: 52562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_CR2: 52662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_CP: 52762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_CR4: 52862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 52962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_CP2: 53062306a36Sopenharmony_ci return ICE_MEDIA_DA; 53162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 53262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40G_XLAUI: 53362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_LAUI2: 53462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI2: 53562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI1: 53662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_AUI4: 53762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_CAUI4: 53862306a36Sopenharmony_ci if (ice_is_media_cage_present(pi)) 53962306a36Sopenharmony_ci return ICE_MEDIA_DA; 54062306a36Sopenharmony_ci fallthrough; 54162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_KX: 54262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_2500BASE_KX: 54362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_2500BASE_X: 54462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_5GBASE_KR: 54562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 54662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_KR: 54762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_KR1: 54862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 54962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_KR4: 55062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 55162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_KR2: 55262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_KR4: 55362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 55462306a36Sopenharmony_ci return ICE_MEDIA_BACKPLANE; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci } else { 55762306a36Sopenharmony_ci switch (hw_link_info->phy_type_high) { 55862306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_AUI2: 55962306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_CAUI2: 56062306a36Sopenharmony_ci if (ice_is_media_cage_present(pi)) 56162306a36Sopenharmony_ci return ICE_MEDIA_DA; 56262306a36Sopenharmony_ci fallthrough; 56362306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 56462306a36Sopenharmony_ci return ICE_MEDIA_BACKPLANE; 56562306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: 56662306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: 56762306a36Sopenharmony_ci return ICE_MEDIA_FIBER; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci return ICE_MEDIA_UNKNOWN; 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci/** 57462306a36Sopenharmony_ci * ice_aq_get_link_info 57562306a36Sopenharmony_ci * @pi: port information structure 57662306a36Sopenharmony_ci * @ena_lse: enable/disable LinkStatusEvent reporting 57762306a36Sopenharmony_ci * @link: pointer to link status structure - optional 57862306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 57962306a36Sopenharmony_ci * 58062306a36Sopenharmony_ci * Get Link Status (0x607). Returns the link status of the adapter. 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ciint 58362306a36Sopenharmony_ciice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, 58462306a36Sopenharmony_ci struct ice_link_status *link, struct ice_sq_cd *cd) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci struct ice_aqc_get_link_status_data link_data = { 0 }; 58762306a36Sopenharmony_ci struct ice_aqc_get_link_status *resp; 58862306a36Sopenharmony_ci struct ice_link_status *li_old, *li; 58962306a36Sopenharmony_ci enum ice_media_type *hw_media_type; 59062306a36Sopenharmony_ci struct ice_fc_info *hw_fc_info; 59162306a36Sopenharmony_ci bool tx_pause, rx_pause; 59262306a36Sopenharmony_ci struct ice_aq_desc desc; 59362306a36Sopenharmony_ci struct ice_hw *hw; 59462306a36Sopenharmony_ci u16 cmd_flags; 59562306a36Sopenharmony_ci int status; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci if (!pi) 59862306a36Sopenharmony_ci return -EINVAL; 59962306a36Sopenharmony_ci hw = pi->hw; 60062306a36Sopenharmony_ci li_old = &pi->phy.link_info_old; 60162306a36Sopenharmony_ci hw_media_type = &pi->phy.media_type; 60262306a36Sopenharmony_ci li = &pi->phy.link_info; 60362306a36Sopenharmony_ci hw_fc_info = &pi->fc; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status); 60662306a36Sopenharmony_ci cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS; 60762306a36Sopenharmony_ci resp = &desc.params.get_link_status; 60862306a36Sopenharmony_ci resp->cmd_flags = cpu_to_le16(cmd_flags); 60962306a36Sopenharmony_ci resp->lport_num = pi->lport; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci if (status) 61462306a36Sopenharmony_ci return status; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* save off old link status information */ 61762306a36Sopenharmony_ci *li_old = *li; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* update current link status information */ 62062306a36Sopenharmony_ci li->link_speed = le16_to_cpu(link_data.link_speed); 62162306a36Sopenharmony_ci li->phy_type_low = le64_to_cpu(link_data.phy_type_low); 62262306a36Sopenharmony_ci li->phy_type_high = le64_to_cpu(link_data.phy_type_high); 62362306a36Sopenharmony_ci *hw_media_type = ice_get_media_type(pi); 62462306a36Sopenharmony_ci li->link_info = link_data.link_info; 62562306a36Sopenharmony_ci li->link_cfg_err = link_data.link_cfg_err; 62662306a36Sopenharmony_ci li->an_info = link_data.an_info; 62762306a36Sopenharmony_ci li->ext_info = link_data.ext_info; 62862306a36Sopenharmony_ci li->max_frame_size = le16_to_cpu(link_data.max_frame_size); 62962306a36Sopenharmony_ci li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK; 63062306a36Sopenharmony_ci li->topo_media_conflict = link_data.topo_media_conflict; 63162306a36Sopenharmony_ci li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M | 63262306a36Sopenharmony_ci ICE_AQ_CFG_PACING_TYPE_M); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* update fc info */ 63562306a36Sopenharmony_ci tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX); 63662306a36Sopenharmony_ci rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX); 63762306a36Sopenharmony_ci if (tx_pause && rx_pause) 63862306a36Sopenharmony_ci hw_fc_info->current_mode = ICE_FC_FULL; 63962306a36Sopenharmony_ci else if (tx_pause) 64062306a36Sopenharmony_ci hw_fc_info->current_mode = ICE_FC_TX_PAUSE; 64162306a36Sopenharmony_ci else if (rx_pause) 64262306a36Sopenharmony_ci hw_fc_info->current_mode = ICE_FC_RX_PAUSE; 64362306a36Sopenharmony_ci else 64462306a36Sopenharmony_ci hw_fc_info->current_mode = ICE_FC_NONE; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci li->lse_ena = !!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED)); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "get link info\n"); 64962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " link_speed = 0x%x\n", li->link_speed); 65062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " phy_type_low = 0x%llx\n", 65162306a36Sopenharmony_ci (unsigned long long)li->phy_type_low); 65262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " phy_type_high = 0x%llx\n", 65362306a36Sopenharmony_ci (unsigned long long)li->phy_type_high); 65462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " media_type = 0x%x\n", *hw_media_type); 65562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " link_info = 0x%x\n", li->link_info); 65662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " link_cfg_err = 0x%x\n", li->link_cfg_err); 65762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " an_info = 0x%x\n", li->an_info); 65862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " ext_info = 0x%x\n", li->ext_info); 65962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " fec_info = 0x%x\n", li->fec_info); 66062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " lse_ena = 0x%x\n", li->lse_ena); 66162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " max_frame = 0x%x\n", 66262306a36Sopenharmony_ci li->max_frame_size); 66362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " pacing = 0x%x\n", li->pacing); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci /* save link status information */ 66662306a36Sopenharmony_ci if (link) 66762306a36Sopenharmony_ci *link = *li; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* flag cleared so calling functions don't call AQ again */ 67062306a36Sopenharmony_ci pi->phy.get_link_info = false; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return 0; 67362306a36Sopenharmony_ci} 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci/** 67662306a36Sopenharmony_ci * ice_fill_tx_timer_and_fc_thresh 67762306a36Sopenharmony_ci * @hw: pointer to the HW struct 67862306a36Sopenharmony_ci * @cmd: pointer to MAC cfg structure 67962306a36Sopenharmony_ci * 68062306a36Sopenharmony_ci * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command 68162306a36Sopenharmony_ci * descriptor 68262306a36Sopenharmony_ci */ 68362306a36Sopenharmony_cistatic void 68462306a36Sopenharmony_ciice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw, 68562306a36Sopenharmony_ci struct ice_aqc_set_mac_cfg *cmd) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci u16 fc_thres_val, tx_timer_val; 68862306a36Sopenharmony_ci u32 val; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* We read back the transmit timer and FC threshold value of 69162306a36Sopenharmony_ci * LFC. Thus, we will use index = 69262306a36Sopenharmony_ci * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX. 69362306a36Sopenharmony_ci * 69462306a36Sopenharmony_ci * Also, because we are operating on transmit timer and FC 69562306a36Sopenharmony_ci * threshold of LFC, we don't turn on any bit in tx_tmr_priority 69662306a36Sopenharmony_ci */ 69762306a36Sopenharmony_ci#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* Retrieve the transmit timer */ 70062306a36Sopenharmony_ci val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC)); 70162306a36Sopenharmony_ci tx_timer_val = val & 70262306a36Sopenharmony_ci PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M; 70362306a36Sopenharmony_ci cmd->tx_tmr_value = cpu_to_le16(tx_timer_val); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* Retrieve the FC threshold */ 70662306a36Sopenharmony_ci val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC)); 70762306a36Sopenharmony_ci fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci cmd->fc_refresh_threshold = cpu_to_le16(fc_thres_val); 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci/** 71362306a36Sopenharmony_ci * ice_aq_set_mac_cfg 71462306a36Sopenharmony_ci * @hw: pointer to the HW struct 71562306a36Sopenharmony_ci * @max_frame_size: Maximum Frame Size to be supported 71662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 71762306a36Sopenharmony_ci * 71862306a36Sopenharmony_ci * Set MAC configuration (0x0603) 71962306a36Sopenharmony_ci */ 72062306a36Sopenharmony_ciint 72162306a36Sopenharmony_ciice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci struct ice_aqc_set_mac_cfg *cmd; 72462306a36Sopenharmony_ci struct ice_aq_desc desc; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci cmd = &desc.params.set_mac_cfg; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (max_frame_size == 0) 72962306a36Sopenharmony_ci return -EINVAL; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci cmd->max_frame_size = cpu_to_le16(max_frame_size); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci ice_fill_tx_timer_and_fc_thresh(hw, cmd); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci/** 74162306a36Sopenharmony_ci * ice_init_fltr_mgmt_struct - initializes filter management list and locks 74262306a36Sopenharmony_ci * @hw: pointer to the HW struct 74362306a36Sopenharmony_ci */ 74462306a36Sopenharmony_cistatic int ice_init_fltr_mgmt_struct(struct ice_hw *hw) 74562306a36Sopenharmony_ci{ 74662306a36Sopenharmony_ci struct ice_switch_info *sw; 74762306a36Sopenharmony_ci int status; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw), 75062306a36Sopenharmony_ci sizeof(*hw->switch_info), GFP_KERNEL); 75162306a36Sopenharmony_ci sw = hw->switch_info; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci if (!sw) 75462306a36Sopenharmony_ci return -ENOMEM; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci INIT_LIST_HEAD(&sw->vsi_list_map_head); 75762306a36Sopenharmony_ci sw->prof_res_bm_init = 0; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci status = ice_init_def_sw_recp(hw); 76062306a36Sopenharmony_ci if (status) { 76162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), hw->switch_info); 76262306a36Sopenharmony_ci return status; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci return 0; 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci/** 76862306a36Sopenharmony_ci * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks 76962306a36Sopenharmony_ci * @hw: pointer to the HW struct 77062306a36Sopenharmony_ci */ 77162306a36Sopenharmony_cistatic void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 77462306a36Sopenharmony_ci struct ice_vsi_list_map_info *v_pos_map; 77562306a36Sopenharmony_ci struct ice_vsi_list_map_info *v_tmp_map; 77662306a36Sopenharmony_ci struct ice_sw_recipe *recps; 77762306a36Sopenharmony_ci u8 i; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head, 78062306a36Sopenharmony_ci list_entry) { 78162306a36Sopenharmony_ci list_del(&v_pos_map->list_entry); 78262306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), v_pos_map); 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci recps = sw->recp_list; 78562306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 78662306a36Sopenharmony_ci struct ice_recp_grp_entry *rg_entry, *tmprg_entry; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci recps[i].root_rid = i; 78962306a36Sopenharmony_ci list_for_each_entry_safe(rg_entry, tmprg_entry, 79062306a36Sopenharmony_ci &recps[i].rg_list, l_entry) { 79162306a36Sopenharmony_ci list_del(&rg_entry->l_entry); 79262306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), rg_entry); 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci if (recps[i].adv_rule) { 79662306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *tmp_entry; 79762306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *lst_itr; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci mutex_destroy(&recps[i].filt_rule_lock); 80062306a36Sopenharmony_ci list_for_each_entry_safe(lst_itr, tmp_entry, 80162306a36Sopenharmony_ci &recps[i].filt_rules, 80262306a36Sopenharmony_ci list_entry) { 80362306a36Sopenharmony_ci list_del(&lst_itr->list_entry); 80462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups); 80562306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), lst_itr); 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci } else { 80862306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci mutex_destroy(&recps[i].filt_rule_lock); 81162306a36Sopenharmony_ci list_for_each_entry_safe(lst_itr, tmp_entry, 81262306a36Sopenharmony_ci &recps[i].filt_rules, 81362306a36Sopenharmony_ci list_entry) { 81462306a36Sopenharmony_ci list_del(&lst_itr->list_entry); 81562306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), lst_itr); 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf); 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci ice_rm_all_sw_replay_rule_info(hw); 82162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), sw->recp_list); 82262306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), sw); 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci/** 82662306a36Sopenharmony_ci * ice_get_fw_log_cfg - get FW logging configuration 82762306a36Sopenharmony_ci * @hw: pointer to the HW struct 82862306a36Sopenharmony_ci */ 82962306a36Sopenharmony_cistatic int ice_get_fw_log_cfg(struct ice_hw *hw) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci struct ice_aq_desc desc; 83262306a36Sopenharmony_ci __le16 *config; 83362306a36Sopenharmony_ci int status; 83462306a36Sopenharmony_ci u16 size; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX; 83762306a36Sopenharmony_ci config = kzalloc(size, GFP_KERNEL); 83862306a36Sopenharmony_ci if (!config) 83962306a36Sopenharmony_ci return -ENOMEM; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info); 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, config, size, NULL); 84462306a36Sopenharmony_ci if (!status) { 84562306a36Sopenharmony_ci u16 i; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci /* Save FW logging information into the HW structure */ 84862306a36Sopenharmony_ci for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { 84962306a36Sopenharmony_ci u16 v, m, flgs; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci v = le16_to_cpu(config[i]); 85262306a36Sopenharmony_ci m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; 85362306a36Sopenharmony_ci flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci if (m < ICE_AQC_FW_LOG_ID_MAX) 85662306a36Sopenharmony_ci hw->fw_log.evnts[m].cur = flgs; 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci kfree(config); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci return status; 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci/** 86662306a36Sopenharmony_ci * ice_cfg_fw_log - configure FW logging 86762306a36Sopenharmony_ci * @hw: pointer to the HW struct 86862306a36Sopenharmony_ci * @enable: enable certain FW logging events if true, disable all if false 86962306a36Sopenharmony_ci * 87062306a36Sopenharmony_ci * This function enables/disables the FW logging via Rx CQ events and a UART 87162306a36Sopenharmony_ci * port based on predetermined configurations. FW logging via the Rx CQ can be 87262306a36Sopenharmony_ci * enabled/disabled for individual PF's. However, FW logging via the UART can 87362306a36Sopenharmony_ci * only be enabled/disabled for all PFs on the same device. 87462306a36Sopenharmony_ci * 87562306a36Sopenharmony_ci * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in 87662306a36Sopenharmony_ci * hw->fw_log need to be set accordingly, e.g. based on user-provided input, 87762306a36Sopenharmony_ci * before initializing the device. 87862306a36Sopenharmony_ci * 87962306a36Sopenharmony_ci * When re/configuring FW logging, callers need to update the "cfg" elements of 88062306a36Sopenharmony_ci * the hw->fw_log.evnts array with the desired logging event configurations for 88162306a36Sopenharmony_ci * modules of interest. When disabling FW logging completely, the callers can 88262306a36Sopenharmony_ci * just pass false in the "enable" parameter. On completion, the function will 88362306a36Sopenharmony_ci * update the "cur" element of the hw->fw_log.evnts array with the resulting 88462306a36Sopenharmony_ci * logging event configurations of the modules that are being re/configured. FW 88562306a36Sopenharmony_ci * logging modules that are not part of a reconfiguration operation retain their 88662306a36Sopenharmony_ci * previous states. 88762306a36Sopenharmony_ci * 88862306a36Sopenharmony_ci * Before resetting the device, it is recommended that the driver disables FW 88962306a36Sopenharmony_ci * logging before shutting down the control queue. When disabling FW logging 89062306a36Sopenharmony_ci * ("enable" = false), the latest configurations of FW logging events stored in 89162306a36Sopenharmony_ci * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after 89262306a36Sopenharmony_ci * a device reset. 89362306a36Sopenharmony_ci * 89462306a36Sopenharmony_ci * When enabling FW logging to emit log messages via the Rx CQ during the 89562306a36Sopenharmony_ci * device's initialization phase, a mechanism alternative to interrupt handlers 89662306a36Sopenharmony_ci * needs to be used to extract FW log messages from the Rx CQ periodically and 89762306a36Sopenharmony_ci * to prevent the Rx CQ from being full and stalling other types of control 89862306a36Sopenharmony_ci * messages from FW to SW. Interrupts are typically disabled during the device's 89962306a36Sopenharmony_ci * initialization phase. 90062306a36Sopenharmony_ci */ 90162306a36Sopenharmony_cistatic int ice_cfg_fw_log(struct ice_hw *hw, bool enable) 90262306a36Sopenharmony_ci{ 90362306a36Sopenharmony_ci struct ice_aqc_fw_logging *cmd; 90462306a36Sopenharmony_ci u16 i, chgs = 0, len = 0; 90562306a36Sopenharmony_ci struct ice_aq_desc desc; 90662306a36Sopenharmony_ci __le16 *data = NULL; 90762306a36Sopenharmony_ci u8 actv_evnts = 0; 90862306a36Sopenharmony_ci void *buf = NULL; 90962306a36Sopenharmony_ci int status = 0; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if (!hw->fw_log.cq_en && !hw->fw_log.uart_en) 91262306a36Sopenharmony_ci return 0; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci /* Disable FW logging only when the control queue is still responsive */ 91562306a36Sopenharmony_ci if (!enable && 91662306a36Sopenharmony_ci (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq))) 91762306a36Sopenharmony_ci return 0; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci /* Get current FW log settings */ 92062306a36Sopenharmony_ci status = ice_get_fw_log_cfg(hw); 92162306a36Sopenharmony_ci if (status) 92262306a36Sopenharmony_ci return status; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging); 92562306a36Sopenharmony_ci cmd = &desc.params.fw_logging; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci /* Indicate which controls are valid */ 92862306a36Sopenharmony_ci if (hw->fw_log.cq_en) 92962306a36Sopenharmony_ci cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci if (hw->fw_log.uart_en) 93262306a36Sopenharmony_ci cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci if (enable) { 93562306a36Sopenharmony_ci /* Fill in an array of entries with FW logging modules and 93662306a36Sopenharmony_ci * logging events being reconfigured. 93762306a36Sopenharmony_ci */ 93862306a36Sopenharmony_ci for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) { 93962306a36Sopenharmony_ci u16 val; 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci /* Keep track of enabled event types */ 94262306a36Sopenharmony_ci actv_evnts |= hw->fw_log.evnts[i].cfg; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur) 94562306a36Sopenharmony_ci continue; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci if (!data) { 94862306a36Sopenharmony_ci data = devm_kcalloc(ice_hw_to_dev(hw), 94962306a36Sopenharmony_ci ICE_AQC_FW_LOG_ID_MAX, 95062306a36Sopenharmony_ci sizeof(*data), 95162306a36Sopenharmony_ci GFP_KERNEL); 95262306a36Sopenharmony_ci if (!data) 95362306a36Sopenharmony_ci return -ENOMEM; 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci val = i << ICE_AQC_FW_LOG_ID_S; 95762306a36Sopenharmony_ci val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S; 95862306a36Sopenharmony_ci data[chgs++] = cpu_to_le16(val); 95962306a36Sopenharmony_ci } 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* Only enable FW logging if at least one module is specified. 96262306a36Sopenharmony_ci * If FW logging is currently enabled but all modules are not 96362306a36Sopenharmony_ci * enabled to emit log messages, disable FW logging altogether. 96462306a36Sopenharmony_ci */ 96562306a36Sopenharmony_ci if (actv_evnts) { 96662306a36Sopenharmony_ci /* Leave if there is effectively no change */ 96762306a36Sopenharmony_ci if (!chgs) 96862306a36Sopenharmony_ci goto out; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci if (hw->fw_log.cq_en) 97162306a36Sopenharmony_ci cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci if (hw->fw_log.uart_en) 97462306a36Sopenharmony_ci cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci buf = data; 97762306a36Sopenharmony_ci len = sizeof(*data) * chgs; 97862306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 97962306a36Sopenharmony_ci } 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, buf, len, NULL); 98362306a36Sopenharmony_ci if (!status) { 98462306a36Sopenharmony_ci /* Update the current configuration to reflect events enabled. 98562306a36Sopenharmony_ci * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW 98662306a36Sopenharmony_ci * logging mode is enabled for the device. They do not reflect 98762306a36Sopenharmony_ci * actual modules being enabled to emit log messages. So, their 98862306a36Sopenharmony_ci * values remain unchanged even when all modules are disabled. 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_ci u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci hw->fw_log.actv_evnts = actv_evnts; 99362306a36Sopenharmony_ci for (i = 0; i < cnt; i++) { 99462306a36Sopenharmony_ci u16 v, m; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (!enable) { 99762306a36Sopenharmony_ci /* When disabling all FW logging events as part 99862306a36Sopenharmony_ci * of device's de-initialization, the original 99962306a36Sopenharmony_ci * configurations are retained, and can be used 100062306a36Sopenharmony_ci * to reconfigure FW logging later if the device 100162306a36Sopenharmony_ci * is re-initialized. 100262306a36Sopenharmony_ci */ 100362306a36Sopenharmony_ci hw->fw_log.evnts[i].cur = 0; 100462306a36Sopenharmony_ci continue; 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci v = le16_to_cpu(data[i]); 100862306a36Sopenharmony_ci m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S; 100962306a36Sopenharmony_ci hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg; 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci } 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ciout: 101462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), data); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci return status; 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci/** 102062306a36Sopenharmony_ci * ice_output_fw_log 102162306a36Sopenharmony_ci * @hw: pointer to the HW struct 102262306a36Sopenharmony_ci * @desc: pointer to the AQ message descriptor 102362306a36Sopenharmony_ci * @buf: pointer to the buffer accompanying the AQ message 102462306a36Sopenharmony_ci * 102562306a36Sopenharmony_ci * Formats a FW Log message and outputs it via the standard driver logs. 102662306a36Sopenharmony_ci */ 102762306a36Sopenharmony_civoid ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf) 102862306a36Sopenharmony_ci{ 102962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg Start ]\n"); 103062306a36Sopenharmony_ci ice_debug_array(hw, ICE_DBG_FW_LOG, 16, 1, (u8 *)buf, 103162306a36Sopenharmony_ci le16_to_cpu(desc->datalen)); 103262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg End ]\n"); 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci/** 103662306a36Sopenharmony_ci * ice_get_itr_intrl_gran 103762306a36Sopenharmony_ci * @hw: pointer to the HW struct 103862306a36Sopenharmony_ci * 103962306a36Sopenharmony_ci * Determines the ITR/INTRL granularities based on the maximum aggregate 104062306a36Sopenharmony_ci * bandwidth according to the device's configuration during power-on. 104162306a36Sopenharmony_ci */ 104262306a36Sopenharmony_cistatic void ice_get_itr_intrl_gran(struct ice_hw *hw) 104362306a36Sopenharmony_ci{ 104462306a36Sopenharmony_ci u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) & 104562306a36Sopenharmony_ci GL_PWR_MODE_CTL_CAR_MAX_BW_M) >> 104662306a36Sopenharmony_ci GL_PWR_MODE_CTL_CAR_MAX_BW_S; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci switch (max_agg_bw) { 104962306a36Sopenharmony_ci case ICE_MAX_AGG_BW_200G: 105062306a36Sopenharmony_ci case ICE_MAX_AGG_BW_100G: 105162306a36Sopenharmony_ci case ICE_MAX_AGG_BW_50G: 105262306a36Sopenharmony_ci hw->itr_gran = ICE_ITR_GRAN_ABOVE_25; 105362306a36Sopenharmony_ci hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25; 105462306a36Sopenharmony_ci break; 105562306a36Sopenharmony_ci case ICE_MAX_AGG_BW_25G: 105662306a36Sopenharmony_ci hw->itr_gran = ICE_ITR_GRAN_MAX_25; 105762306a36Sopenharmony_ci hw->intrl_gran = ICE_INTRL_GRAN_MAX_25; 105862306a36Sopenharmony_ci break; 105962306a36Sopenharmony_ci } 106062306a36Sopenharmony_ci} 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci/** 106362306a36Sopenharmony_ci * ice_init_hw - main hardware initialization routine 106462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 106562306a36Sopenharmony_ci */ 106662306a36Sopenharmony_ciint ice_init_hw(struct ice_hw *hw) 106762306a36Sopenharmony_ci{ 106862306a36Sopenharmony_ci struct ice_aqc_get_phy_caps_data *pcaps; 106962306a36Sopenharmony_ci u16 mac_buf_len; 107062306a36Sopenharmony_ci void *mac_buf; 107162306a36Sopenharmony_ci int status; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci /* Set MAC type based on DeviceID */ 107462306a36Sopenharmony_ci status = ice_set_mac_type(hw); 107562306a36Sopenharmony_ci if (status) 107662306a36Sopenharmony_ci return status; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) & 107962306a36Sopenharmony_ci PF_FUNC_RID_FUNC_NUM_M) >> 108062306a36Sopenharmony_ci PF_FUNC_RID_FUNC_NUM_S; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci status = ice_reset(hw, ICE_RESET_PFR); 108362306a36Sopenharmony_ci if (status) 108462306a36Sopenharmony_ci return status; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci ice_get_itr_intrl_gran(hw); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci status = ice_create_all_ctrlq(hw); 108962306a36Sopenharmony_ci if (status) 109062306a36Sopenharmony_ci goto err_unroll_cqinit; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci /* Enable FW logging. Not fatal if this fails. */ 109362306a36Sopenharmony_ci status = ice_cfg_fw_log(hw, true); 109462306a36Sopenharmony_ci if (status) 109562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n"); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci status = ice_clear_pf_cfg(hw); 109862306a36Sopenharmony_ci if (status) 109962306a36Sopenharmony_ci goto err_unroll_cqinit; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* Set bit to enable Flow Director filters */ 110262306a36Sopenharmony_ci wr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M); 110362306a36Sopenharmony_ci INIT_LIST_HEAD(&hw->fdir_list_head); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci ice_clear_pxe_mode(hw); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci status = ice_init_nvm(hw); 110862306a36Sopenharmony_ci if (status) 110962306a36Sopenharmony_ci goto err_unroll_cqinit; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci status = ice_get_caps(hw); 111262306a36Sopenharmony_ci if (status) 111362306a36Sopenharmony_ci goto err_unroll_cqinit; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci if (!hw->port_info) 111662306a36Sopenharmony_ci hw->port_info = devm_kzalloc(ice_hw_to_dev(hw), 111762306a36Sopenharmony_ci sizeof(*hw->port_info), 111862306a36Sopenharmony_ci GFP_KERNEL); 111962306a36Sopenharmony_ci if (!hw->port_info) { 112062306a36Sopenharmony_ci status = -ENOMEM; 112162306a36Sopenharmony_ci goto err_unroll_cqinit; 112262306a36Sopenharmony_ci } 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci /* set the back pointer to HW */ 112562306a36Sopenharmony_ci hw->port_info->hw = hw; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci /* Initialize port_info struct with switch configuration data */ 112862306a36Sopenharmony_ci status = ice_get_initial_sw_cfg(hw); 112962306a36Sopenharmony_ci if (status) 113062306a36Sopenharmony_ci goto err_unroll_alloc; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci hw->evb_veb = true; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci /* init xarray for identifying scheduling nodes uniquely */ 113562306a36Sopenharmony_ci xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci /* Query the allocated resources for Tx scheduler */ 113862306a36Sopenharmony_ci status = ice_sched_query_res_alloc(hw); 113962306a36Sopenharmony_ci if (status) { 114062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n"); 114162306a36Sopenharmony_ci goto err_unroll_alloc; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci ice_sched_get_psm_clk_freq(hw); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* Initialize port_info struct with scheduler data */ 114662306a36Sopenharmony_ci status = ice_sched_init_port(hw->port_info); 114762306a36Sopenharmony_ci if (status) 114862306a36Sopenharmony_ci goto err_unroll_sched; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL); 115162306a36Sopenharmony_ci if (!pcaps) { 115262306a36Sopenharmony_ci status = -ENOMEM; 115362306a36Sopenharmony_ci goto err_unroll_sched; 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci /* Initialize port_info struct with PHY capabilities */ 115762306a36Sopenharmony_ci status = ice_aq_get_phy_caps(hw->port_info, false, 115862306a36Sopenharmony_ci ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, 115962306a36Sopenharmony_ci NULL); 116062306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), pcaps); 116162306a36Sopenharmony_ci if (status) 116262306a36Sopenharmony_ci dev_warn(ice_hw_to_dev(hw), "Get PHY capabilities failed status = %d, continuing anyway\n", 116362306a36Sopenharmony_ci status); 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci /* Initialize port_info struct with link information */ 116662306a36Sopenharmony_ci status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL); 116762306a36Sopenharmony_ci if (status) 116862306a36Sopenharmony_ci goto err_unroll_sched; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci /* need a valid SW entry point to build a Tx tree */ 117162306a36Sopenharmony_ci if (!hw->sw_entry_point_layer) { 117262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n"); 117362306a36Sopenharmony_ci status = -EIO; 117462306a36Sopenharmony_ci goto err_unroll_sched; 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci INIT_LIST_HEAD(&hw->agg_list); 117762306a36Sopenharmony_ci /* Initialize max burst size */ 117862306a36Sopenharmony_ci if (!hw->max_burst_size) 117962306a36Sopenharmony_ci ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci status = ice_init_fltr_mgmt_struct(hw); 118262306a36Sopenharmony_ci if (status) 118362306a36Sopenharmony_ci goto err_unroll_sched; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci /* Get MAC information */ 118662306a36Sopenharmony_ci /* A single port can report up to two (LAN and WoL) addresses */ 118762306a36Sopenharmony_ci mac_buf = devm_kcalloc(ice_hw_to_dev(hw), 2, 118862306a36Sopenharmony_ci sizeof(struct ice_aqc_manage_mac_read_resp), 118962306a36Sopenharmony_ci GFP_KERNEL); 119062306a36Sopenharmony_ci mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp); 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci if (!mac_buf) { 119362306a36Sopenharmony_ci status = -ENOMEM; 119462306a36Sopenharmony_ci goto err_unroll_fltr_mgmt_struct; 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL); 119862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), mac_buf); 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci if (status) 120162306a36Sopenharmony_ci goto err_unroll_fltr_mgmt_struct; 120262306a36Sopenharmony_ci /* enable jumbo frame support at MAC level */ 120362306a36Sopenharmony_ci status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL); 120462306a36Sopenharmony_ci if (status) 120562306a36Sopenharmony_ci goto err_unroll_fltr_mgmt_struct; 120662306a36Sopenharmony_ci /* Obtain counter base index which would be used by flow director */ 120762306a36Sopenharmony_ci status = ice_alloc_fd_res_cntr(hw, &hw->fd_ctr_base); 120862306a36Sopenharmony_ci if (status) 120962306a36Sopenharmony_ci goto err_unroll_fltr_mgmt_struct; 121062306a36Sopenharmony_ci status = ice_init_hw_tbls(hw); 121162306a36Sopenharmony_ci if (status) 121262306a36Sopenharmony_ci goto err_unroll_fltr_mgmt_struct; 121362306a36Sopenharmony_ci mutex_init(&hw->tnl_lock); 121462306a36Sopenharmony_ci return 0; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_cierr_unroll_fltr_mgmt_struct: 121762306a36Sopenharmony_ci ice_cleanup_fltr_mgmt_struct(hw); 121862306a36Sopenharmony_cierr_unroll_sched: 121962306a36Sopenharmony_ci ice_sched_cleanup_all(hw); 122062306a36Sopenharmony_cierr_unroll_alloc: 122162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), hw->port_info); 122262306a36Sopenharmony_cierr_unroll_cqinit: 122362306a36Sopenharmony_ci ice_destroy_all_ctrlq(hw); 122462306a36Sopenharmony_ci return status; 122562306a36Sopenharmony_ci} 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci/** 122862306a36Sopenharmony_ci * ice_deinit_hw - unroll initialization operations done by ice_init_hw 122962306a36Sopenharmony_ci * @hw: pointer to the hardware structure 123062306a36Sopenharmony_ci * 123162306a36Sopenharmony_ci * This should be called only during nominal operation, not as a result of 123262306a36Sopenharmony_ci * ice_init_hw() failing since ice_init_hw() will take care of unrolling 123362306a36Sopenharmony_ci * applicable initializations if it fails for any reason. 123462306a36Sopenharmony_ci */ 123562306a36Sopenharmony_civoid ice_deinit_hw(struct ice_hw *hw) 123662306a36Sopenharmony_ci{ 123762306a36Sopenharmony_ci ice_free_fd_res_cntr(hw, hw->fd_ctr_base); 123862306a36Sopenharmony_ci ice_cleanup_fltr_mgmt_struct(hw); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci ice_sched_cleanup_all(hw); 124162306a36Sopenharmony_ci ice_sched_clear_agg(hw); 124262306a36Sopenharmony_ci ice_free_seg(hw); 124362306a36Sopenharmony_ci ice_free_hw_tbls(hw); 124462306a36Sopenharmony_ci mutex_destroy(&hw->tnl_lock); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci /* Attempt to disable FW logging before shutting down control queues */ 124762306a36Sopenharmony_ci ice_cfg_fw_log(hw, false); 124862306a36Sopenharmony_ci ice_destroy_all_ctrlq(hw); 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci /* Clear VSI contexts if not already cleared */ 125162306a36Sopenharmony_ci ice_clear_all_vsi_ctx(hw); 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci/** 125562306a36Sopenharmony_ci * ice_check_reset - Check to see if a global reset is complete 125662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 125762306a36Sopenharmony_ci */ 125862306a36Sopenharmony_ciint ice_check_reset(struct ice_hw *hw) 125962306a36Sopenharmony_ci{ 126062306a36Sopenharmony_ci u32 cnt, reg = 0, grst_timeout, uld_mask; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci /* Poll for Device Active state in case a recent CORER, GLOBR, 126362306a36Sopenharmony_ci * or EMPR has occurred. The grst delay value is in 100ms units. 126462306a36Sopenharmony_ci * Add 1sec for outstanding AQ commands that can take a long time. 126562306a36Sopenharmony_ci */ 126662306a36Sopenharmony_ci grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >> 126762306a36Sopenharmony_ci GLGEN_RSTCTL_GRSTDEL_S) + 10; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci for (cnt = 0; cnt < grst_timeout; cnt++) { 127062306a36Sopenharmony_ci mdelay(100); 127162306a36Sopenharmony_ci reg = rd32(hw, GLGEN_RSTAT); 127262306a36Sopenharmony_ci if (!(reg & GLGEN_RSTAT_DEVSTATE_M)) 127362306a36Sopenharmony_ci break; 127462306a36Sopenharmony_ci } 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci if (cnt == grst_timeout) { 127762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n"); 127862306a36Sopenharmony_ci return -EIO; 127962306a36Sopenharmony_ci } 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci#define ICE_RESET_DONE_MASK (GLNVM_ULD_PCIER_DONE_M |\ 128262306a36Sopenharmony_ci GLNVM_ULD_PCIER_DONE_1_M |\ 128362306a36Sopenharmony_ci GLNVM_ULD_CORER_DONE_M |\ 128462306a36Sopenharmony_ci GLNVM_ULD_GLOBR_DONE_M |\ 128562306a36Sopenharmony_ci GLNVM_ULD_POR_DONE_M |\ 128662306a36Sopenharmony_ci GLNVM_ULD_POR_DONE_1_M |\ 128762306a36Sopenharmony_ci GLNVM_ULD_PCIER_DONE_2_M) 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci uld_mask = ICE_RESET_DONE_MASK | (hw->func_caps.common_cap.rdma ? 129062306a36Sopenharmony_ci GLNVM_ULD_PE_DONE_M : 0); 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci /* Device is Active; check Global Reset processes are done */ 129362306a36Sopenharmony_ci for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 129462306a36Sopenharmony_ci reg = rd32(hw, GLNVM_ULD) & uld_mask; 129562306a36Sopenharmony_ci if (reg == uld_mask) { 129662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt); 129762306a36Sopenharmony_ci break; 129862306a36Sopenharmony_ci } 129962306a36Sopenharmony_ci mdelay(10); 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci if (cnt == ICE_PF_RESET_WAIT_COUNT) { 130362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n", 130462306a36Sopenharmony_ci reg); 130562306a36Sopenharmony_ci return -EIO; 130662306a36Sopenharmony_ci } 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci} 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci/** 131262306a36Sopenharmony_ci * ice_pf_reset - Reset the PF 131362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 131462306a36Sopenharmony_ci * 131562306a36Sopenharmony_ci * If a global reset has been triggered, this function checks 131662306a36Sopenharmony_ci * for its completion and then issues the PF reset 131762306a36Sopenharmony_ci */ 131862306a36Sopenharmony_cistatic int ice_pf_reset(struct ice_hw *hw) 131962306a36Sopenharmony_ci{ 132062306a36Sopenharmony_ci u32 cnt, reg; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci /* If at function entry a global reset was already in progress, i.e. 132362306a36Sopenharmony_ci * state is not 'device active' or any of the reset done bits are not 132462306a36Sopenharmony_ci * set in GLNVM_ULD, there is no need for a PF Reset; poll until the 132562306a36Sopenharmony_ci * global reset is done. 132662306a36Sopenharmony_ci */ 132762306a36Sopenharmony_ci if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) || 132862306a36Sopenharmony_ci (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) { 132962306a36Sopenharmony_ci /* poll on global reset currently in progress until done */ 133062306a36Sopenharmony_ci if (ice_check_reset(hw)) 133162306a36Sopenharmony_ci return -EIO; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci return 0; 133462306a36Sopenharmony_ci } 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci /* Reset the PF */ 133762306a36Sopenharmony_ci reg = rd32(hw, PFGEN_CTRL); 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M)); 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci /* Wait for the PFR to complete. The wait time is the global config lock 134262306a36Sopenharmony_ci * timeout plus the PFR timeout which will account for a possible reset 134362306a36Sopenharmony_ci * that is occurring during a download package operation. 134462306a36Sopenharmony_ci */ 134562306a36Sopenharmony_ci for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT + 134662306a36Sopenharmony_ci ICE_PF_RESET_WAIT_COUNT; cnt++) { 134762306a36Sopenharmony_ci reg = rd32(hw, PFGEN_CTRL); 134862306a36Sopenharmony_ci if (!(reg & PFGEN_CTRL_PFSWR_M)) 134962306a36Sopenharmony_ci break; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci mdelay(1); 135262306a36Sopenharmony_ci } 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci if (cnt == ICE_PF_RESET_WAIT_COUNT) { 135562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n"); 135662306a36Sopenharmony_ci return -EIO; 135762306a36Sopenharmony_ci } 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci return 0; 136062306a36Sopenharmony_ci} 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci/** 136362306a36Sopenharmony_ci * ice_reset - Perform different types of reset 136462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 136562306a36Sopenharmony_ci * @req: reset request 136662306a36Sopenharmony_ci * 136762306a36Sopenharmony_ci * This function triggers a reset as specified by the req parameter. 136862306a36Sopenharmony_ci * 136962306a36Sopenharmony_ci * Note: 137062306a36Sopenharmony_ci * If anything other than a PF reset is triggered, PXE mode is restored. 137162306a36Sopenharmony_ci * This has to be cleared using ice_clear_pxe_mode again, once the AQ 137262306a36Sopenharmony_ci * interface has been restored in the rebuild flow. 137362306a36Sopenharmony_ci */ 137462306a36Sopenharmony_ciint ice_reset(struct ice_hw *hw, enum ice_reset_req req) 137562306a36Sopenharmony_ci{ 137662306a36Sopenharmony_ci u32 val = 0; 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci switch (req) { 137962306a36Sopenharmony_ci case ICE_RESET_PFR: 138062306a36Sopenharmony_ci return ice_pf_reset(hw); 138162306a36Sopenharmony_ci case ICE_RESET_CORER: 138262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n"); 138362306a36Sopenharmony_ci val = GLGEN_RTRIG_CORER_M; 138462306a36Sopenharmony_ci break; 138562306a36Sopenharmony_ci case ICE_RESET_GLOBR: 138662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n"); 138762306a36Sopenharmony_ci val = GLGEN_RTRIG_GLOBR_M; 138862306a36Sopenharmony_ci break; 138962306a36Sopenharmony_ci default: 139062306a36Sopenharmony_ci return -EINVAL; 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci val |= rd32(hw, GLGEN_RTRIG); 139462306a36Sopenharmony_ci wr32(hw, GLGEN_RTRIG, val); 139562306a36Sopenharmony_ci ice_flush(hw); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci /* wait for the FW to be ready */ 139862306a36Sopenharmony_ci return ice_check_reset(hw); 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci/** 140262306a36Sopenharmony_ci * ice_copy_rxq_ctx_to_hw 140362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 140462306a36Sopenharmony_ci * @ice_rxq_ctx: pointer to the rxq context 140562306a36Sopenharmony_ci * @rxq_index: the index of the Rx queue 140662306a36Sopenharmony_ci * 140762306a36Sopenharmony_ci * Copies rxq context from dense structure to HW register space 140862306a36Sopenharmony_ci */ 140962306a36Sopenharmony_cistatic int 141062306a36Sopenharmony_ciice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index) 141162306a36Sopenharmony_ci{ 141262306a36Sopenharmony_ci u8 i; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci if (!ice_rxq_ctx) 141562306a36Sopenharmony_ci return -EINVAL; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci if (rxq_index > QRX_CTRL_MAX_INDEX) 141862306a36Sopenharmony_ci return -EINVAL; 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci /* Copy each dword separately to HW */ 142162306a36Sopenharmony_ci for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) { 142262306a36Sopenharmony_ci wr32(hw, QRX_CONTEXT(i, rxq_index), 142362306a36Sopenharmony_ci *((u32 *)(ice_rxq_ctx + (i * sizeof(u32))))); 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, 142662306a36Sopenharmony_ci *((u32 *)(ice_rxq_ctx + (i * sizeof(u32))))); 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci return 0; 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci/* LAN Rx Queue Context */ 143362306a36Sopenharmony_cistatic const struct ice_ctx_ele ice_rlan_ctx_info[] = { 143462306a36Sopenharmony_ci /* Field Width LSB */ 143562306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, head, 13, 0), 143662306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, cpuid, 8, 13), 143762306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, base, 57, 32), 143862306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, qlen, 13, 89), 143962306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, dbuf, 7, 102), 144062306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, hbuf, 5, 109), 144162306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, dtype, 2, 114), 144262306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, dsize, 1, 116), 144362306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, crcstrip, 1, 117), 144462306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, l2tsel, 1, 119), 144562306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, hsplit_0, 4, 120), 144662306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, hsplit_1, 2, 124), 144762306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, showiv, 1, 127), 144862306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, rxmax, 14, 174), 144962306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena, 1, 193), 145062306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena, 1, 194), 145162306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena, 1, 195), 145262306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena, 1, 196), 145362306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh, 3, 198), 145462306a36Sopenharmony_ci ICE_CTX_STORE(ice_rlan_ctx, prefena, 1, 201), 145562306a36Sopenharmony_ci { 0 } 145662306a36Sopenharmony_ci}; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci/** 145962306a36Sopenharmony_ci * ice_write_rxq_ctx 146062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 146162306a36Sopenharmony_ci * @rlan_ctx: pointer to the rxq context 146262306a36Sopenharmony_ci * @rxq_index: the index of the Rx queue 146362306a36Sopenharmony_ci * 146462306a36Sopenharmony_ci * Converts rxq context from sparse to dense structure and then writes 146562306a36Sopenharmony_ci * it to HW register space and enables the hardware to prefetch descriptors 146662306a36Sopenharmony_ci * instead of only fetching them on demand 146762306a36Sopenharmony_ci */ 146862306a36Sopenharmony_ciint 146962306a36Sopenharmony_ciice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, 147062306a36Sopenharmony_ci u32 rxq_index) 147162306a36Sopenharmony_ci{ 147262306a36Sopenharmony_ci u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 }; 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci if (!rlan_ctx) 147562306a36Sopenharmony_ci return -EINVAL; 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci rlan_ctx->prefena = 1; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info); 148062306a36Sopenharmony_ci return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index); 148162306a36Sopenharmony_ci} 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci/* LAN Tx Queue Context */ 148462306a36Sopenharmony_ciconst struct ice_ctx_ele ice_tlan_ctx_info[] = { 148562306a36Sopenharmony_ci /* Field Width LSB */ 148662306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, base, 57, 0), 148762306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, port_num, 3, 57), 148862306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, cgd_num, 5, 60), 148962306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, pf_num, 3, 65), 149062306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, vmvf_num, 10, 68), 149162306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, vmvf_type, 2, 78), 149262306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, src_vsi, 10, 80), 149362306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena, 1, 90), 149462306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag, 1, 91), 149562306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, alt_vlan, 1, 92), 149662306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, cpuid, 8, 93), 149762306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, wb_mode, 1, 101), 149862306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc, 1, 102), 149962306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, tphrd, 1, 103), 150062306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc, 1, 104), 150162306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, cmpq_id, 9, 105), 150262306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func, 14, 114), 150362306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode, 1, 128), 150462306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id, 6, 129), 150562306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, qlen, 13, 135), 150662306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx, 4, 148), 150762306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, tso_ena, 1, 152), 150862306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, tso_qnum, 11, 153), 150962306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, legacy_int, 1, 164), 151062306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, drop_ena, 1, 165), 151162306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx, 2, 166), 151262306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx, 3, 168), 151362306a36Sopenharmony_ci ICE_CTX_STORE(ice_tlan_ctx, int_q_state, 122, 171), 151462306a36Sopenharmony_ci { 0 } 151562306a36Sopenharmony_ci}; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci/* Sideband Queue command wrappers */ 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci/** 152062306a36Sopenharmony_ci * ice_sbq_send_cmd - send Sideband Queue command to Sideband Queue 152162306a36Sopenharmony_ci * @hw: pointer to the HW struct 152262306a36Sopenharmony_ci * @desc: descriptor describing the command 152362306a36Sopenharmony_ci * @buf: buffer to use for indirect commands (NULL for direct commands) 152462306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands (0 for direct commands) 152562306a36Sopenharmony_ci * @cd: pointer to command details structure 152662306a36Sopenharmony_ci */ 152762306a36Sopenharmony_cistatic int 152862306a36Sopenharmony_ciice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc, 152962306a36Sopenharmony_ci void *buf, u16 buf_size, struct ice_sq_cd *cd) 153062306a36Sopenharmony_ci{ 153162306a36Sopenharmony_ci return ice_sq_send_cmd(hw, ice_get_sbq(hw), 153262306a36Sopenharmony_ci (struct ice_aq_desc *)desc, buf, buf_size, cd); 153362306a36Sopenharmony_ci} 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci/** 153662306a36Sopenharmony_ci * ice_sbq_rw_reg - Fill Sideband Queue command 153762306a36Sopenharmony_ci * @hw: pointer to the HW struct 153862306a36Sopenharmony_ci * @in: message info to be filled in descriptor 153962306a36Sopenharmony_ci */ 154062306a36Sopenharmony_ciint ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci struct ice_sbq_cmd_desc desc = {0}; 154362306a36Sopenharmony_ci struct ice_sbq_msg_req msg = {0}; 154462306a36Sopenharmony_ci u16 msg_len; 154562306a36Sopenharmony_ci int status; 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci msg_len = sizeof(msg); 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci msg.dest_dev = in->dest_dev; 155062306a36Sopenharmony_ci msg.opcode = in->opcode; 155162306a36Sopenharmony_ci msg.flags = ICE_SBQ_MSG_FLAGS; 155262306a36Sopenharmony_ci msg.sbe_fbe = ICE_SBQ_MSG_SBE_FBE; 155362306a36Sopenharmony_ci msg.msg_addr_low = cpu_to_le16(in->msg_addr_low); 155462306a36Sopenharmony_ci msg.msg_addr_high = cpu_to_le32(in->msg_addr_high); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci if (in->opcode) 155762306a36Sopenharmony_ci msg.data = cpu_to_le32(in->data); 155862306a36Sopenharmony_ci else 155962306a36Sopenharmony_ci /* data read comes back in completion, so shorten the struct by 156062306a36Sopenharmony_ci * sizeof(msg.data) 156162306a36Sopenharmony_ci */ 156262306a36Sopenharmony_ci msg_len -= sizeof(msg.data); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD); 156562306a36Sopenharmony_ci desc.opcode = cpu_to_le16(ice_sbq_opc_neigh_dev_req); 156662306a36Sopenharmony_ci desc.param0.cmd_len = cpu_to_le16(msg_len); 156762306a36Sopenharmony_ci status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL); 156862306a36Sopenharmony_ci if (!status && !in->opcode) 156962306a36Sopenharmony_ci in->data = le32_to_cpu 157062306a36Sopenharmony_ci (((struct ice_sbq_msg_cmpl *)&msg)->data); 157162306a36Sopenharmony_ci return status; 157262306a36Sopenharmony_ci} 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci/* FW Admin Queue command wrappers */ 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci/* Software lock/mutex that is meant to be held while the Global Config Lock 157762306a36Sopenharmony_ci * in firmware is acquired by the software to prevent most (but not all) types 157862306a36Sopenharmony_ci * of AQ commands from being sent to FW 157962306a36Sopenharmony_ci */ 158062306a36Sopenharmony_ciDEFINE_MUTEX(ice_global_cfg_lock_sw); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci/** 158362306a36Sopenharmony_ci * ice_should_retry_sq_send_cmd 158462306a36Sopenharmony_ci * @opcode: AQ opcode 158562306a36Sopenharmony_ci * 158662306a36Sopenharmony_ci * Decide if we should retry the send command routine for the ATQ, depending 158762306a36Sopenharmony_ci * on the opcode. 158862306a36Sopenharmony_ci */ 158962306a36Sopenharmony_cistatic bool ice_should_retry_sq_send_cmd(u16 opcode) 159062306a36Sopenharmony_ci{ 159162306a36Sopenharmony_ci switch (opcode) { 159262306a36Sopenharmony_ci case ice_aqc_opc_get_link_topo: 159362306a36Sopenharmony_ci case ice_aqc_opc_lldp_stop: 159462306a36Sopenharmony_ci case ice_aqc_opc_lldp_start: 159562306a36Sopenharmony_ci case ice_aqc_opc_lldp_filter_ctrl: 159662306a36Sopenharmony_ci return true; 159762306a36Sopenharmony_ci } 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci return false; 160062306a36Sopenharmony_ci} 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci/** 160362306a36Sopenharmony_ci * ice_sq_send_cmd_retry - send command to Control Queue (ATQ) 160462306a36Sopenharmony_ci * @hw: pointer to the HW struct 160562306a36Sopenharmony_ci * @cq: pointer to the specific Control queue 160662306a36Sopenharmony_ci * @desc: prefilled descriptor describing the command 160762306a36Sopenharmony_ci * @buf: buffer to use for indirect commands (or NULL for direct commands) 160862306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands (or 0 for direct commands) 160962306a36Sopenharmony_ci * @cd: pointer to command details structure 161062306a36Sopenharmony_ci * 161162306a36Sopenharmony_ci * Retry sending the FW Admin Queue command, multiple times, to the FW Admin 161262306a36Sopenharmony_ci * Queue if the EBUSY AQ error is returned. 161362306a36Sopenharmony_ci */ 161462306a36Sopenharmony_cistatic int 161562306a36Sopenharmony_ciice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq, 161662306a36Sopenharmony_ci struct ice_aq_desc *desc, void *buf, u16 buf_size, 161762306a36Sopenharmony_ci struct ice_sq_cd *cd) 161862306a36Sopenharmony_ci{ 161962306a36Sopenharmony_ci struct ice_aq_desc desc_cpy; 162062306a36Sopenharmony_ci bool is_cmd_for_retry; 162162306a36Sopenharmony_ci u8 idx = 0; 162262306a36Sopenharmony_ci u16 opcode; 162362306a36Sopenharmony_ci int status; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci opcode = le16_to_cpu(desc->opcode); 162662306a36Sopenharmony_ci is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode); 162762306a36Sopenharmony_ci memset(&desc_cpy, 0, sizeof(desc_cpy)); 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci if (is_cmd_for_retry) { 163062306a36Sopenharmony_ci /* All retryable cmds are direct, without buf. */ 163162306a36Sopenharmony_ci WARN_ON(buf); 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci memcpy(&desc_cpy, desc, sizeof(desc_cpy)); 163462306a36Sopenharmony_ci } 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci do { 163762306a36Sopenharmony_ci status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd); 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci if (!is_cmd_for_retry || !status || 164062306a36Sopenharmony_ci hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY) 164162306a36Sopenharmony_ci break; 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci memcpy(desc, &desc_cpy, sizeof(desc_cpy)); 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci msleep(ICE_SQ_SEND_DELAY_TIME_MS); 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci } while (++idx < ICE_SQ_SEND_MAX_EXECUTE); 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci return status; 165062306a36Sopenharmony_ci} 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci/** 165362306a36Sopenharmony_ci * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue 165462306a36Sopenharmony_ci * @hw: pointer to the HW struct 165562306a36Sopenharmony_ci * @desc: descriptor describing the command 165662306a36Sopenharmony_ci * @buf: buffer to use for indirect commands (NULL for direct commands) 165762306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands (0 for direct commands) 165862306a36Sopenharmony_ci * @cd: pointer to command details structure 165962306a36Sopenharmony_ci * 166062306a36Sopenharmony_ci * Helper function to send FW Admin Queue commands to the FW Admin Queue. 166162306a36Sopenharmony_ci */ 166262306a36Sopenharmony_ciint 166362306a36Sopenharmony_ciice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf, 166462306a36Sopenharmony_ci u16 buf_size, struct ice_sq_cd *cd) 166562306a36Sopenharmony_ci{ 166662306a36Sopenharmony_ci struct ice_aqc_req_res *cmd = &desc->params.res_owner; 166762306a36Sopenharmony_ci bool lock_acquired = false; 166862306a36Sopenharmony_ci int status; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci /* When a package download is in process (i.e. when the firmware's 167162306a36Sopenharmony_ci * Global Configuration Lock resource is held), only the Download 167262306a36Sopenharmony_ci * Package, Get Version, Get Package Info List, Upload Section, 167362306a36Sopenharmony_ci * Update Package, Set Port Parameters, Get/Set VLAN Mode Parameters, 167462306a36Sopenharmony_ci * Add Recipe, Set Recipes to Profile Association, Get Recipe, and Get 167562306a36Sopenharmony_ci * Recipes to Profile Association, and Release Resource (with resource 167662306a36Sopenharmony_ci * ID set to Global Config Lock) AdminQ commands are allowed; all others 167762306a36Sopenharmony_ci * must block until the package download completes and the Global Config 167862306a36Sopenharmony_ci * Lock is released. See also ice_acquire_global_cfg_lock(). 167962306a36Sopenharmony_ci */ 168062306a36Sopenharmony_ci switch (le16_to_cpu(desc->opcode)) { 168162306a36Sopenharmony_ci case ice_aqc_opc_download_pkg: 168262306a36Sopenharmony_ci case ice_aqc_opc_get_pkg_info_list: 168362306a36Sopenharmony_ci case ice_aqc_opc_get_ver: 168462306a36Sopenharmony_ci case ice_aqc_opc_upload_section: 168562306a36Sopenharmony_ci case ice_aqc_opc_update_pkg: 168662306a36Sopenharmony_ci case ice_aqc_opc_set_port_params: 168762306a36Sopenharmony_ci case ice_aqc_opc_get_vlan_mode_parameters: 168862306a36Sopenharmony_ci case ice_aqc_opc_set_vlan_mode_parameters: 168962306a36Sopenharmony_ci case ice_aqc_opc_add_recipe: 169062306a36Sopenharmony_ci case ice_aqc_opc_recipe_to_profile: 169162306a36Sopenharmony_ci case ice_aqc_opc_get_recipe: 169262306a36Sopenharmony_ci case ice_aqc_opc_get_recipe_to_profile: 169362306a36Sopenharmony_ci break; 169462306a36Sopenharmony_ci case ice_aqc_opc_release_res: 169562306a36Sopenharmony_ci if (le16_to_cpu(cmd->res_id) == ICE_AQC_RES_ID_GLBL_LOCK) 169662306a36Sopenharmony_ci break; 169762306a36Sopenharmony_ci fallthrough; 169862306a36Sopenharmony_ci default: 169962306a36Sopenharmony_ci mutex_lock(&ice_global_cfg_lock_sw); 170062306a36Sopenharmony_ci lock_acquired = true; 170162306a36Sopenharmony_ci break; 170262306a36Sopenharmony_ci } 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci status = ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd); 170562306a36Sopenharmony_ci if (lock_acquired) 170662306a36Sopenharmony_ci mutex_unlock(&ice_global_cfg_lock_sw); 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci return status; 170962306a36Sopenharmony_ci} 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci/** 171262306a36Sopenharmony_ci * ice_aq_get_fw_ver 171362306a36Sopenharmony_ci * @hw: pointer to the HW struct 171462306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 171562306a36Sopenharmony_ci * 171662306a36Sopenharmony_ci * Get the firmware version (0x0001) from the admin queue commands 171762306a36Sopenharmony_ci */ 171862306a36Sopenharmony_ciint ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd) 171962306a36Sopenharmony_ci{ 172062306a36Sopenharmony_ci struct ice_aqc_get_ver *resp; 172162306a36Sopenharmony_ci struct ice_aq_desc desc; 172262306a36Sopenharmony_ci int status; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci resp = &desc.params.get_ver; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver); 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci if (!status) { 173162306a36Sopenharmony_ci hw->fw_branch = resp->fw_branch; 173262306a36Sopenharmony_ci hw->fw_maj_ver = resp->fw_major; 173362306a36Sopenharmony_ci hw->fw_min_ver = resp->fw_minor; 173462306a36Sopenharmony_ci hw->fw_patch = resp->fw_patch; 173562306a36Sopenharmony_ci hw->fw_build = le32_to_cpu(resp->fw_build); 173662306a36Sopenharmony_ci hw->api_branch = resp->api_branch; 173762306a36Sopenharmony_ci hw->api_maj_ver = resp->api_major; 173862306a36Sopenharmony_ci hw->api_min_ver = resp->api_minor; 173962306a36Sopenharmony_ci hw->api_patch = resp->api_patch; 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci return status; 174362306a36Sopenharmony_ci} 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci/** 174662306a36Sopenharmony_ci * ice_aq_send_driver_ver 174762306a36Sopenharmony_ci * @hw: pointer to the HW struct 174862306a36Sopenharmony_ci * @dv: driver's major, minor version 174962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 175062306a36Sopenharmony_ci * 175162306a36Sopenharmony_ci * Send the driver version (0x0002) to the firmware 175262306a36Sopenharmony_ci */ 175362306a36Sopenharmony_ciint 175462306a36Sopenharmony_ciice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv, 175562306a36Sopenharmony_ci struct ice_sq_cd *cd) 175662306a36Sopenharmony_ci{ 175762306a36Sopenharmony_ci struct ice_aqc_driver_ver *cmd; 175862306a36Sopenharmony_ci struct ice_aq_desc desc; 175962306a36Sopenharmony_ci u16 len; 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci cmd = &desc.params.driver_ver; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci if (!dv) 176462306a36Sopenharmony_ci return -EINVAL; 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver); 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 176962306a36Sopenharmony_ci cmd->major_ver = dv->major_ver; 177062306a36Sopenharmony_ci cmd->minor_ver = dv->minor_ver; 177162306a36Sopenharmony_ci cmd->build_ver = dv->build_ver; 177262306a36Sopenharmony_ci cmd->subbuild_ver = dv->subbuild_ver; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci len = 0; 177562306a36Sopenharmony_ci while (len < sizeof(dv->driver_string) && 177662306a36Sopenharmony_ci isascii(dv->driver_string[len]) && dv->driver_string[len]) 177762306a36Sopenharmony_ci len++; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd); 178062306a36Sopenharmony_ci} 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci/** 178362306a36Sopenharmony_ci * ice_aq_q_shutdown 178462306a36Sopenharmony_ci * @hw: pointer to the HW struct 178562306a36Sopenharmony_ci * @unloading: is the driver unloading itself 178662306a36Sopenharmony_ci * 178762306a36Sopenharmony_ci * Tell the Firmware that we're shutting down the AdminQ and whether 178862306a36Sopenharmony_ci * or not the driver is unloading as well (0x0003). 178962306a36Sopenharmony_ci */ 179062306a36Sopenharmony_ciint ice_aq_q_shutdown(struct ice_hw *hw, bool unloading) 179162306a36Sopenharmony_ci{ 179262306a36Sopenharmony_ci struct ice_aqc_q_shutdown *cmd; 179362306a36Sopenharmony_ci struct ice_aq_desc desc; 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci cmd = &desc.params.q_shutdown; 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown); 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci if (unloading) 180062306a36Sopenharmony_ci cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 180362306a36Sopenharmony_ci} 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci/** 180662306a36Sopenharmony_ci * ice_aq_req_res 180762306a36Sopenharmony_ci * @hw: pointer to the HW struct 180862306a36Sopenharmony_ci * @res: resource ID 180962306a36Sopenharmony_ci * @access: access type 181062306a36Sopenharmony_ci * @sdp_number: resource number 181162306a36Sopenharmony_ci * @timeout: the maximum time in ms that the driver may hold the resource 181262306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 181362306a36Sopenharmony_ci * 181462306a36Sopenharmony_ci * Requests common resource using the admin queue commands (0x0008). 181562306a36Sopenharmony_ci * When attempting to acquire the Global Config Lock, the driver can 181662306a36Sopenharmony_ci * learn of three states: 181762306a36Sopenharmony_ci * 1) 0 - acquired lock, and can perform download package 181862306a36Sopenharmony_ci * 2) -EIO - did not get lock, driver should fail to load 181962306a36Sopenharmony_ci * 3) -EALREADY - did not get lock, but another driver has 182062306a36Sopenharmony_ci * successfully downloaded the package; the driver does 182162306a36Sopenharmony_ci * not have to download the package and can continue 182262306a36Sopenharmony_ci * loading 182362306a36Sopenharmony_ci * 182462306a36Sopenharmony_ci * Note that if the caller is in an acquire lock, perform action, release lock 182562306a36Sopenharmony_ci * phase of operation, it is possible that the FW may detect a timeout and issue 182662306a36Sopenharmony_ci * a CORER. In this case, the driver will receive a CORER interrupt and will 182762306a36Sopenharmony_ci * have to determine its cause. The calling thread that is handling this flow 182862306a36Sopenharmony_ci * will likely get an error propagated back to it indicating the Download 182962306a36Sopenharmony_ci * Package, Update Package or the Release Resource AQ commands timed out. 183062306a36Sopenharmony_ci */ 183162306a36Sopenharmony_cistatic int 183262306a36Sopenharmony_ciice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res, 183362306a36Sopenharmony_ci enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout, 183462306a36Sopenharmony_ci struct ice_sq_cd *cd) 183562306a36Sopenharmony_ci{ 183662306a36Sopenharmony_ci struct ice_aqc_req_res *cmd_resp; 183762306a36Sopenharmony_ci struct ice_aq_desc desc; 183862306a36Sopenharmony_ci int status; 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci cmd_resp = &desc.params.res_owner; 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res); 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci cmd_resp->res_id = cpu_to_le16(res); 184562306a36Sopenharmony_ci cmd_resp->access_type = cpu_to_le16(access); 184662306a36Sopenharmony_ci cmd_resp->res_number = cpu_to_le32(sdp_number); 184762306a36Sopenharmony_ci cmd_resp->timeout = cpu_to_le32(*timeout); 184862306a36Sopenharmony_ci *timeout = 0; 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci /* The completion specifies the maximum time in ms that the driver 185362306a36Sopenharmony_ci * may hold the resource in the Timeout field. 185462306a36Sopenharmony_ci */ 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci /* Global config lock response utilizes an additional status field. 185762306a36Sopenharmony_ci * 185862306a36Sopenharmony_ci * If the Global config lock resource is held by some other driver, the 185962306a36Sopenharmony_ci * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field 186062306a36Sopenharmony_ci * and the timeout field indicates the maximum time the current owner 186162306a36Sopenharmony_ci * of the resource has to free it. 186262306a36Sopenharmony_ci */ 186362306a36Sopenharmony_ci if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) { 186462306a36Sopenharmony_ci if (le16_to_cpu(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) { 186562306a36Sopenharmony_ci *timeout = le32_to_cpu(cmd_resp->timeout); 186662306a36Sopenharmony_ci return 0; 186762306a36Sopenharmony_ci } else if (le16_to_cpu(cmd_resp->status) == 186862306a36Sopenharmony_ci ICE_AQ_RES_GLBL_IN_PROG) { 186962306a36Sopenharmony_ci *timeout = le32_to_cpu(cmd_resp->timeout); 187062306a36Sopenharmony_ci return -EIO; 187162306a36Sopenharmony_ci } else if (le16_to_cpu(cmd_resp->status) == 187262306a36Sopenharmony_ci ICE_AQ_RES_GLBL_DONE) { 187362306a36Sopenharmony_ci return -EALREADY; 187462306a36Sopenharmony_ci } 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci /* invalid FW response, force a timeout immediately */ 187762306a36Sopenharmony_ci *timeout = 0; 187862306a36Sopenharmony_ci return -EIO; 187962306a36Sopenharmony_ci } 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci /* If the resource is held by some other driver, the command completes 188262306a36Sopenharmony_ci * with a busy return value and the timeout field indicates the maximum 188362306a36Sopenharmony_ci * time the current owner of the resource has to free it. 188462306a36Sopenharmony_ci */ 188562306a36Sopenharmony_ci if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) 188662306a36Sopenharmony_ci *timeout = le32_to_cpu(cmd_resp->timeout); 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci return status; 188962306a36Sopenharmony_ci} 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci/** 189262306a36Sopenharmony_ci * ice_aq_release_res 189362306a36Sopenharmony_ci * @hw: pointer to the HW struct 189462306a36Sopenharmony_ci * @res: resource ID 189562306a36Sopenharmony_ci * @sdp_number: resource number 189662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 189762306a36Sopenharmony_ci * 189862306a36Sopenharmony_ci * release common resource using the admin queue commands (0x0009) 189962306a36Sopenharmony_ci */ 190062306a36Sopenharmony_cistatic int 190162306a36Sopenharmony_ciice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number, 190262306a36Sopenharmony_ci struct ice_sq_cd *cd) 190362306a36Sopenharmony_ci{ 190462306a36Sopenharmony_ci struct ice_aqc_req_res *cmd; 190562306a36Sopenharmony_ci struct ice_aq_desc desc; 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci cmd = &desc.params.res_owner; 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res); 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci cmd->res_id = cpu_to_le16(res); 191262306a36Sopenharmony_ci cmd->res_number = cpu_to_le32(sdp_number); 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 191562306a36Sopenharmony_ci} 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci/** 191862306a36Sopenharmony_ci * ice_acquire_res 191962306a36Sopenharmony_ci * @hw: pointer to the HW structure 192062306a36Sopenharmony_ci * @res: resource ID 192162306a36Sopenharmony_ci * @access: access type (read or write) 192262306a36Sopenharmony_ci * @timeout: timeout in milliseconds 192362306a36Sopenharmony_ci * 192462306a36Sopenharmony_ci * This function will attempt to acquire the ownership of a resource. 192562306a36Sopenharmony_ci */ 192662306a36Sopenharmony_ciint 192762306a36Sopenharmony_ciice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, 192862306a36Sopenharmony_ci enum ice_aq_res_access_type access, u32 timeout) 192962306a36Sopenharmony_ci{ 193062306a36Sopenharmony_ci#define ICE_RES_POLLING_DELAY_MS 10 193162306a36Sopenharmony_ci u32 delay = ICE_RES_POLLING_DELAY_MS; 193262306a36Sopenharmony_ci u32 time_left = timeout; 193362306a36Sopenharmony_ci int status; 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci /* A return code of -EALREADY means that another driver has 193862306a36Sopenharmony_ci * previously acquired the resource and performed any necessary updates; 193962306a36Sopenharmony_ci * in this case the caller does not obtain the resource and has no 194062306a36Sopenharmony_ci * further work to do. 194162306a36Sopenharmony_ci */ 194262306a36Sopenharmony_ci if (status == -EALREADY) 194362306a36Sopenharmony_ci goto ice_acquire_res_exit; 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_ci if (status) 194662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access); 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci /* If necessary, poll until the current lock owner timeouts */ 194962306a36Sopenharmony_ci timeout = time_left; 195062306a36Sopenharmony_ci while (status && timeout && time_left) { 195162306a36Sopenharmony_ci mdelay(delay); 195262306a36Sopenharmony_ci timeout = (timeout > delay) ? timeout - delay : 0; 195362306a36Sopenharmony_ci status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci if (status == -EALREADY) 195662306a36Sopenharmony_ci /* lock free, but no work to do */ 195762306a36Sopenharmony_ci break; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci if (!status) 196062306a36Sopenharmony_ci /* lock acquired */ 196162306a36Sopenharmony_ci break; 196262306a36Sopenharmony_ci } 196362306a36Sopenharmony_ci if (status && status != -EALREADY) 196462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n"); 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ciice_acquire_res_exit: 196762306a36Sopenharmony_ci if (status == -EALREADY) { 196862306a36Sopenharmony_ci if (access == ICE_RES_WRITE) 196962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n"); 197062306a36Sopenharmony_ci else 197162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_RES, "Warning: -EALREADY not expected\n"); 197262306a36Sopenharmony_ci } 197362306a36Sopenharmony_ci return status; 197462306a36Sopenharmony_ci} 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci/** 197762306a36Sopenharmony_ci * ice_release_res 197862306a36Sopenharmony_ci * @hw: pointer to the HW structure 197962306a36Sopenharmony_ci * @res: resource ID 198062306a36Sopenharmony_ci * 198162306a36Sopenharmony_ci * This function will release a resource using the proper Admin Command. 198262306a36Sopenharmony_ci */ 198362306a36Sopenharmony_civoid ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res) 198462306a36Sopenharmony_ci{ 198562306a36Sopenharmony_ci unsigned long timeout; 198662306a36Sopenharmony_ci int status; 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci /* there are some rare cases when trying to release the resource 198962306a36Sopenharmony_ci * results in an admin queue timeout, so handle them correctly 199062306a36Sopenharmony_ci */ 199162306a36Sopenharmony_ci timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT; 199262306a36Sopenharmony_ci do { 199362306a36Sopenharmony_ci status = ice_aq_release_res(hw, res, 0, NULL); 199462306a36Sopenharmony_ci if (status != -EIO) 199562306a36Sopenharmony_ci break; 199662306a36Sopenharmony_ci usleep_range(1000, 2000); 199762306a36Sopenharmony_ci } while (time_before(jiffies, timeout)); 199862306a36Sopenharmony_ci} 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci/** 200162306a36Sopenharmony_ci * ice_aq_alloc_free_res - command to allocate/free resources 200262306a36Sopenharmony_ci * @hw: pointer to the HW struct 200362306a36Sopenharmony_ci * @buf: Indirect buffer to hold data parameters and response 200462306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands 200562306a36Sopenharmony_ci * @opc: pass in the command opcode 200662306a36Sopenharmony_ci * 200762306a36Sopenharmony_ci * Helper function to allocate/free resources using the admin queue commands 200862306a36Sopenharmony_ci */ 200962306a36Sopenharmony_ciint ice_aq_alloc_free_res(struct ice_hw *hw, 201062306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, 201162306a36Sopenharmony_ci enum ice_adminq_opc opc) 201262306a36Sopenharmony_ci{ 201362306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_cmd *cmd; 201462306a36Sopenharmony_ci struct ice_aq_desc desc; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci cmd = &desc.params.sw_res_ctrl; 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci if (!buf || buf_size < flex_array_size(buf, elem, 1)) 201962306a36Sopenharmony_ci return -EINVAL; 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, opc); 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci cmd->num_entries = cpu_to_le16(1); 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, buf, buf_size, NULL); 202862306a36Sopenharmony_ci} 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci/** 203162306a36Sopenharmony_ci * ice_alloc_hw_res - allocate resource 203262306a36Sopenharmony_ci * @hw: pointer to the HW struct 203362306a36Sopenharmony_ci * @type: type of resource 203462306a36Sopenharmony_ci * @num: number of resources to allocate 203562306a36Sopenharmony_ci * @btm: allocate from bottom 203662306a36Sopenharmony_ci * @res: pointer to array that will receive the resources 203762306a36Sopenharmony_ci */ 203862306a36Sopenharmony_ciint 203962306a36Sopenharmony_ciice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res) 204062306a36Sopenharmony_ci{ 204162306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *buf; 204262306a36Sopenharmony_ci u16 buf_len; 204362306a36Sopenharmony_ci int status; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci buf_len = struct_size(buf, elem, num); 204662306a36Sopenharmony_ci buf = kzalloc(buf_len, GFP_KERNEL); 204762306a36Sopenharmony_ci if (!buf) 204862306a36Sopenharmony_ci return -ENOMEM; 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci /* Prepare buffer to allocate resource. */ 205162306a36Sopenharmony_ci buf->num_elems = cpu_to_le16(num); 205262306a36Sopenharmony_ci buf->res_type = cpu_to_le16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED | 205362306a36Sopenharmony_ci ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX); 205462306a36Sopenharmony_ci if (btm) 205562306a36Sopenharmony_ci buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM); 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res); 205862306a36Sopenharmony_ci if (status) 205962306a36Sopenharmony_ci goto ice_alloc_res_exit; 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_ci memcpy(res, buf->elem, sizeof(*buf->elem) * num); 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ciice_alloc_res_exit: 206462306a36Sopenharmony_ci kfree(buf); 206562306a36Sopenharmony_ci return status; 206662306a36Sopenharmony_ci} 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci/** 206962306a36Sopenharmony_ci * ice_free_hw_res - free allocated HW resource 207062306a36Sopenharmony_ci * @hw: pointer to the HW struct 207162306a36Sopenharmony_ci * @type: type of resource to free 207262306a36Sopenharmony_ci * @num: number of resources 207362306a36Sopenharmony_ci * @res: pointer to array that contains the resources to free 207462306a36Sopenharmony_ci */ 207562306a36Sopenharmony_ciint ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res) 207662306a36Sopenharmony_ci{ 207762306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *buf; 207862306a36Sopenharmony_ci u16 buf_len; 207962306a36Sopenharmony_ci int status; 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci buf_len = struct_size(buf, elem, num); 208262306a36Sopenharmony_ci buf = kzalloc(buf_len, GFP_KERNEL); 208362306a36Sopenharmony_ci if (!buf) 208462306a36Sopenharmony_ci return -ENOMEM; 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci /* Prepare buffer to free resource. */ 208762306a36Sopenharmony_ci buf->num_elems = cpu_to_le16(num); 208862306a36Sopenharmony_ci buf->res_type = cpu_to_le16(type); 208962306a36Sopenharmony_ci memcpy(buf->elem, res, sizeof(*buf->elem) * num); 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res); 209262306a36Sopenharmony_ci if (status) 209362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci kfree(buf); 209662306a36Sopenharmony_ci return status; 209762306a36Sopenharmony_ci} 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci/** 210062306a36Sopenharmony_ci * ice_get_num_per_func - determine number of resources per PF 210162306a36Sopenharmony_ci * @hw: pointer to the HW structure 210262306a36Sopenharmony_ci * @max: value to be evenly split between each PF 210362306a36Sopenharmony_ci * 210462306a36Sopenharmony_ci * Determine the number of valid functions by going through the bitmap returned 210562306a36Sopenharmony_ci * from parsing capabilities and use this to calculate the number of resources 210662306a36Sopenharmony_ci * per PF based on the max value passed in. 210762306a36Sopenharmony_ci */ 210862306a36Sopenharmony_cistatic u32 ice_get_num_per_func(struct ice_hw *hw, u32 max) 210962306a36Sopenharmony_ci{ 211062306a36Sopenharmony_ci u8 funcs; 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_ci#define ICE_CAPS_VALID_FUNCS_M 0xFF 211362306a36Sopenharmony_ci funcs = hweight8(hw->dev_caps.common_cap.valid_functions & 211462306a36Sopenharmony_ci ICE_CAPS_VALID_FUNCS_M); 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci if (!funcs) 211762306a36Sopenharmony_ci return 0; 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci return max / funcs; 212062306a36Sopenharmony_ci} 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci/** 212362306a36Sopenharmony_ci * ice_parse_common_caps - parse common device/function capabilities 212462306a36Sopenharmony_ci * @hw: pointer to the HW struct 212562306a36Sopenharmony_ci * @caps: pointer to common capabilities structure 212662306a36Sopenharmony_ci * @elem: the capability element to parse 212762306a36Sopenharmony_ci * @prefix: message prefix for tracing capabilities 212862306a36Sopenharmony_ci * 212962306a36Sopenharmony_ci * Given a capability element, extract relevant details into the common 213062306a36Sopenharmony_ci * capability structure. 213162306a36Sopenharmony_ci * 213262306a36Sopenharmony_ci * Returns: true if the capability matches one of the common capability ids, 213362306a36Sopenharmony_ci * false otherwise. 213462306a36Sopenharmony_ci */ 213562306a36Sopenharmony_cistatic bool 213662306a36Sopenharmony_ciice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps, 213762306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *elem, const char *prefix) 213862306a36Sopenharmony_ci{ 213962306a36Sopenharmony_ci u32 logical_id = le32_to_cpu(elem->logical_id); 214062306a36Sopenharmony_ci u32 phys_id = le32_to_cpu(elem->phys_id); 214162306a36Sopenharmony_ci u32 number = le32_to_cpu(elem->number); 214262306a36Sopenharmony_ci u16 cap = le16_to_cpu(elem->cap); 214362306a36Sopenharmony_ci bool found = true; 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci switch (cap) { 214662306a36Sopenharmony_ci case ICE_AQC_CAPS_VALID_FUNCTIONS: 214762306a36Sopenharmony_ci caps->valid_functions = number; 214862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix, 214962306a36Sopenharmony_ci caps->valid_functions); 215062306a36Sopenharmony_ci break; 215162306a36Sopenharmony_ci case ICE_AQC_CAPS_SRIOV: 215262306a36Sopenharmony_ci caps->sr_iov_1_1 = (number == 1); 215362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix, 215462306a36Sopenharmony_ci caps->sr_iov_1_1); 215562306a36Sopenharmony_ci break; 215662306a36Sopenharmony_ci case ICE_AQC_CAPS_DCB: 215762306a36Sopenharmony_ci caps->dcb = (number == 1); 215862306a36Sopenharmony_ci caps->active_tc_bitmap = logical_id; 215962306a36Sopenharmony_ci caps->maxtc = phys_id; 216062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb); 216162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix, 216262306a36Sopenharmony_ci caps->active_tc_bitmap); 216362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc); 216462306a36Sopenharmony_ci break; 216562306a36Sopenharmony_ci case ICE_AQC_CAPS_RSS: 216662306a36Sopenharmony_ci caps->rss_table_size = number; 216762306a36Sopenharmony_ci caps->rss_table_entry_width = logical_id; 216862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix, 216962306a36Sopenharmony_ci caps->rss_table_size); 217062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix, 217162306a36Sopenharmony_ci caps->rss_table_entry_width); 217262306a36Sopenharmony_ci break; 217362306a36Sopenharmony_ci case ICE_AQC_CAPS_RXQS: 217462306a36Sopenharmony_ci caps->num_rxq = number; 217562306a36Sopenharmony_ci caps->rxq_first_id = phys_id; 217662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix, 217762306a36Sopenharmony_ci caps->num_rxq); 217862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix, 217962306a36Sopenharmony_ci caps->rxq_first_id); 218062306a36Sopenharmony_ci break; 218162306a36Sopenharmony_ci case ICE_AQC_CAPS_TXQS: 218262306a36Sopenharmony_ci caps->num_txq = number; 218362306a36Sopenharmony_ci caps->txq_first_id = phys_id; 218462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix, 218562306a36Sopenharmony_ci caps->num_txq); 218662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix, 218762306a36Sopenharmony_ci caps->txq_first_id); 218862306a36Sopenharmony_ci break; 218962306a36Sopenharmony_ci case ICE_AQC_CAPS_MSIX: 219062306a36Sopenharmony_ci caps->num_msix_vectors = number; 219162306a36Sopenharmony_ci caps->msix_vector_first_id = phys_id; 219262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix, 219362306a36Sopenharmony_ci caps->num_msix_vectors); 219462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix, 219562306a36Sopenharmony_ci caps->msix_vector_first_id); 219662306a36Sopenharmony_ci break; 219762306a36Sopenharmony_ci case ICE_AQC_CAPS_PENDING_NVM_VER: 219862306a36Sopenharmony_ci caps->nvm_update_pending_nvm = true; 219962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_nvm\n", prefix); 220062306a36Sopenharmony_ci break; 220162306a36Sopenharmony_ci case ICE_AQC_CAPS_PENDING_OROM_VER: 220262306a36Sopenharmony_ci caps->nvm_update_pending_orom = true; 220362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_orom\n", prefix); 220462306a36Sopenharmony_ci break; 220562306a36Sopenharmony_ci case ICE_AQC_CAPS_PENDING_NET_VER: 220662306a36Sopenharmony_ci caps->nvm_update_pending_netlist = true; 220762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_netlist\n", prefix); 220862306a36Sopenharmony_ci break; 220962306a36Sopenharmony_ci case ICE_AQC_CAPS_NVM_MGMT: 221062306a36Sopenharmony_ci caps->nvm_unified_update = 221162306a36Sopenharmony_ci (number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ? 221262306a36Sopenharmony_ci true : false; 221362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix, 221462306a36Sopenharmony_ci caps->nvm_unified_update); 221562306a36Sopenharmony_ci break; 221662306a36Sopenharmony_ci case ICE_AQC_CAPS_RDMA: 221762306a36Sopenharmony_ci caps->rdma = (number == 1); 221862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: rdma = %d\n", prefix, caps->rdma); 221962306a36Sopenharmony_ci break; 222062306a36Sopenharmony_ci case ICE_AQC_CAPS_MAX_MTU: 222162306a36Sopenharmony_ci caps->max_mtu = number; 222262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n", 222362306a36Sopenharmony_ci prefix, caps->max_mtu); 222462306a36Sopenharmony_ci break; 222562306a36Sopenharmony_ci case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE: 222662306a36Sopenharmony_ci caps->pcie_reset_avoidance = (number > 0); 222762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, 222862306a36Sopenharmony_ci "%s: pcie_reset_avoidance = %d\n", prefix, 222962306a36Sopenharmony_ci caps->pcie_reset_avoidance); 223062306a36Sopenharmony_ci break; 223162306a36Sopenharmony_ci case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT: 223262306a36Sopenharmony_ci caps->reset_restrict_support = (number == 1); 223362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, 223462306a36Sopenharmony_ci "%s: reset_restrict_support = %d\n", prefix, 223562306a36Sopenharmony_ci caps->reset_restrict_support); 223662306a36Sopenharmony_ci break; 223762306a36Sopenharmony_ci case ICE_AQC_CAPS_FW_LAG_SUPPORT: 223862306a36Sopenharmony_ci caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG); 223962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n", 224062306a36Sopenharmony_ci prefix, caps->roce_lag); 224162306a36Sopenharmony_ci caps->sriov_lag = !!(number & ICE_AQC_BIT_SRIOV_LAG); 224262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %u\n", 224362306a36Sopenharmony_ci prefix, caps->sriov_lag); 224462306a36Sopenharmony_ci break; 224562306a36Sopenharmony_ci default: 224662306a36Sopenharmony_ci /* Not one of the recognized common capabilities */ 224762306a36Sopenharmony_ci found = false; 224862306a36Sopenharmony_ci } 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci return found; 225162306a36Sopenharmony_ci} 225262306a36Sopenharmony_ci 225362306a36Sopenharmony_ci/** 225462306a36Sopenharmony_ci * ice_recalc_port_limited_caps - Recalculate port limited capabilities 225562306a36Sopenharmony_ci * @hw: pointer to the HW structure 225662306a36Sopenharmony_ci * @caps: pointer to capabilities structure to fix 225762306a36Sopenharmony_ci * 225862306a36Sopenharmony_ci * Re-calculate the capabilities that are dependent on the number of physical 225962306a36Sopenharmony_ci * ports; i.e. some features are not supported or function differently on 226062306a36Sopenharmony_ci * devices with more than 4 ports. 226162306a36Sopenharmony_ci */ 226262306a36Sopenharmony_cistatic void 226362306a36Sopenharmony_ciice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps) 226462306a36Sopenharmony_ci{ 226562306a36Sopenharmony_ci /* This assumes device capabilities are always scanned before function 226662306a36Sopenharmony_ci * capabilities during the initialization flow. 226762306a36Sopenharmony_ci */ 226862306a36Sopenharmony_ci if (hw->dev_caps.num_funcs > 4) { 226962306a36Sopenharmony_ci /* Max 4 TCs per port */ 227062306a36Sopenharmony_ci caps->maxtc = 4; 227162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %d (based on #ports)\n", 227262306a36Sopenharmony_ci caps->maxtc); 227362306a36Sopenharmony_ci if (caps->rdma) { 227462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "forcing RDMA off\n"); 227562306a36Sopenharmony_ci caps->rdma = 0; 227662306a36Sopenharmony_ci } 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci /* print message only when processing device capabilities 227962306a36Sopenharmony_ci * during initialization. 228062306a36Sopenharmony_ci */ 228162306a36Sopenharmony_ci if (caps == &hw->dev_caps.common_cap) 228262306a36Sopenharmony_ci dev_info(ice_hw_to_dev(hw), "RDMA functionality is not available with the current device configuration.\n"); 228362306a36Sopenharmony_ci } 228462306a36Sopenharmony_ci} 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci/** 228762306a36Sopenharmony_ci * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps 228862306a36Sopenharmony_ci * @hw: pointer to the HW struct 228962306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure 229062306a36Sopenharmony_ci * @cap: pointer to the capability element to parse 229162306a36Sopenharmony_ci * 229262306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_VF. 229362306a36Sopenharmony_ci */ 229462306a36Sopenharmony_cistatic void 229562306a36Sopenharmony_ciice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p, 229662306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 229762306a36Sopenharmony_ci{ 229862306a36Sopenharmony_ci u32 logical_id = le32_to_cpu(cap->logical_id); 229962306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci func_p->num_allocd_vfs = number; 230262306a36Sopenharmony_ci func_p->vf_base_id = logical_id; 230362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n", 230462306a36Sopenharmony_ci func_p->num_allocd_vfs); 230562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n", 230662306a36Sopenharmony_ci func_p->vf_base_id); 230762306a36Sopenharmony_ci} 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_ci/** 231062306a36Sopenharmony_ci * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps 231162306a36Sopenharmony_ci * @hw: pointer to the HW struct 231262306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure 231362306a36Sopenharmony_ci * @cap: pointer to the capability element to parse 231462306a36Sopenharmony_ci * 231562306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_VSI. 231662306a36Sopenharmony_ci */ 231762306a36Sopenharmony_cistatic void 231862306a36Sopenharmony_ciice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p, 231962306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 232062306a36Sopenharmony_ci{ 232162306a36Sopenharmony_ci func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI); 232262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n", 232362306a36Sopenharmony_ci le32_to_cpu(cap->number)); 232462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n", 232562306a36Sopenharmony_ci func_p->guar_num_vsi); 232662306a36Sopenharmony_ci} 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_ci/** 232962306a36Sopenharmony_ci * ice_parse_1588_func_caps - Parse ICE_AQC_CAPS_1588 function caps 233062306a36Sopenharmony_ci * @hw: pointer to the HW struct 233162306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure 233262306a36Sopenharmony_ci * @cap: pointer to the capability element to parse 233362306a36Sopenharmony_ci * 233462306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_1588. 233562306a36Sopenharmony_ci */ 233662306a36Sopenharmony_cistatic void 233762306a36Sopenharmony_ciice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p, 233862306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 233962306a36Sopenharmony_ci{ 234062306a36Sopenharmony_ci struct ice_ts_func_info *info = &func_p->ts_func_info; 234162306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 234262306a36Sopenharmony_ci 234362306a36Sopenharmony_ci info->ena = ((number & ICE_TS_FUNC_ENA_M) != 0); 234462306a36Sopenharmony_ci func_p->common_cap.ieee_1588 = info->ena; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci info->src_tmr_owned = ((number & ICE_TS_SRC_TMR_OWND_M) != 0); 234762306a36Sopenharmony_ci info->tmr_ena = ((number & ICE_TS_TMR_ENA_M) != 0); 234862306a36Sopenharmony_ci info->tmr_index_owned = ((number & ICE_TS_TMR_IDX_OWND_M) != 0); 234962306a36Sopenharmony_ci info->tmr_index_assoc = ((number & ICE_TS_TMR_IDX_ASSOC_M) != 0); 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_ci info->clk_freq = (number & ICE_TS_CLK_FREQ_M) >> ICE_TS_CLK_FREQ_S; 235262306a36Sopenharmony_ci info->clk_src = ((number & ICE_TS_CLK_SRC_M) != 0); 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci if (info->clk_freq < NUM_ICE_TIME_REF_FREQ) { 235562306a36Sopenharmony_ci info->time_ref = (enum ice_time_ref_freq)info->clk_freq; 235662306a36Sopenharmony_ci } else { 235762306a36Sopenharmony_ci /* Unknown clock frequency, so assume a (probably incorrect) 235862306a36Sopenharmony_ci * default to avoid out-of-bounds look ups of frequency 235962306a36Sopenharmony_ci * related information. 236062306a36Sopenharmony_ci */ 236162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "1588 func caps: unknown clock frequency %u\n", 236262306a36Sopenharmony_ci info->clk_freq); 236362306a36Sopenharmony_ci info->time_ref = ICE_TIME_REF_FREQ_25_000; 236462306a36Sopenharmony_ci } 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: ieee_1588 = %u\n", 236762306a36Sopenharmony_ci func_p->common_cap.ieee_1588); 236862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: src_tmr_owned = %u\n", 236962306a36Sopenharmony_ci info->src_tmr_owned); 237062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_ena = %u\n", 237162306a36Sopenharmony_ci info->tmr_ena); 237262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_owned = %u\n", 237362306a36Sopenharmony_ci info->tmr_index_owned); 237462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_assoc = %u\n", 237562306a36Sopenharmony_ci info->tmr_index_assoc); 237662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: clk_freq = %u\n", 237762306a36Sopenharmony_ci info->clk_freq); 237862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: clk_src = %u\n", 237962306a36Sopenharmony_ci info->clk_src); 238062306a36Sopenharmony_ci} 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci/** 238362306a36Sopenharmony_ci * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps 238462306a36Sopenharmony_ci * @hw: pointer to the HW struct 238562306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure 238662306a36Sopenharmony_ci * 238762306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_FD. 238862306a36Sopenharmony_ci */ 238962306a36Sopenharmony_cistatic void 239062306a36Sopenharmony_ciice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p) 239162306a36Sopenharmony_ci{ 239262306a36Sopenharmony_ci u32 reg_val, val; 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci reg_val = rd32(hw, GLQF_FD_SIZE); 239562306a36Sopenharmony_ci val = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >> 239662306a36Sopenharmony_ci GLQF_FD_SIZE_FD_GSIZE_S; 239762306a36Sopenharmony_ci func_p->fd_fltr_guar = 239862306a36Sopenharmony_ci ice_get_num_per_func(hw, val); 239962306a36Sopenharmony_ci val = (reg_val & GLQF_FD_SIZE_FD_BSIZE_M) >> 240062306a36Sopenharmony_ci GLQF_FD_SIZE_FD_BSIZE_S; 240162306a36Sopenharmony_ci func_p->fd_fltr_best_effort = val; 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_guar = %d\n", 240462306a36Sopenharmony_ci func_p->fd_fltr_guar); 240562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_best_effort = %d\n", 240662306a36Sopenharmony_ci func_p->fd_fltr_best_effort); 240762306a36Sopenharmony_ci} 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci/** 241062306a36Sopenharmony_ci * ice_parse_func_caps - Parse function capabilities 241162306a36Sopenharmony_ci * @hw: pointer to the HW struct 241262306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure 241362306a36Sopenharmony_ci * @buf: buffer containing the function capability records 241462306a36Sopenharmony_ci * @cap_count: the number of capabilities 241562306a36Sopenharmony_ci * 241662306a36Sopenharmony_ci * Helper function to parse function (0x000A) capabilities list. For 241762306a36Sopenharmony_ci * capabilities shared between device and function, this relies on 241862306a36Sopenharmony_ci * ice_parse_common_caps. 241962306a36Sopenharmony_ci * 242062306a36Sopenharmony_ci * Loop through the list of provided capabilities and extract the relevant 242162306a36Sopenharmony_ci * data into the function capabilities structured. 242262306a36Sopenharmony_ci */ 242362306a36Sopenharmony_cistatic void 242462306a36Sopenharmony_ciice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p, 242562306a36Sopenharmony_ci void *buf, u32 cap_count) 242662306a36Sopenharmony_ci{ 242762306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap_resp; 242862306a36Sopenharmony_ci u32 i; 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci cap_resp = buf; 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ci memset(func_p, 0, sizeof(*func_p)); 243362306a36Sopenharmony_ci 243462306a36Sopenharmony_ci for (i = 0; i < cap_count; i++) { 243562306a36Sopenharmony_ci u16 cap = le16_to_cpu(cap_resp[i].cap); 243662306a36Sopenharmony_ci bool found; 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci found = ice_parse_common_caps(hw, &func_p->common_cap, 243962306a36Sopenharmony_ci &cap_resp[i], "func caps"); 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci switch (cap) { 244262306a36Sopenharmony_ci case ICE_AQC_CAPS_VF: 244362306a36Sopenharmony_ci ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]); 244462306a36Sopenharmony_ci break; 244562306a36Sopenharmony_ci case ICE_AQC_CAPS_VSI: 244662306a36Sopenharmony_ci ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]); 244762306a36Sopenharmony_ci break; 244862306a36Sopenharmony_ci case ICE_AQC_CAPS_1588: 244962306a36Sopenharmony_ci ice_parse_1588_func_caps(hw, func_p, &cap_resp[i]); 245062306a36Sopenharmony_ci break; 245162306a36Sopenharmony_ci case ICE_AQC_CAPS_FD: 245262306a36Sopenharmony_ci ice_parse_fdir_func_caps(hw, func_p); 245362306a36Sopenharmony_ci break; 245462306a36Sopenharmony_ci default: 245562306a36Sopenharmony_ci /* Don't list common capabilities as unknown */ 245662306a36Sopenharmony_ci if (!found) 245762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n", 245862306a36Sopenharmony_ci i, cap); 245962306a36Sopenharmony_ci break; 246062306a36Sopenharmony_ci } 246162306a36Sopenharmony_ci } 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_ci ice_recalc_port_limited_caps(hw, &func_p->common_cap); 246462306a36Sopenharmony_ci} 246562306a36Sopenharmony_ci 246662306a36Sopenharmony_ci/** 246762306a36Sopenharmony_ci * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps 246862306a36Sopenharmony_ci * @hw: pointer to the HW struct 246962306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure 247062306a36Sopenharmony_ci * @cap: capability element to parse 247162306a36Sopenharmony_ci * 247262306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities. 247362306a36Sopenharmony_ci */ 247462306a36Sopenharmony_cistatic void 247562306a36Sopenharmony_ciice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, 247662306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 247762306a36Sopenharmony_ci{ 247862306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 247962306a36Sopenharmony_ci 248062306a36Sopenharmony_ci dev_p->num_funcs = hweight32(number); 248162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n", 248262306a36Sopenharmony_ci dev_p->num_funcs); 248362306a36Sopenharmony_ci} 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_ci/** 248662306a36Sopenharmony_ci * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps 248762306a36Sopenharmony_ci * @hw: pointer to the HW struct 248862306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure 248962306a36Sopenharmony_ci * @cap: capability element to parse 249062306a36Sopenharmony_ci * 249162306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_VF for device capabilities. 249262306a36Sopenharmony_ci */ 249362306a36Sopenharmony_cistatic void 249462306a36Sopenharmony_ciice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, 249562306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 249662306a36Sopenharmony_ci{ 249762306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci dev_p->num_vfs_exposed = number; 250062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n", 250162306a36Sopenharmony_ci dev_p->num_vfs_exposed); 250262306a36Sopenharmony_ci} 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ci/** 250562306a36Sopenharmony_ci * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps 250662306a36Sopenharmony_ci * @hw: pointer to the HW struct 250762306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure 250862306a36Sopenharmony_ci * @cap: capability element to parse 250962306a36Sopenharmony_ci * 251062306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_VSI for device capabilities. 251162306a36Sopenharmony_ci */ 251262306a36Sopenharmony_cistatic void 251362306a36Sopenharmony_ciice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, 251462306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 251562306a36Sopenharmony_ci{ 251662306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci dev_p->num_vsi_allocd_to_host = number; 251962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n", 252062306a36Sopenharmony_ci dev_p->num_vsi_allocd_to_host); 252162306a36Sopenharmony_ci} 252262306a36Sopenharmony_ci 252362306a36Sopenharmony_ci/** 252462306a36Sopenharmony_ci * ice_parse_1588_dev_caps - Parse ICE_AQC_CAPS_1588 device caps 252562306a36Sopenharmony_ci * @hw: pointer to the HW struct 252662306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure 252762306a36Sopenharmony_ci * @cap: capability element to parse 252862306a36Sopenharmony_ci * 252962306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_1588 for device capabilities. 253062306a36Sopenharmony_ci */ 253162306a36Sopenharmony_cistatic void 253262306a36Sopenharmony_ciice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, 253362306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 253462306a36Sopenharmony_ci{ 253562306a36Sopenharmony_ci struct ice_ts_dev_info *info = &dev_p->ts_dev_info; 253662306a36Sopenharmony_ci u32 logical_id = le32_to_cpu(cap->logical_id); 253762306a36Sopenharmony_ci u32 phys_id = le32_to_cpu(cap->phys_id); 253862306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_ci info->ena = ((number & ICE_TS_DEV_ENA_M) != 0); 254162306a36Sopenharmony_ci dev_p->common_cap.ieee_1588 = info->ena; 254262306a36Sopenharmony_ci 254362306a36Sopenharmony_ci info->tmr0_owner = number & ICE_TS_TMR0_OWNR_M; 254462306a36Sopenharmony_ci info->tmr0_owned = ((number & ICE_TS_TMR0_OWND_M) != 0); 254562306a36Sopenharmony_ci info->tmr0_ena = ((number & ICE_TS_TMR0_ENA_M) != 0); 254662306a36Sopenharmony_ci 254762306a36Sopenharmony_ci info->tmr1_owner = (number & ICE_TS_TMR1_OWNR_M) >> ICE_TS_TMR1_OWNR_S; 254862306a36Sopenharmony_ci info->tmr1_owned = ((number & ICE_TS_TMR1_OWND_M) != 0); 254962306a36Sopenharmony_ci info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0); 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0); 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci info->ena_ports = logical_id; 255462306a36Sopenharmony_ci info->tmr_own_map = phys_id; 255562306a36Sopenharmony_ci 255662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 = %u\n", 255762306a36Sopenharmony_ci dev_p->common_cap.ieee_1588); 255862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owner = %u\n", 255962306a36Sopenharmony_ci info->tmr0_owner); 256062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owned = %u\n", 256162306a36Sopenharmony_ci info->tmr0_owned); 256262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_ena = %u\n", 256362306a36Sopenharmony_ci info->tmr0_ena); 256462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owner = %u\n", 256562306a36Sopenharmony_ci info->tmr1_owner); 256662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owned = %u\n", 256762306a36Sopenharmony_ci info->tmr1_owned); 256862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_ena = %u\n", 256962306a36Sopenharmony_ci info->tmr1_ena); 257062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n", 257162306a36Sopenharmony_ci info->ts_ll_read); 257262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n", 257362306a36Sopenharmony_ci info->ena_ports); 257462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n", 257562306a36Sopenharmony_ci info->tmr_own_map); 257662306a36Sopenharmony_ci} 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci/** 257962306a36Sopenharmony_ci * ice_parse_fdir_dev_caps - Parse ICE_AQC_CAPS_FD device caps 258062306a36Sopenharmony_ci * @hw: pointer to the HW struct 258162306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure 258262306a36Sopenharmony_ci * @cap: capability element to parse 258362306a36Sopenharmony_ci * 258462306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_FD for device capabilities. 258562306a36Sopenharmony_ci */ 258662306a36Sopenharmony_cistatic void 258762306a36Sopenharmony_ciice_parse_fdir_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, 258862306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap) 258962306a36Sopenharmony_ci{ 259062306a36Sopenharmony_ci u32 number = le32_to_cpu(cap->number); 259162306a36Sopenharmony_ci 259262306a36Sopenharmony_ci dev_p->num_flow_director_fltr = number; 259362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: num_flow_director_fltr = %d\n", 259462306a36Sopenharmony_ci dev_p->num_flow_director_fltr); 259562306a36Sopenharmony_ci} 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci/** 259862306a36Sopenharmony_ci * ice_parse_dev_caps - Parse device capabilities 259962306a36Sopenharmony_ci * @hw: pointer to the HW struct 260062306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure 260162306a36Sopenharmony_ci * @buf: buffer containing the device capability records 260262306a36Sopenharmony_ci * @cap_count: the number of capabilities 260362306a36Sopenharmony_ci * 260462306a36Sopenharmony_ci * Helper device to parse device (0x000B) capabilities list. For 260562306a36Sopenharmony_ci * capabilities shared between device and function, this relies on 260662306a36Sopenharmony_ci * ice_parse_common_caps. 260762306a36Sopenharmony_ci * 260862306a36Sopenharmony_ci * Loop through the list of provided capabilities and extract the relevant 260962306a36Sopenharmony_ci * data into the device capabilities structured. 261062306a36Sopenharmony_ci */ 261162306a36Sopenharmony_cistatic void 261262306a36Sopenharmony_ciice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, 261362306a36Sopenharmony_ci void *buf, u32 cap_count) 261462306a36Sopenharmony_ci{ 261562306a36Sopenharmony_ci struct ice_aqc_list_caps_elem *cap_resp; 261662306a36Sopenharmony_ci u32 i; 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci cap_resp = buf; 261962306a36Sopenharmony_ci 262062306a36Sopenharmony_ci memset(dev_p, 0, sizeof(*dev_p)); 262162306a36Sopenharmony_ci 262262306a36Sopenharmony_ci for (i = 0; i < cap_count; i++) { 262362306a36Sopenharmony_ci u16 cap = le16_to_cpu(cap_resp[i].cap); 262462306a36Sopenharmony_ci bool found; 262562306a36Sopenharmony_ci 262662306a36Sopenharmony_ci found = ice_parse_common_caps(hw, &dev_p->common_cap, 262762306a36Sopenharmony_ci &cap_resp[i], "dev caps"); 262862306a36Sopenharmony_ci 262962306a36Sopenharmony_ci switch (cap) { 263062306a36Sopenharmony_ci case ICE_AQC_CAPS_VALID_FUNCTIONS: 263162306a36Sopenharmony_ci ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]); 263262306a36Sopenharmony_ci break; 263362306a36Sopenharmony_ci case ICE_AQC_CAPS_VF: 263462306a36Sopenharmony_ci ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]); 263562306a36Sopenharmony_ci break; 263662306a36Sopenharmony_ci case ICE_AQC_CAPS_VSI: 263762306a36Sopenharmony_ci ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]); 263862306a36Sopenharmony_ci break; 263962306a36Sopenharmony_ci case ICE_AQC_CAPS_1588: 264062306a36Sopenharmony_ci ice_parse_1588_dev_caps(hw, dev_p, &cap_resp[i]); 264162306a36Sopenharmony_ci break; 264262306a36Sopenharmony_ci case ICE_AQC_CAPS_FD: 264362306a36Sopenharmony_ci ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]); 264462306a36Sopenharmony_ci break; 264562306a36Sopenharmony_ci default: 264662306a36Sopenharmony_ci /* Don't list common capabilities as unknown */ 264762306a36Sopenharmony_ci if (!found) 264862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%d]: 0x%x\n", 264962306a36Sopenharmony_ci i, cap); 265062306a36Sopenharmony_ci break; 265162306a36Sopenharmony_ci } 265262306a36Sopenharmony_ci } 265362306a36Sopenharmony_ci 265462306a36Sopenharmony_ci ice_recalc_port_limited_caps(hw, &dev_p->common_cap); 265562306a36Sopenharmony_ci} 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci/** 265862306a36Sopenharmony_ci * ice_aq_get_netlist_node 265962306a36Sopenharmony_ci * @hw: pointer to the hw struct 266062306a36Sopenharmony_ci * @cmd: get_link_topo AQ structure 266162306a36Sopenharmony_ci * @node_part_number: output node part number if node found 266262306a36Sopenharmony_ci * @node_handle: output node handle parameter if node found 266362306a36Sopenharmony_ci */ 266462306a36Sopenharmony_cistatic int 266562306a36Sopenharmony_ciice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd, 266662306a36Sopenharmony_ci u8 *node_part_number, u16 *node_handle) 266762306a36Sopenharmony_ci{ 266862306a36Sopenharmony_ci struct ice_aq_desc desc; 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); 267162306a36Sopenharmony_ci desc.params.get_link_topo = *cmd; 267262306a36Sopenharmony_ci 267362306a36Sopenharmony_ci if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL)) 267462306a36Sopenharmony_ci return -EIO; 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci if (node_handle) 267762306a36Sopenharmony_ci *node_handle = le16_to_cpu(desc.params.get_link_topo.addr.handle); 267862306a36Sopenharmony_ci if (node_part_number) 267962306a36Sopenharmony_ci *node_part_number = desc.params.get_link_topo.node_part_num; 268062306a36Sopenharmony_ci 268162306a36Sopenharmony_ci return 0; 268262306a36Sopenharmony_ci} 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci/** 268562306a36Sopenharmony_ci * ice_is_pf_c827 - check if pf contains c827 phy 268662306a36Sopenharmony_ci * @hw: pointer to the hw struct 268762306a36Sopenharmony_ci */ 268862306a36Sopenharmony_cibool ice_is_pf_c827(struct ice_hw *hw) 268962306a36Sopenharmony_ci{ 269062306a36Sopenharmony_ci struct ice_aqc_get_link_topo cmd = {}; 269162306a36Sopenharmony_ci u8 node_part_number; 269262306a36Sopenharmony_ci u16 node_handle; 269362306a36Sopenharmony_ci int status; 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci if (hw->mac_type != ICE_MAC_E810) 269662306a36Sopenharmony_ci return false; 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci if (hw->device_id != ICE_DEV_ID_E810C_QSFP) 269962306a36Sopenharmony_ci return true; 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci cmd.addr.topo_params.node_type_ctx = 270262306a36Sopenharmony_ci FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY) | 270362306a36Sopenharmony_ci FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ICE_AQC_LINK_TOPO_NODE_CTX_PORT); 270462306a36Sopenharmony_ci cmd.addr.topo_params.index = 0; 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number, 270762306a36Sopenharmony_ci &node_handle); 270862306a36Sopenharmony_ci 270962306a36Sopenharmony_ci if (status || node_part_number != ICE_AQC_GET_LINK_TOPO_NODE_NR_C827) 271062306a36Sopenharmony_ci return false; 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci if (node_handle == E810C_QSFP_C827_0_HANDLE || node_handle == E810C_QSFP_C827_1_HANDLE) 271362306a36Sopenharmony_ci return true; 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci return false; 271662306a36Sopenharmony_ci} 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci/** 271962306a36Sopenharmony_ci * ice_aq_list_caps - query function/device capabilities 272062306a36Sopenharmony_ci * @hw: pointer to the HW struct 272162306a36Sopenharmony_ci * @buf: a buffer to hold the capabilities 272262306a36Sopenharmony_ci * @buf_size: size of the buffer 272362306a36Sopenharmony_ci * @cap_count: if not NULL, set to the number of capabilities reported 272462306a36Sopenharmony_ci * @opc: capabilities type to discover, device or function 272562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 272662306a36Sopenharmony_ci * 272762306a36Sopenharmony_ci * Get the function (0x000A) or device (0x000B) capabilities description from 272862306a36Sopenharmony_ci * firmware and store it in the buffer. 272962306a36Sopenharmony_ci * 273062306a36Sopenharmony_ci * If the cap_count pointer is not NULL, then it is set to the number of 273162306a36Sopenharmony_ci * capabilities firmware will report. Note that if the buffer size is too 273262306a36Sopenharmony_ci * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The 273362306a36Sopenharmony_ci * cap_count will still be updated in this case. It is recommended that the 273462306a36Sopenharmony_ci * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that 273562306a36Sopenharmony_ci * firmware could return) to avoid this. 273662306a36Sopenharmony_ci */ 273762306a36Sopenharmony_ciint 273862306a36Sopenharmony_ciice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, 273962306a36Sopenharmony_ci enum ice_adminq_opc opc, struct ice_sq_cd *cd) 274062306a36Sopenharmony_ci{ 274162306a36Sopenharmony_ci struct ice_aqc_list_caps *cmd; 274262306a36Sopenharmony_ci struct ice_aq_desc desc; 274362306a36Sopenharmony_ci int status; 274462306a36Sopenharmony_ci 274562306a36Sopenharmony_ci cmd = &desc.params.get_cap; 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_ci if (opc != ice_aqc_opc_list_func_caps && 274862306a36Sopenharmony_ci opc != ice_aqc_opc_list_dev_caps) 274962306a36Sopenharmony_ci return -EINVAL; 275062306a36Sopenharmony_ci 275162306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, opc); 275262306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 275362306a36Sopenharmony_ci 275462306a36Sopenharmony_ci if (cap_count) 275562306a36Sopenharmony_ci *cap_count = le32_to_cpu(cmd->count); 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_ci return status; 275862306a36Sopenharmony_ci} 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci/** 276162306a36Sopenharmony_ci * ice_discover_dev_caps - Read and extract device capabilities 276262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 276362306a36Sopenharmony_ci * @dev_caps: pointer to device capabilities structure 276462306a36Sopenharmony_ci * 276562306a36Sopenharmony_ci * Read the device capabilities and extract them into the dev_caps structure 276662306a36Sopenharmony_ci * for later use. 276762306a36Sopenharmony_ci */ 276862306a36Sopenharmony_ciint 276962306a36Sopenharmony_ciice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps) 277062306a36Sopenharmony_ci{ 277162306a36Sopenharmony_ci u32 cap_count = 0; 277262306a36Sopenharmony_ci void *cbuf; 277362306a36Sopenharmony_ci int status; 277462306a36Sopenharmony_ci 277562306a36Sopenharmony_ci cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL); 277662306a36Sopenharmony_ci if (!cbuf) 277762306a36Sopenharmony_ci return -ENOMEM; 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_ci /* Although the driver doesn't know the number of capabilities the 278062306a36Sopenharmony_ci * device will return, we can simply send a 4KB buffer, the maximum 278162306a36Sopenharmony_ci * possible size that firmware can return. 278262306a36Sopenharmony_ci */ 278362306a36Sopenharmony_ci cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem); 278462306a36Sopenharmony_ci 278562306a36Sopenharmony_ci status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count, 278662306a36Sopenharmony_ci ice_aqc_opc_list_dev_caps, NULL); 278762306a36Sopenharmony_ci if (!status) 278862306a36Sopenharmony_ci ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count); 278962306a36Sopenharmony_ci kfree(cbuf); 279062306a36Sopenharmony_ci 279162306a36Sopenharmony_ci return status; 279262306a36Sopenharmony_ci} 279362306a36Sopenharmony_ci 279462306a36Sopenharmony_ci/** 279562306a36Sopenharmony_ci * ice_discover_func_caps - Read and extract function capabilities 279662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 279762306a36Sopenharmony_ci * @func_caps: pointer to function capabilities structure 279862306a36Sopenharmony_ci * 279962306a36Sopenharmony_ci * Read the function capabilities and extract them into the func_caps structure 280062306a36Sopenharmony_ci * for later use. 280162306a36Sopenharmony_ci */ 280262306a36Sopenharmony_cistatic int 280362306a36Sopenharmony_ciice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps) 280462306a36Sopenharmony_ci{ 280562306a36Sopenharmony_ci u32 cap_count = 0; 280662306a36Sopenharmony_ci void *cbuf; 280762306a36Sopenharmony_ci int status; 280862306a36Sopenharmony_ci 280962306a36Sopenharmony_ci cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL); 281062306a36Sopenharmony_ci if (!cbuf) 281162306a36Sopenharmony_ci return -ENOMEM; 281262306a36Sopenharmony_ci 281362306a36Sopenharmony_ci /* Although the driver doesn't know the number of capabilities the 281462306a36Sopenharmony_ci * device will return, we can simply send a 4KB buffer, the maximum 281562306a36Sopenharmony_ci * possible size that firmware can return. 281662306a36Sopenharmony_ci */ 281762306a36Sopenharmony_ci cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem); 281862306a36Sopenharmony_ci 281962306a36Sopenharmony_ci status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count, 282062306a36Sopenharmony_ci ice_aqc_opc_list_func_caps, NULL); 282162306a36Sopenharmony_ci if (!status) 282262306a36Sopenharmony_ci ice_parse_func_caps(hw, func_caps, cbuf, cap_count); 282362306a36Sopenharmony_ci kfree(cbuf); 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci return status; 282662306a36Sopenharmony_ci} 282762306a36Sopenharmony_ci 282862306a36Sopenharmony_ci/** 282962306a36Sopenharmony_ci * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode 283062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 283162306a36Sopenharmony_ci */ 283262306a36Sopenharmony_civoid ice_set_safe_mode_caps(struct ice_hw *hw) 283362306a36Sopenharmony_ci{ 283462306a36Sopenharmony_ci struct ice_hw_func_caps *func_caps = &hw->func_caps; 283562306a36Sopenharmony_ci struct ice_hw_dev_caps *dev_caps = &hw->dev_caps; 283662306a36Sopenharmony_ci struct ice_hw_common_caps cached_caps; 283762306a36Sopenharmony_ci u32 num_funcs; 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci /* cache some func_caps values that should be restored after memset */ 284062306a36Sopenharmony_ci cached_caps = func_caps->common_cap; 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci /* unset func capabilities */ 284362306a36Sopenharmony_ci memset(func_caps, 0, sizeof(*func_caps)); 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci#define ICE_RESTORE_FUNC_CAP(name) \ 284662306a36Sopenharmony_ci func_caps->common_cap.name = cached_caps.name 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci /* restore cached values */ 284962306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(valid_functions); 285062306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(txq_first_id); 285162306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(rxq_first_id); 285262306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(msix_vector_first_id); 285362306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(max_mtu); 285462306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(nvm_unified_update); 285562306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(nvm_update_pending_nvm); 285662306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(nvm_update_pending_orom); 285762306a36Sopenharmony_ci ICE_RESTORE_FUNC_CAP(nvm_update_pending_netlist); 285862306a36Sopenharmony_ci 285962306a36Sopenharmony_ci /* one Tx and one Rx queue in safe mode */ 286062306a36Sopenharmony_ci func_caps->common_cap.num_rxq = 1; 286162306a36Sopenharmony_ci func_caps->common_cap.num_txq = 1; 286262306a36Sopenharmony_ci 286362306a36Sopenharmony_ci /* two MSIX vectors, one for traffic and one for misc causes */ 286462306a36Sopenharmony_ci func_caps->common_cap.num_msix_vectors = 2; 286562306a36Sopenharmony_ci func_caps->guar_num_vsi = 1; 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci /* cache some dev_caps values that should be restored after memset */ 286862306a36Sopenharmony_ci cached_caps = dev_caps->common_cap; 286962306a36Sopenharmony_ci num_funcs = dev_caps->num_funcs; 287062306a36Sopenharmony_ci 287162306a36Sopenharmony_ci /* unset dev capabilities */ 287262306a36Sopenharmony_ci memset(dev_caps, 0, sizeof(*dev_caps)); 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_ci#define ICE_RESTORE_DEV_CAP(name) \ 287562306a36Sopenharmony_ci dev_caps->common_cap.name = cached_caps.name 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci /* restore cached values */ 287862306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(valid_functions); 287962306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(txq_first_id); 288062306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(rxq_first_id); 288162306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(msix_vector_first_id); 288262306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(max_mtu); 288362306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(nvm_unified_update); 288462306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(nvm_update_pending_nvm); 288562306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(nvm_update_pending_orom); 288662306a36Sopenharmony_ci ICE_RESTORE_DEV_CAP(nvm_update_pending_netlist); 288762306a36Sopenharmony_ci dev_caps->num_funcs = num_funcs; 288862306a36Sopenharmony_ci 288962306a36Sopenharmony_ci /* one Tx and one Rx queue per function in safe mode */ 289062306a36Sopenharmony_ci dev_caps->common_cap.num_rxq = num_funcs; 289162306a36Sopenharmony_ci dev_caps->common_cap.num_txq = num_funcs; 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci /* two MSIX vectors per function */ 289462306a36Sopenharmony_ci dev_caps->common_cap.num_msix_vectors = 2 * num_funcs; 289562306a36Sopenharmony_ci} 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci/** 289862306a36Sopenharmony_ci * ice_get_caps - get info about the HW 289962306a36Sopenharmony_ci * @hw: pointer to the hardware structure 290062306a36Sopenharmony_ci */ 290162306a36Sopenharmony_ciint ice_get_caps(struct ice_hw *hw) 290262306a36Sopenharmony_ci{ 290362306a36Sopenharmony_ci int status; 290462306a36Sopenharmony_ci 290562306a36Sopenharmony_ci status = ice_discover_dev_caps(hw, &hw->dev_caps); 290662306a36Sopenharmony_ci if (status) 290762306a36Sopenharmony_ci return status; 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_ci return ice_discover_func_caps(hw, &hw->func_caps); 291062306a36Sopenharmony_ci} 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci/** 291362306a36Sopenharmony_ci * ice_aq_manage_mac_write - manage MAC address write command 291462306a36Sopenharmony_ci * @hw: pointer to the HW struct 291562306a36Sopenharmony_ci * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address 291662306a36Sopenharmony_ci * @flags: flags to control write behavior 291762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 291862306a36Sopenharmony_ci * 291962306a36Sopenharmony_ci * This function is used to write MAC address to the NVM (0x0108). 292062306a36Sopenharmony_ci */ 292162306a36Sopenharmony_ciint 292262306a36Sopenharmony_ciice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags, 292362306a36Sopenharmony_ci struct ice_sq_cd *cd) 292462306a36Sopenharmony_ci{ 292562306a36Sopenharmony_ci struct ice_aqc_manage_mac_write *cmd; 292662306a36Sopenharmony_ci struct ice_aq_desc desc; 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_ci cmd = &desc.params.mac_write; 292962306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write); 293062306a36Sopenharmony_ci 293162306a36Sopenharmony_ci cmd->flags = flags; 293262306a36Sopenharmony_ci ether_addr_copy(cmd->mac_addr, mac_addr); 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 293562306a36Sopenharmony_ci} 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci/** 293862306a36Sopenharmony_ci * ice_aq_clear_pxe_mode 293962306a36Sopenharmony_ci * @hw: pointer to the HW struct 294062306a36Sopenharmony_ci * 294162306a36Sopenharmony_ci * Tell the firmware that the driver is taking over from PXE (0x0110). 294262306a36Sopenharmony_ci */ 294362306a36Sopenharmony_cistatic int ice_aq_clear_pxe_mode(struct ice_hw *hw) 294462306a36Sopenharmony_ci{ 294562306a36Sopenharmony_ci struct ice_aq_desc desc; 294662306a36Sopenharmony_ci 294762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode); 294862306a36Sopenharmony_ci desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT; 294962306a36Sopenharmony_ci 295062306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 295162306a36Sopenharmony_ci} 295262306a36Sopenharmony_ci 295362306a36Sopenharmony_ci/** 295462306a36Sopenharmony_ci * ice_clear_pxe_mode - clear pxe operations mode 295562306a36Sopenharmony_ci * @hw: pointer to the HW struct 295662306a36Sopenharmony_ci * 295762306a36Sopenharmony_ci * Make sure all PXE mode settings are cleared, including things 295862306a36Sopenharmony_ci * like descriptor fetch/write-back mode. 295962306a36Sopenharmony_ci */ 296062306a36Sopenharmony_civoid ice_clear_pxe_mode(struct ice_hw *hw) 296162306a36Sopenharmony_ci{ 296262306a36Sopenharmony_ci if (ice_check_sq_alive(hw, &hw->adminq)) 296362306a36Sopenharmony_ci ice_aq_clear_pxe_mode(hw); 296462306a36Sopenharmony_ci} 296562306a36Sopenharmony_ci 296662306a36Sopenharmony_ci/** 296762306a36Sopenharmony_ci * ice_aq_set_port_params - set physical port parameters. 296862306a36Sopenharmony_ci * @pi: pointer to the port info struct 296962306a36Sopenharmony_ci * @double_vlan: if set double VLAN is enabled 297062306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 297162306a36Sopenharmony_ci * 297262306a36Sopenharmony_ci * Set Physical port parameters (0x0203) 297362306a36Sopenharmony_ci */ 297462306a36Sopenharmony_ciint 297562306a36Sopenharmony_ciice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan, 297662306a36Sopenharmony_ci struct ice_sq_cd *cd) 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_ci{ 297962306a36Sopenharmony_ci struct ice_aqc_set_port_params *cmd; 298062306a36Sopenharmony_ci struct ice_hw *hw = pi->hw; 298162306a36Sopenharmony_ci struct ice_aq_desc desc; 298262306a36Sopenharmony_ci u16 cmd_flags = 0; 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci cmd = &desc.params.set_port_params; 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params); 298762306a36Sopenharmony_ci if (double_vlan) 298862306a36Sopenharmony_ci cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA; 298962306a36Sopenharmony_ci cmd->cmd_flags = cpu_to_le16(cmd_flags); 299062306a36Sopenharmony_ci 299162306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 299262306a36Sopenharmony_ci} 299362306a36Sopenharmony_ci 299462306a36Sopenharmony_ci/** 299562306a36Sopenharmony_ci * ice_is_100m_speed_supported 299662306a36Sopenharmony_ci * @hw: pointer to the HW struct 299762306a36Sopenharmony_ci * 299862306a36Sopenharmony_ci * returns true if 100M speeds are supported by the device, 299962306a36Sopenharmony_ci * false otherwise. 300062306a36Sopenharmony_ci */ 300162306a36Sopenharmony_cibool ice_is_100m_speed_supported(struct ice_hw *hw) 300262306a36Sopenharmony_ci{ 300362306a36Sopenharmony_ci switch (hw->device_id) { 300462306a36Sopenharmony_ci case ICE_DEV_ID_E822C_SGMII: 300562306a36Sopenharmony_ci case ICE_DEV_ID_E822L_SGMII: 300662306a36Sopenharmony_ci case ICE_DEV_ID_E823L_1GBE: 300762306a36Sopenharmony_ci case ICE_DEV_ID_E823C_SGMII: 300862306a36Sopenharmony_ci return true; 300962306a36Sopenharmony_ci default: 301062306a36Sopenharmony_ci return false; 301162306a36Sopenharmony_ci } 301262306a36Sopenharmony_ci} 301362306a36Sopenharmony_ci 301462306a36Sopenharmony_ci/** 301562306a36Sopenharmony_ci * ice_get_link_speed_based_on_phy_type - returns link speed 301662306a36Sopenharmony_ci * @phy_type_low: lower part of phy_type 301762306a36Sopenharmony_ci * @phy_type_high: higher part of phy_type 301862306a36Sopenharmony_ci * 301962306a36Sopenharmony_ci * This helper function will convert an entry in PHY type structure 302062306a36Sopenharmony_ci * [phy_type_low, phy_type_high] to its corresponding link speed. 302162306a36Sopenharmony_ci * Note: In the structure of [phy_type_low, phy_type_high], there should 302262306a36Sopenharmony_ci * be one bit set, as this function will convert one PHY type to its 302362306a36Sopenharmony_ci * speed. 302462306a36Sopenharmony_ci * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned 302562306a36Sopenharmony_ci * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned 302662306a36Sopenharmony_ci */ 302762306a36Sopenharmony_cistatic u16 302862306a36Sopenharmony_ciice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) 302962306a36Sopenharmony_ci{ 303062306a36Sopenharmony_ci u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; 303162306a36Sopenharmony_ci u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; 303262306a36Sopenharmony_ci 303362306a36Sopenharmony_ci switch (phy_type_low) { 303462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100BASE_TX: 303562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100M_SGMII: 303662306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB; 303762306a36Sopenharmony_ci break; 303862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_T: 303962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_SX: 304062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_LX: 304162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1000BASE_KX: 304262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_1G_SGMII: 304362306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB; 304462306a36Sopenharmony_ci break; 304562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_2500BASE_T: 304662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_2500BASE_X: 304762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_2500BASE_KX: 304862306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB; 304962306a36Sopenharmony_ci break; 305062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_5GBASE_T: 305162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_5GBASE_KR: 305262306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB; 305362306a36Sopenharmony_ci break; 305462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_T: 305562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10G_SFI_DA: 305662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_SR: 305762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_LR: 305862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 305962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC: 306062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 306162306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB; 306262306a36Sopenharmony_ci break; 306362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_T: 306462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_CR: 306562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 306662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_CR1: 306762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_SR: 306862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_LR: 306962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_KR: 307062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 307162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25GBASE_KR1: 307262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC: 307362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 307462306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB; 307562306a36Sopenharmony_ci break; 307662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_CR4: 307762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_SR4: 307862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_LR4: 307962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40GBASE_KR4: 308062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC: 308162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_40G_XLAUI: 308262306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB; 308362306a36Sopenharmony_ci break; 308462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_CR2: 308562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_SR2: 308662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_LR2: 308762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_KR2: 308862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: 308962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_LAUI2: 309062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: 309162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI2: 309262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_CP: 309362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_SR: 309462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_FR: 309562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_LR: 309662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 309762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: 309862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_50G_AUI1: 309962306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB; 310062306a36Sopenharmony_ci break; 310162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_CR4: 310262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_SR4: 310362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_LR4: 310462306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_KR4: 310562306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: 310662306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_CAUI4: 310762306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: 310862306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100G_AUI4: 310962306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 311062306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 311162306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_CP2: 311262306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_SR2: 311362306a36Sopenharmony_ci case ICE_PHY_TYPE_LOW_100GBASE_DR: 311462306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB; 311562306a36Sopenharmony_ci break; 311662306a36Sopenharmony_ci default: 311762306a36Sopenharmony_ci speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; 311862306a36Sopenharmony_ci break; 311962306a36Sopenharmony_ci } 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci switch (phy_type_high) { 312262306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 312362306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: 312462306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_CAUI2: 312562306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: 312662306a36Sopenharmony_ci case ICE_PHY_TYPE_HIGH_100G_AUI2: 312762306a36Sopenharmony_ci speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB; 312862306a36Sopenharmony_ci break; 312962306a36Sopenharmony_ci default: 313062306a36Sopenharmony_ci speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; 313162306a36Sopenharmony_ci break; 313262306a36Sopenharmony_ci } 313362306a36Sopenharmony_ci 313462306a36Sopenharmony_ci if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN && 313562306a36Sopenharmony_ci speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN) 313662306a36Sopenharmony_ci return ICE_AQ_LINK_SPEED_UNKNOWN; 313762306a36Sopenharmony_ci else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN && 313862306a36Sopenharmony_ci speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN) 313962306a36Sopenharmony_ci return ICE_AQ_LINK_SPEED_UNKNOWN; 314062306a36Sopenharmony_ci else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN && 314162306a36Sopenharmony_ci speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN) 314262306a36Sopenharmony_ci return speed_phy_type_low; 314362306a36Sopenharmony_ci else 314462306a36Sopenharmony_ci return speed_phy_type_high; 314562306a36Sopenharmony_ci} 314662306a36Sopenharmony_ci 314762306a36Sopenharmony_ci/** 314862306a36Sopenharmony_ci * ice_update_phy_type 314962306a36Sopenharmony_ci * @phy_type_low: pointer to the lower part of phy_type 315062306a36Sopenharmony_ci * @phy_type_high: pointer to the higher part of phy_type 315162306a36Sopenharmony_ci * @link_speeds_bitmap: targeted link speeds bitmap 315262306a36Sopenharmony_ci * 315362306a36Sopenharmony_ci * Note: For the link_speeds_bitmap structure, you can check it at 315462306a36Sopenharmony_ci * [ice_aqc_get_link_status->link_speed]. Caller can pass in 315562306a36Sopenharmony_ci * link_speeds_bitmap include multiple speeds. 315662306a36Sopenharmony_ci * 315762306a36Sopenharmony_ci * Each entry in this [phy_type_low, phy_type_high] structure will 315862306a36Sopenharmony_ci * present a certain link speed. This helper function will turn on bits 315962306a36Sopenharmony_ci * in [phy_type_low, phy_type_high] structure based on the value of 316062306a36Sopenharmony_ci * link_speeds_bitmap input parameter. 316162306a36Sopenharmony_ci */ 316262306a36Sopenharmony_civoid 316362306a36Sopenharmony_ciice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, 316462306a36Sopenharmony_ci u16 link_speeds_bitmap) 316562306a36Sopenharmony_ci{ 316662306a36Sopenharmony_ci u64 pt_high; 316762306a36Sopenharmony_ci u64 pt_low; 316862306a36Sopenharmony_ci int index; 316962306a36Sopenharmony_ci u16 speed; 317062306a36Sopenharmony_ci 317162306a36Sopenharmony_ci /* We first check with low part of phy_type */ 317262306a36Sopenharmony_ci for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) { 317362306a36Sopenharmony_ci pt_low = BIT_ULL(index); 317462306a36Sopenharmony_ci speed = ice_get_link_speed_based_on_phy_type(pt_low, 0); 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci if (link_speeds_bitmap & speed) 317762306a36Sopenharmony_ci *phy_type_low |= BIT_ULL(index); 317862306a36Sopenharmony_ci } 317962306a36Sopenharmony_ci 318062306a36Sopenharmony_ci /* We then check with high part of phy_type */ 318162306a36Sopenharmony_ci for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) { 318262306a36Sopenharmony_ci pt_high = BIT_ULL(index); 318362306a36Sopenharmony_ci speed = ice_get_link_speed_based_on_phy_type(0, pt_high); 318462306a36Sopenharmony_ci 318562306a36Sopenharmony_ci if (link_speeds_bitmap & speed) 318662306a36Sopenharmony_ci *phy_type_high |= BIT_ULL(index); 318762306a36Sopenharmony_ci } 318862306a36Sopenharmony_ci} 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_ci/** 319162306a36Sopenharmony_ci * ice_aq_set_phy_cfg 319262306a36Sopenharmony_ci * @hw: pointer to the HW struct 319362306a36Sopenharmony_ci * @pi: port info structure of the interested logical port 319462306a36Sopenharmony_ci * @cfg: structure with PHY configuration data to be set 319562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 319662306a36Sopenharmony_ci * 319762306a36Sopenharmony_ci * Set the various PHY configuration parameters supported on the Port. 319862306a36Sopenharmony_ci * One or more of the Set PHY config parameters may be ignored in an MFP 319962306a36Sopenharmony_ci * mode as the PF may not have the privilege to set some of the PHY Config 320062306a36Sopenharmony_ci * parameters. This status will be indicated by the command response (0x0601). 320162306a36Sopenharmony_ci */ 320262306a36Sopenharmony_ciint 320362306a36Sopenharmony_ciice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi, 320462306a36Sopenharmony_ci struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd) 320562306a36Sopenharmony_ci{ 320662306a36Sopenharmony_ci struct ice_aq_desc desc; 320762306a36Sopenharmony_ci int status; 320862306a36Sopenharmony_ci 320962306a36Sopenharmony_ci if (!cfg) 321062306a36Sopenharmony_ci return -EINVAL; 321162306a36Sopenharmony_ci 321262306a36Sopenharmony_ci /* Ensure that only valid bits of cfg->caps can be turned on. */ 321362306a36Sopenharmony_ci if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) { 321462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n", 321562306a36Sopenharmony_ci cfg->caps); 321662306a36Sopenharmony_ci 321762306a36Sopenharmony_ci cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK; 321862306a36Sopenharmony_ci } 321962306a36Sopenharmony_ci 322062306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg); 322162306a36Sopenharmony_ci desc.params.set_phy.lport_num = pi->lport; 322262306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 322362306a36Sopenharmony_ci 322462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n"); 322562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " phy_type_low = 0x%llx\n", 322662306a36Sopenharmony_ci (unsigned long long)le64_to_cpu(cfg->phy_type_low)); 322762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " phy_type_high = 0x%llx\n", 322862306a36Sopenharmony_ci (unsigned long long)le64_to_cpu(cfg->phy_type_high)); 322962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " caps = 0x%x\n", cfg->caps); 323062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " low_power_ctrl_an = 0x%x\n", 323162306a36Sopenharmony_ci cfg->low_power_ctrl_an); 323262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " eee_cap = 0x%x\n", cfg->eee_cap); 323362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " eeer_value = 0x%x\n", cfg->eeer_value); 323462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_LINK, " link_fec_opt = 0x%x\n", 323562306a36Sopenharmony_ci cfg->link_fec_opt); 323662306a36Sopenharmony_ci 323762306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd); 323862306a36Sopenharmony_ci if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE) 323962306a36Sopenharmony_ci status = 0; 324062306a36Sopenharmony_ci 324162306a36Sopenharmony_ci if (!status) 324262306a36Sopenharmony_ci pi->phy.curr_user_phy_cfg = *cfg; 324362306a36Sopenharmony_ci 324462306a36Sopenharmony_ci return status; 324562306a36Sopenharmony_ci} 324662306a36Sopenharmony_ci 324762306a36Sopenharmony_ci/** 324862306a36Sopenharmony_ci * ice_update_link_info - update status of the HW network link 324962306a36Sopenharmony_ci * @pi: port info structure of the interested logical port 325062306a36Sopenharmony_ci */ 325162306a36Sopenharmony_ciint ice_update_link_info(struct ice_port_info *pi) 325262306a36Sopenharmony_ci{ 325362306a36Sopenharmony_ci struct ice_link_status *li; 325462306a36Sopenharmony_ci int status; 325562306a36Sopenharmony_ci 325662306a36Sopenharmony_ci if (!pi) 325762306a36Sopenharmony_ci return -EINVAL; 325862306a36Sopenharmony_ci 325962306a36Sopenharmony_ci li = &pi->phy.link_info; 326062306a36Sopenharmony_ci 326162306a36Sopenharmony_ci status = ice_aq_get_link_info(pi, true, NULL, NULL); 326262306a36Sopenharmony_ci if (status) 326362306a36Sopenharmony_ci return status; 326462306a36Sopenharmony_ci 326562306a36Sopenharmony_ci if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) { 326662306a36Sopenharmony_ci struct ice_aqc_get_phy_caps_data *pcaps; 326762306a36Sopenharmony_ci struct ice_hw *hw; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci hw = pi->hw; 327062306a36Sopenharmony_ci pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), 327162306a36Sopenharmony_ci GFP_KERNEL); 327262306a36Sopenharmony_ci if (!pcaps) 327362306a36Sopenharmony_ci return -ENOMEM; 327462306a36Sopenharmony_ci 327562306a36Sopenharmony_ci status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA, 327662306a36Sopenharmony_ci pcaps, NULL); 327762306a36Sopenharmony_ci 327862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), pcaps); 327962306a36Sopenharmony_ci } 328062306a36Sopenharmony_ci 328162306a36Sopenharmony_ci return status; 328262306a36Sopenharmony_ci} 328362306a36Sopenharmony_ci 328462306a36Sopenharmony_ci/** 328562306a36Sopenharmony_ci * ice_cache_phy_user_req 328662306a36Sopenharmony_ci * @pi: port information structure 328762306a36Sopenharmony_ci * @cache_data: PHY logging data 328862306a36Sopenharmony_ci * @cache_mode: PHY logging mode 328962306a36Sopenharmony_ci * 329062306a36Sopenharmony_ci * Log the user request on (FC, FEC, SPEED) for later use. 329162306a36Sopenharmony_ci */ 329262306a36Sopenharmony_cistatic void 329362306a36Sopenharmony_ciice_cache_phy_user_req(struct ice_port_info *pi, 329462306a36Sopenharmony_ci struct ice_phy_cache_mode_data cache_data, 329562306a36Sopenharmony_ci enum ice_phy_cache_mode cache_mode) 329662306a36Sopenharmony_ci{ 329762306a36Sopenharmony_ci if (!pi) 329862306a36Sopenharmony_ci return; 329962306a36Sopenharmony_ci 330062306a36Sopenharmony_ci switch (cache_mode) { 330162306a36Sopenharmony_ci case ICE_FC_MODE: 330262306a36Sopenharmony_ci pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req; 330362306a36Sopenharmony_ci break; 330462306a36Sopenharmony_ci case ICE_SPEED_MODE: 330562306a36Sopenharmony_ci pi->phy.curr_user_speed_req = 330662306a36Sopenharmony_ci cache_data.data.curr_user_speed_req; 330762306a36Sopenharmony_ci break; 330862306a36Sopenharmony_ci case ICE_FEC_MODE: 330962306a36Sopenharmony_ci pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req; 331062306a36Sopenharmony_ci break; 331162306a36Sopenharmony_ci default: 331262306a36Sopenharmony_ci break; 331362306a36Sopenharmony_ci } 331462306a36Sopenharmony_ci} 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci/** 331762306a36Sopenharmony_ci * ice_caps_to_fc_mode 331862306a36Sopenharmony_ci * @caps: PHY capabilities 331962306a36Sopenharmony_ci * 332062306a36Sopenharmony_ci * Convert PHY FC capabilities to ice FC mode 332162306a36Sopenharmony_ci */ 332262306a36Sopenharmony_cienum ice_fc_mode ice_caps_to_fc_mode(u8 caps) 332362306a36Sopenharmony_ci{ 332462306a36Sopenharmony_ci if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE && 332562306a36Sopenharmony_ci caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 332662306a36Sopenharmony_ci return ICE_FC_FULL; 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) 332962306a36Sopenharmony_ci return ICE_FC_TX_PAUSE; 333062306a36Sopenharmony_ci 333162306a36Sopenharmony_ci if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 333262306a36Sopenharmony_ci return ICE_FC_RX_PAUSE; 333362306a36Sopenharmony_ci 333462306a36Sopenharmony_ci return ICE_FC_NONE; 333562306a36Sopenharmony_ci} 333662306a36Sopenharmony_ci 333762306a36Sopenharmony_ci/** 333862306a36Sopenharmony_ci * ice_caps_to_fec_mode 333962306a36Sopenharmony_ci * @caps: PHY capabilities 334062306a36Sopenharmony_ci * @fec_options: Link FEC options 334162306a36Sopenharmony_ci * 334262306a36Sopenharmony_ci * Convert PHY FEC capabilities to ice FEC mode 334362306a36Sopenharmony_ci */ 334462306a36Sopenharmony_cienum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options) 334562306a36Sopenharmony_ci{ 334662306a36Sopenharmony_ci if (caps & ICE_AQC_PHY_EN_AUTO_FEC) 334762306a36Sopenharmony_ci return ICE_FEC_AUTO; 334862306a36Sopenharmony_ci 334962306a36Sopenharmony_ci if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN | 335062306a36Sopenharmony_ci ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ | 335162306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN | 335262306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_KR_REQ)) 335362306a36Sopenharmony_ci return ICE_FEC_BASER; 335462306a36Sopenharmony_ci 335562306a36Sopenharmony_ci if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ | 335662306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_RS_544_REQ | 335762306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN)) 335862306a36Sopenharmony_ci return ICE_FEC_RS; 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci return ICE_FEC_NONE; 336162306a36Sopenharmony_ci} 336262306a36Sopenharmony_ci 336362306a36Sopenharmony_ci/** 336462306a36Sopenharmony_ci * ice_cfg_phy_fc - Configure PHY FC data based on FC mode 336562306a36Sopenharmony_ci * @pi: port information structure 336662306a36Sopenharmony_ci * @cfg: PHY configuration data to set FC mode 336762306a36Sopenharmony_ci * @req_mode: FC mode to configure 336862306a36Sopenharmony_ci */ 336962306a36Sopenharmony_ciint 337062306a36Sopenharmony_ciice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg, 337162306a36Sopenharmony_ci enum ice_fc_mode req_mode) 337262306a36Sopenharmony_ci{ 337362306a36Sopenharmony_ci struct ice_phy_cache_mode_data cache_data; 337462306a36Sopenharmony_ci u8 pause_mask = 0x0; 337562306a36Sopenharmony_ci 337662306a36Sopenharmony_ci if (!pi || !cfg) 337762306a36Sopenharmony_ci return -EINVAL; 337862306a36Sopenharmony_ci 337962306a36Sopenharmony_ci switch (req_mode) { 338062306a36Sopenharmony_ci case ICE_FC_FULL: 338162306a36Sopenharmony_ci pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE; 338262306a36Sopenharmony_ci pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE; 338362306a36Sopenharmony_ci break; 338462306a36Sopenharmony_ci case ICE_FC_RX_PAUSE: 338562306a36Sopenharmony_ci pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE; 338662306a36Sopenharmony_ci break; 338762306a36Sopenharmony_ci case ICE_FC_TX_PAUSE: 338862306a36Sopenharmony_ci pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE; 338962306a36Sopenharmony_ci break; 339062306a36Sopenharmony_ci default: 339162306a36Sopenharmony_ci break; 339262306a36Sopenharmony_ci } 339362306a36Sopenharmony_ci 339462306a36Sopenharmony_ci /* clear the old pause settings */ 339562306a36Sopenharmony_ci cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE | 339662306a36Sopenharmony_ci ICE_AQC_PHY_EN_RX_LINK_PAUSE); 339762306a36Sopenharmony_ci 339862306a36Sopenharmony_ci /* set the new capabilities */ 339962306a36Sopenharmony_ci cfg->caps |= pause_mask; 340062306a36Sopenharmony_ci 340162306a36Sopenharmony_ci /* Cache user FC request */ 340262306a36Sopenharmony_ci cache_data.data.curr_user_fc_req = req_mode; 340362306a36Sopenharmony_ci ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE); 340462306a36Sopenharmony_ci 340562306a36Sopenharmony_ci return 0; 340662306a36Sopenharmony_ci} 340762306a36Sopenharmony_ci 340862306a36Sopenharmony_ci/** 340962306a36Sopenharmony_ci * ice_set_fc 341062306a36Sopenharmony_ci * @pi: port information structure 341162306a36Sopenharmony_ci * @aq_failures: pointer to status code, specific to ice_set_fc routine 341262306a36Sopenharmony_ci * @ena_auto_link_update: enable automatic link update 341362306a36Sopenharmony_ci * 341462306a36Sopenharmony_ci * Set the requested flow control mode. 341562306a36Sopenharmony_ci */ 341662306a36Sopenharmony_ciint 341762306a36Sopenharmony_ciice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) 341862306a36Sopenharmony_ci{ 341962306a36Sopenharmony_ci struct ice_aqc_set_phy_cfg_data cfg = { 0 }; 342062306a36Sopenharmony_ci struct ice_aqc_get_phy_caps_data *pcaps; 342162306a36Sopenharmony_ci struct ice_hw *hw; 342262306a36Sopenharmony_ci int status; 342362306a36Sopenharmony_ci 342462306a36Sopenharmony_ci if (!pi || !aq_failures) 342562306a36Sopenharmony_ci return -EINVAL; 342662306a36Sopenharmony_ci 342762306a36Sopenharmony_ci *aq_failures = 0; 342862306a36Sopenharmony_ci hw = pi->hw; 342962306a36Sopenharmony_ci 343062306a36Sopenharmony_ci pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL); 343162306a36Sopenharmony_ci if (!pcaps) 343262306a36Sopenharmony_ci return -ENOMEM; 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ci /* Get the current PHY config */ 343562306a36Sopenharmony_ci status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG, 343662306a36Sopenharmony_ci pcaps, NULL); 343762306a36Sopenharmony_ci if (status) { 343862306a36Sopenharmony_ci *aq_failures = ICE_SET_FC_AQ_FAIL_GET; 343962306a36Sopenharmony_ci goto out; 344062306a36Sopenharmony_ci } 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_ci ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg); 344362306a36Sopenharmony_ci 344462306a36Sopenharmony_ci /* Configure the set PHY data */ 344562306a36Sopenharmony_ci status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode); 344662306a36Sopenharmony_ci if (status) 344762306a36Sopenharmony_ci goto out; 344862306a36Sopenharmony_ci 344962306a36Sopenharmony_ci /* If the capabilities have changed, then set the new config */ 345062306a36Sopenharmony_ci if (cfg.caps != pcaps->caps) { 345162306a36Sopenharmony_ci int retry_count, retry_max = 10; 345262306a36Sopenharmony_ci 345362306a36Sopenharmony_ci /* Auto restart link so settings take effect */ 345462306a36Sopenharmony_ci if (ena_auto_link_update) 345562306a36Sopenharmony_ci cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 345662306a36Sopenharmony_ci 345762306a36Sopenharmony_ci status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL); 345862306a36Sopenharmony_ci if (status) { 345962306a36Sopenharmony_ci *aq_failures = ICE_SET_FC_AQ_FAIL_SET; 346062306a36Sopenharmony_ci goto out; 346162306a36Sopenharmony_ci } 346262306a36Sopenharmony_ci 346362306a36Sopenharmony_ci /* Update the link info 346462306a36Sopenharmony_ci * It sometimes takes a really long time for link to 346562306a36Sopenharmony_ci * come back from the atomic reset. Thus, we wait a 346662306a36Sopenharmony_ci * little bit. 346762306a36Sopenharmony_ci */ 346862306a36Sopenharmony_ci for (retry_count = 0; retry_count < retry_max; retry_count++) { 346962306a36Sopenharmony_ci status = ice_update_link_info(pi); 347062306a36Sopenharmony_ci 347162306a36Sopenharmony_ci if (!status) 347262306a36Sopenharmony_ci break; 347362306a36Sopenharmony_ci 347462306a36Sopenharmony_ci mdelay(100); 347562306a36Sopenharmony_ci } 347662306a36Sopenharmony_ci 347762306a36Sopenharmony_ci if (status) 347862306a36Sopenharmony_ci *aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE; 347962306a36Sopenharmony_ci } 348062306a36Sopenharmony_ci 348162306a36Sopenharmony_ciout: 348262306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), pcaps); 348362306a36Sopenharmony_ci return status; 348462306a36Sopenharmony_ci} 348562306a36Sopenharmony_ci 348662306a36Sopenharmony_ci/** 348762306a36Sopenharmony_ci * ice_phy_caps_equals_cfg 348862306a36Sopenharmony_ci * @phy_caps: PHY capabilities 348962306a36Sopenharmony_ci * @phy_cfg: PHY configuration 349062306a36Sopenharmony_ci * 349162306a36Sopenharmony_ci * Helper function to determine if PHY capabilities matches PHY 349262306a36Sopenharmony_ci * configuration 349362306a36Sopenharmony_ci */ 349462306a36Sopenharmony_cibool 349562306a36Sopenharmony_ciice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps, 349662306a36Sopenharmony_ci struct ice_aqc_set_phy_cfg_data *phy_cfg) 349762306a36Sopenharmony_ci{ 349862306a36Sopenharmony_ci u8 caps_mask, cfg_mask; 349962306a36Sopenharmony_ci 350062306a36Sopenharmony_ci if (!phy_caps || !phy_cfg) 350162306a36Sopenharmony_ci return false; 350262306a36Sopenharmony_ci 350362306a36Sopenharmony_ci /* These bits are not common between capabilities and configuration. 350462306a36Sopenharmony_ci * Do not use them to determine equality. 350562306a36Sopenharmony_ci */ 350662306a36Sopenharmony_ci caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE | 350762306a36Sopenharmony_ci ICE_AQC_GET_PHY_EN_MOD_QUAL); 350862306a36Sopenharmony_ci cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 350962306a36Sopenharmony_ci 351062306a36Sopenharmony_ci if (phy_caps->phy_type_low != phy_cfg->phy_type_low || 351162306a36Sopenharmony_ci phy_caps->phy_type_high != phy_cfg->phy_type_high || 351262306a36Sopenharmony_ci ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) || 351362306a36Sopenharmony_ci phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an || 351462306a36Sopenharmony_ci phy_caps->eee_cap != phy_cfg->eee_cap || 351562306a36Sopenharmony_ci phy_caps->eeer_value != phy_cfg->eeer_value || 351662306a36Sopenharmony_ci phy_caps->link_fec_options != phy_cfg->link_fec_opt) 351762306a36Sopenharmony_ci return false; 351862306a36Sopenharmony_ci 351962306a36Sopenharmony_ci return true; 352062306a36Sopenharmony_ci} 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci/** 352362306a36Sopenharmony_ci * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data 352462306a36Sopenharmony_ci * @pi: port information structure 352562306a36Sopenharmony_ci * @caps: PHY ability structure to copy date from 352662306a36Sopenharmony_ci * @cfg: PHY configuration structure to copy data to 352762306a36Sopenharmony_ci * 352862306a36Sopenharmony_ci * Helper function to copy AQC PHY get ability data to PHY set configuration 352962306a36Sopenharmony_ci * data structure 353062306a36Sopenharmony_ci */ 353162306a36Sopenharmony_civoid 353262306a36Sopenharmony_ciice_copy_phy_caps_to_cfg(struct ice_port_info *pi, 353362306a36Sopenharmony_ci struct ice_aqc_get_phy_caps_data *caps, 353462306a36Sopenharmony_ci struct ice_aqc_set_phy_cfg_data *cfg) 353562306a36Sopenharmony_ci{ 353662306a36Sopenharmony_ci if (!pi || !caps || !cfg) 353762306a36Sopenharmony_ci return; 353862306a36Sopenharmony_ci 353962306a36Sopenharmony_ci memset(cfg, 0, sizeof(*cfg)); 354062306a36Sopenharmony_ci cfg->phy_type_low = caps->phy_type_low; 354162306a36Sopenharmony_ci cfg->phy_type_high = caps->phy_type_high; 354262306a36Sopenharmony_ci cfg->caps = caps->caps; 354362306a36Sopenharmony_ci cfg->low_power_ctrl_an = caps->low_power_ctrl_an; 354462306a36Sopenharmony_ci cfg->eee_cap = caps->eee_cap; 354562306a36Sopenharmony_ci cfg->eeer_value = caps->eeer_value; 354662306a36Sopenharmony_ci cfg->link_fec_opt = caps->link_fec_options; 354762306a36Sopenharmony_ci cfg->module_compliance_enforcement = 354862306a36Sopenharmony_ci caps->module_compliance_enforcement; 354962306a36Sopenharmony_ci} 355062306a36Sopenharmony_ci 355162306a36Sopenharmony_ci/** 355262306a36Sopenharmony_ci * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode 355362306a36Sopenharmony_ci * @pi: port information structure 355462306a36Sopenharmony_ci * @cfg: PHY configuration data to set FEC mode 355562306a36Sopenharmony_ci * @fec: FEC mode to configure 355662306a36Sopenharmony_ci */ 355762306a36Sopenharmony_ciint 355862306a36Sopenharmony_ciice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg, 355962306a36Sopenharmony_ci enum ice_fec_mode fec) 356062306a36Sopenharmony_ci{ 356162306a36Sopenharmony_ci struct ice_aqc_get_phy_caps_data *pcaps; 356262306a36Sopenharmony_ci struct ice_hw *hw; 356362306a36Sopenharmony_ci int status; 356462306a36Sopenharmony_ci 356562306a36Sopenharmony_ci if (!pi || !cfg) 356662306a36Sopenharmony_ci return -EINVAL; 356762306a36Sopenharmony_ci 356862306a36Sopenharmony_ci hw = pi->hw; 356962306a36Sopenharmony_ci 357062306a36Sopenharmony_ci pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL); 357162306a36Sopenharmony_ci if (!pcaps) 357262306a36Sopenharmony_ci return -ENOMEM; 357362306a36Sopenharmony_ci 357462306a36Sopenharmony_ci status = ice_aq_get_phy_caps(pi, false, 357562306a36Sopenharmony_ci (ice_fw_supports_report_dflt_cfg(hw) ? 357662306a36Sopenharmony_ci ICE_AQC_REPORT_DFLT_CFG : 357762306a36Sopenharmony_ci ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL); 357862306a36Sopenharmony_ci if (status) 357962306a36Sopenharmony_ci goto out; 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ci cfg->caps |= pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC; 358262306a36Sopenharmony_ci cfg->link_fec_opt = pcaps->link_fec_options; 358362306a36Sopenharmony_ci 358462306a36Sopenharmony_ci switch (fec) { 358562306a36Sopenharmony_ci case ICE_FEC_BASER: 358662306a36Sopenharmony_ci /* Clear RS bits, and AND BASE-R ability 358762306a36Sopenharmony_ci * bits and OR request bits. 358862306a36Sopenharmony_ci */ 358962306a36Sopenharmony_ci cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN | 359062306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN; 359162306a36Sopenharmony_ci cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ | 359262306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_KR_REQ; 359362306a36Sopenharmony_ci break; 359462306a36Sopenharmony_ci case ICE_FEC_RS: 359562306a36Sopenharmony_ci /* Clear BASE-R bits, and AND RS ability 359662306a36Sopenharmony_ci * bits and OR request bits. 359762306a36Sopenharmony_ci */ 359862306a36Sopenharmony_ci cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN; 359962306a36Sopenharmony_ci cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ | 360062306a36Sopenharmony_ci ICE_AQC_PHY_FEC_25G_RS_544_REQ; 360162306a36Sopenharmony_ci break; 360262306a36Sopenharmony_ci case ICE_FEC_NONE: 360362306a36Sopenharmony_ci /* Clear all FEC option bits. */ 360462306a36Sopenharmony_ci cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK; 360562306a36Sopenharmony_ci break; 360662306a36Sopenharmony_ci case ICE_FEC_AUTO: 360762306a36Sopenharmony_ci /* AND auto FEC bit, and all caps bits. */ 360862306a36Sopenharmony_ci cfg->caps &= ICE_AQC_PHY_CAPS_MASK; 360962306a36Sopenharmony_ci cfg->link_fec_opt |= pcaps->link_fec_options; 361062306a36Sopenharmony_ci break; 361162306a36Sopenharmony_ci default: 361262306a36Sopenharmony_ci status = -EINVAL; 361362306a36Sopenharmony_ci break; 361462306a36Sopenharmony_ci } 361562306a36Sopenharmony_ci 361662306a36Sopenharmony_ci if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(hw) && 361762306a36Sopenharmony_ci !ice_fw_supports_report_dflt_cfg(hw)) { 361862306a36Sopenharmony_ci struct ice_link_default_override_tlv tlv = { 0 }; 361962306a36Sopenharmony_ci 362062306a36Sopenharmony_ci status = ice_get_link_default_override(&tlv, pi); 362162306a36Sopenharmony_ci if (status) 362262306a36Sopenharmony_ci goto out; 362362306a36Sopenharmony_ci 362462306a36Sopenharmony_ci if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && 362562306a36Sopenharmony_ci (tlv.options & ICE_LINK_OVERRIDE_EN)) 362662306a36Sopenharmony_ci cfg->link_fec_opt = tlv.fec_options; 362762306a36Sopenharmony_ci } 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_ciout: 363062306a36Sopenharmony_ci kfree(pcaps); 363162306a36Sopenharmony_ci 363262306a36Sopenharmony_ci return status; 363362306a36Sopenharmony_ci} 363462306a36Sopenharmony_ci 363562306a36Sopenharmony_ci/** 363662306a36Sopenharmony_ci * ice_get_link_status - get status of the HW network link 363762306a36Sopenharmony_ci * @pi: port information structure 363862306a36Sopenharmony_ci * @link_up: pointer to bool (true/false = linkup/linkdown) 363962306a36Sopenharmony_ci * 364062306a36Sopenharmony_ci * Variable link_up is true if link is up, false if link is down. 364162306a36Sopenharmony_ci * The variable link_up is invalid if status is non zero. As a 364262306a36Sopenharmony_ci * result of this call, link status reporting becomes enabled 364362306a36Sopenharmony_ci */ 364462306a36Sopenharmony_ciint ice_get_link_status(struct ice_port_info *pi, bool *link_up) 364562306a36Sopenharmony_ci{ 364662306a36Sopenharmony_ci struct ice_phy_info *phy_info; 364762306a36Sopenharmony_ci int status = 0; 364862306a36Sopenharmony_ci 364962306a36Sopenharmony_ci if (!pi || !link_up) 365062306a36Sopenharmony_ci return -EINVAL; 365162306a36Sopenharmony_ci 365262306a36Sopenharmony_ci phy_info = &pi->phy; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci if (phy_info->get_link_info) { 365562306a36Sopenharmony_ci status = ice_update_link_info(pi); 365662306a36Sopenharmony_ci 365762306a36Sopenharmony_ci if (status) 365862306a36Sopenharmony_ci ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n", 365962306a36Sopenharmony_ci status); 366062306a36Sopenharmony_ci } 366162306a36Sopenharmony_ci 366262306a36Sopenharmony_ci *link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP; 366362306a36Sopenharmony_ci 366462306a36Sopenharmony_ci return status; 366562306a36Sopenharmony_ci} 366662306a36Sopenharmony_ci 366762306a36Sopenharmony_ci/** 366862306a36Sopenharmony_ci * ice_aq_set_link_restart_an 366962306a36Sopenharmony_ci * @pi: pointer to the port information structure 367062306a36Sopenharmony_ci * @ena_link: if true: enable link, if false: disable link 367162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 367262306a36Sopenharmony_ci * 367362306a36Sopenharmony_ci * Sets up the link and restarts the Auto-Negotiation over the link. 367462306a36Sopenharmony_ci */ 367562306a36Sopenharmony_ciint 367662306a36Sopenharmony_ciice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link, 367762306a36Sopenharmony_ci struct ice_sq_cd *cd) 367862306a36Sopenharmony_ci{ 367962306a36Sopenharmony_ci struct ice_aqc_restart_an *cmd; 368062306a36Sopenharmony_ci struct ice_aq_desc desc; 368162306a36Sopenharmony_ci 368262306a36Sopenharmony_ci cmd = &desc.params.restart_an; 368362306a36Sopenharmony_ci 368462306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an); 368562306a36Sopenharmony_ci 368662306a36Sopenharmony_ci cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART; 368762306a36Sopenharmony_ci cmd->lport_num = pi->lport; 368862306a36Sopenharmony_ci if (ena_link) 368962306a36Sopenharmony_ci cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE; 369062306a36Sopenharmony_ci else 369162306a36Sopenharmony_ci cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE; 369262306a36Sopenharmony_ci 369362306a36Sopenharmony_ci return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd); 369462306a36Sopenharmony_ci} 369562306a36Sopenharmony_ci 369662306a36Sopenharmony_ci/** 369762306a36Sopenharmony_ci * ice_aq_set_event_mask 369862306a36Sopenharmony_ci * @hw: pointer to the HW struct 369962306a36Sopenharmony_ci * @port_num: port number of the physical function 370062306a36Sopenharmony_ci * @mask: event mask to be set 370162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 370262306a36Sopenharmony_ci * 370362306a36Sopenharmony_ci * Set event mask (0x0613) 370462306a36Sopenharmony_ci */ 370562306a36Sopenharmony_ciint 370662306a36Sopenharmony_ciice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask, 370762306a36Sopenharmony_ci struct ice_sq_cd *cd) 370862306a36Sopenharmony_ci{ 370962306a36Sopenharmony_ci struct ice_aqc_set_event_mask *cmd; 371062306a36Sopenharmony_ci struct ice_aq_desc desc; 371162306a36Sopenharmony_ci 371262306a36Sopenharmony_ci cmd = &desc.params.set_event_mask; 371362306a36Sopenharmony_ci 371462306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask); 371562306a36Sopenharmony_ci 371662306a36Sopenharmony_ci cmd->lport_num = port_num; 371762306a36Sopenharmony_ci 371862306a36Sopenharmony_ci cmd->event_mask = cpu_to_le16(mask); 371962306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 372062306a36Sopenharmony_ci} 372162306a36Sopenharmony_ci 372262306a36Sopenharmony_ci/** 372362306a36Sopenharmony_ci * ice_aq_set_mac_loopback 372462306a36Sopenharmony_ci * @hw: pointer to the HW struct 372562306a36Sopenharmony_ci * @ena_lpbk: Enable or Disable loopback 372662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 372762306a36Sopenharmony_ci * 372862306a36Sopenharmony_ci * Enable/disable loopback on a given port 372962306a36Sopenharmony_ci */ 373062306a36Sopenharmony_ciint 373162306a36Sopenharmony_ciice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd) 373262306a36Sopenharmony_ci{ 373362306a36Sopenharmony_ci struct ice_aqc_set_mac_lb *cmd; 373462306a36Sopenharmony_ci struct ice_aq_desc desc; 373562306a36Sopenharmony_ci 373662306a36Sopenharmony_ci cmd = &desc.params.set_mac_lb; 373762306a36Sopenharmony_ci 373862306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb); 373962306a36Sopenharmony_ci if (ena_lpbk) 374062306a36Sopenharmony_ci cmd->lb_mode = ICE_AQ_MAC_LB_EN; 374162306a36Sopenharmony_ci 374262306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 374362306a36Sopenharmony_ci} 374462306a36Sopenharmony_ci 374562306a36Sopenharmony_ci/** 374662306a36Sopenharmony_ci * ice_aq_set_port_id_led 374762306a36Sopenharmony_ci * @pi: pointer to the port information 374862306a36Sopenharmony_ci * @is_orig_mode: is this LED set to original mode (by the net-list) 374962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 375062306a36Sopenharmony_ci * 375162306a36Sopenharmony_ci * Set LED value for the given port (0x06e9) 375262306a36Sopenharmony_ci */ 375362306a36Sopenharmony_ciint 375462306a36Sopenharmony_ciice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode, 375562306a36Sopenharmony_ci struct ice_sq_cd *cd) 375662306a36Sopenharmony_ci{ 375762306a36Sopenharmony_ci struct ice_aqc_set_port_id_led *cmd; 375862306a36Sopenharmony_ci struct ice_hw *hw = pi->hw; 375962306a36Sopenharmony_ci struct ice_aq_desc desc; 376062306a36Sopenharmony_ci 376162306a36Sopenharmony_ci cmd = &desc.params.set_port_id_led; 376262306a36Sopenharmony_ci 376362306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led); 376462306a36Sopenharmony_ci 376562306a36Sopenharmony_ci if (is_orig_mode) 376662306a36Sopenharmony_ci cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG; 376762306a36Sopenharmony_ci else 376862306a36Sopenharmony_ci cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK; 376962306a36Sopenharmony_ci 377062306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 377162306a36Sopenharmony_ci} 377262306a36Sopenharmony_ci 377362306a36Sopenharmony_ci/** 377462306a36Sopenharmony_ci * ice_aq_get_port_options 377562306a36Sopenharmony_ci * @hw: pointer to the HW struct 377662306a36Sopenharmony_ci * @options: buffer for the resultant port options 377762306a36Sopenharmony_ci * @option_count: input - size of the buffer in port options structures, 377862306a36Sopenharmony_ci * output - number of returned port options 377962306a36Sopenharmony_ci * @lport: logical port to call the command with (optional) 378062306a36Sopenharmony_ci * @lport_valid: when false, FW uses port owned by the PF instead of lport, 378162306a36Sopenharmony_ci * when PF owns more than 1 port it must be true 378262306a36Sopenharmony_ci * @active_option_idx: index of active port option in returned buffer 378362306a36Sopenharmony_ci * @active_option_valid: active option in returned buffer is valid 378462306a36Sopenharmony_ci * @pending_option_idx: index of pending port option in returned buffer 378562306a36Sopenharmony_ci * @pending_option_valid: pending option in returned buffer is valid 378662306a36Sopenharmony_ci * 378762306a36Sopenharmony_ci * Calls Get Port Options AQC (0x06ea) and verifies result. 378862306a36Sopenharmony_ci */ 378962306a36Sopenharmony_ciint 379062306a36Sopenharmony_ciice_aq_get_port_options(struct ice_hw *hw, 379162306a36Sopenharmony_ci struct ice_aqc_get_port_options_elem *options, 379262306a36Sopenharmony_ci u8 *option_count, u8 lport, bool lport_valid, 379362306a36Sopenharmony_ci u8 *active_option_idx, bool *active_option_valid, 379462306a36Sopenharmony_ci u8 *pending_option_idx, bool *pending_option_valid) 379562306a36Sopenharmony_ci{ 379662306a36Sopenharmony_ci struct ice_aqc_get_port_options *cmd; 379762306a36Sopenharmony_ci struct ice_aq_desc desc; 379862306a36Sopenharmony_ci int status; 379962306a36Sopenharmony_ci u8 i; 380062306a36Sopenharmony_ci 380162306a36Sopenharmony_ci /* options buffer shall be able to hold max returned options */ 380262306a36Sopenharmony_ci if (*option_count < ICE_AQC_PORT_OPT_COUNT_M) 380362306a36Sopenharmony_ci return -EINVAL; 380462306a36Sopenharmony_ci 380562306a36Sopenharmony_ci cmd = &desc.params.get_port_options; 380662306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options); 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_ci if (lport_valid) 380962306a36Sopenharmony_ci cmd->lport_num = lport; 381062306a36Sopenharmony_ci cmd->lport_num_valid = lport_valid; 381162306a36Sopenharmony_ci 381262306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, options, 381362306a36Sopenharmony_ci *option_count * sizeof(*options), NULL); 381462306a36Sopenharmony_ci if (status) 381562306a36Sopenharmony_ci return status; 381662306a36Sopenharmony_ci 381762306a36Sopenharmony_ci /* verify direct FW response & set output parameters */ 381862306a36Sopenharmony_ci *option_count = FIELD_GET(ICE_AQC_PORT_OPT_COUNT_M, 381962306a36Sopenharmony_ci cmd->port_options_count); 382062306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count); 382162306a36Sopenharmony_ci *active_option_valid = FIELD_GET(ICE_AQC_PORT_OPT_VALID, 382262306a36Sopenharmony_ci cmd->port_options); 382362306a36Sopenharmony_ci if (*active_option_valid) { 382462306a36Sopenharmony_ci *active_option_idx = FIELD_GET(ICE_AQC_PORT_OPT_ACTIVE_M, 382562306a36Sopenharmony_ci cmd->port_options); 382662306a36Sopenharmony_ci if (*active_option_idx > (*option_count - 1)) 382762306a36Sopenharmony_ci return -EIO; 382862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n", 382962306a36Sopenharmony_ci *active_option_idx); 383062306a36Sopenharmony_ci } 383162306a36Sopenharmony_ci 383262306a36Sopenharmony_ci *pending_option_valid = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_VALID, 383362306a36Sopenharmony_ci cmd->pending_port_option_status); 383462306a36Sopenharmony_ci if (*pending_option_valid) { 383562306a36Sopenharmony_ci *pending_option_idx = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_IDX_M, 383662306a36Sopenharmony_ci cmd->pending_port_option_status); 383762306a36Sopenharmony_ci if (*pending_option_idx > (*option_count - 1)) 383862306a36Sopenharmony_ci return -EIO; 383962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n", 384062306a36Sopenharmony_ci *pending_option_idx); 384162306a36Sopenharmony_ci } 384262306a36Sopenharmony_ci 384362306a36Sopenharmony_ci /* mask output options fields */ 384462306a36Sopenharmony_ci for (i = 0; i < *option_count; i++) { 384562306a36Sopenharmony_ci options[i].pmd = FIELD_GET(ICE_AQC_PORT_OPT_PMD_COUNT_M, 384662306a36Sopenharmony_ci options[i].pmd); 384762306a36Sopenharmony_ci options[i].max_lane_speed = FIELD_GET(ICE_AQC_PORT_OPT_MAX_LANE_M, 384862306a36Sopenharmony_ci options[i].max_lane_speed); 384962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n", 385062306a36Sopenharmony_ci options[i].pmd, options[i].max_lane_speed); 385162306a36Sopenharmony_ci } 385262306a36Sopenharmony_ci 385362306a36Sopenharmony_ci return 0; 385462306a36Sopenharmony_ci} 385562306a36Sopenharmony_ci 385662306a36Sopenharmony_ci/** 385762306a36Sopenharmony_ci * ice_aq_set_port_option 385862306a36Sopenharmony_ci * @hw: pointer to the HW struct 385962306a36Sopenharmony_ci * @lport: logical port to call the command with 386062306a36Sopenharmony_ci * @lport_valid: when false, FW uses port owned by the PF instead of lport, 386162306a36Sopenharmony_ci * when PF owns more than 1 port it must be true 386262306a36Sopenharmony_ci * @new_option: new port option to be written 386362306a36Sopenharmony_ci * 386462306a36Sopenharmony_ci * Calls Set Port Options AQC (0x06eb). 386562306a36Sopenharmony_ci */ 386662306a36Sopenharmony_ciint 386762306a36Sopenharmony_ciice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid, 386862306a36Sopenharmony_ci u8 new_option) 386962306a36Sopenharmony_ci{ 387062306a36Sopenharmony_ci struct ice_aqc_set_port_option *cmd; 387162306a36Sopenharmony_ci struct ice_aq_desc desc; 387262306a36Sopenharmony_ci 387362306a36Sopenharmony_ci if (new_option > ICE_AQC_PORT_OPT_COUNT_M) 387462306a36Sopenharmony_ci return -EINVAL; 387562306a36Sopenharmony_ci 387662306a36Sopenharmony_ci cmd = &desc.params.set_port_option; 387762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option); 387862306a36Sopenharmony_ci 387962306a36Sopenharmony_ci if (lport_valid) 388062306a36Sopenharmony_ci cmd->lport_num = lport; 388162306a36Sopenharmony_ci 388262306a36Sopenharmony_ci cmd->lport_num_valid = lport_valid; 388362306a36Sopenharmony_ci cmd->selected_port_option = new_option; 388462306a36Sopenharmony_ci 388562306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 388662306a36Sopenharmony_ci} 388762306a36Sopenharmony_ci 388862306a36Sopenharmony_ci/** 388962306a36Sopenharmony_ci * ice_aq_sff_eeprom 389062306a36Sopenharmony_ci * @hw: pointer to the HW struct 389162306a36Sopenharmony_ci * @lport: bits [7:0] = logical port, bit [8] = logical port valid 389262306a36Sopenharmony_ci * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default) 389362306a36Sopenharmony_ci * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding. 389462306a36Sopenharmony_ci * @page: QSFP page 389562306a36Sopenharmony_ci * @set_page: set or ignore the page 389662306a36Sopenharmony_ci * @data: pointer to data buffer to be read/written to the I2C device. 389762306a36Sopenharmony_ci * @length: 1-16 for read, 1 for write. 389862306a36Sopenharmony_ci * @write: 0 read, 1 for write. 389962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 390062306a36Sopenharmony_ci * 390162306a36Sopenharmony_ci * Read/Write SFF EEPROM (0x06EE) 390262306a36Sopenharmony_ci */ 390362306a36Sopenharmony_ciint 390462306a36Sopenharmony_ciice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr, 390562306a36Sopenharmony_ci u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length, 390662306a36Sopenharmony_ci bool write, struct ice_sq_cd *cd) 390762306a36Sopenharmony_ci{ 390862306a36Sopenharmony_ci struct ice_aqc_sff_eeprom *cmd; 390962306a36Sopenharmony_ci struct ice_aq_desc desc; 391062306a36Sopenharmony_ci int status; 391162306a36Sopenharmony_ci 391262306a36Sopenharmony_ci if (!data || (mem_addr & 0xff00)) 391362306a36Sopenharmony_ci return -EINVAL; 391462306a36Sopenharmony_ci 391562306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom); 391662306a36Sopenharmony_ci cmd = &desc.params.read_write_sff_param; 391762306a36Sopenharmony_ci desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD); 391862306a36Sopenharmony_ci cmd->lport_num = (u8)(lport & 0xff); 391962306a36Sopenharmony_ci cmd->lport_num_valid = (u8)((lport >> 8) & 0x01); 392062306a36Sopenharmony_ci cmd->i2c_bus_addr = cpu_to_le16(((bus_addr >> 1) & 392162306a36Sopenharmony_ci ICE_AQC_SFF_I2CBUS_7BIT_M) | 392262306a36Sopenharmony_ci ((set_page << 392362306a36Sopenharmony_ci ICE_AQC_SFF_SET_EEPROM_PAGE_S) & 392462306a36Sopenharmony_ci ICE_AQC_SFF_SET_EEPROM_PAGE_M)); 392562306a36Sopenharmony_ci cmd->i2c_mem_addr = cpu_to_le16(mem_addr & 0xff); 392662306a36Sopenharmony_ci cmd->eeprom_page = cpu_to_le16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S); 392762306a36Sopenharmony_ci if (write) 392862306a36Sopenharmony_ci cmd->i2c_bus_addr |= cpu_to_le16(ICE_AQC_SFF_IS_WRITE); 392962306a36Sopenharmony_ci 393062306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, data, length, cd); 393162306a36Sopenharmony_ci return status; 393262306a36Sopenharmony_ci} 393362306a36Sopenharmony_ci 393462306a36Sopenharmony_cistatic enum ice_lut_size ice_lut_type_to_size(enum ice_lut_type type) 393562306a36Sopenharmony_ci{ 393662306a36Sopenharmony_ci switch (type) { 393762306a36Sopenharmony_ci case ICE_LUT_VSI: 393862306a36Sopenharmony_ci return ICE_LUT_VSI_SIZE; 393962306a36Sopenharmony_ci case ICE_LUT_GLOBAL: 394062306a36Sopenharmony_ci return ICE_LUT_GLOBAL_SIZE; 394162306a36Sopenharmony_ci case ICE_LUT_PF: 394262306a36Sopenharmony_ci return ICE_LUT_PF_SIZE; 394362306a36Sopenharmony_ci } 394462306a36Sopenharmony_ci WARN_ONCE(1, "incorrect type passed"); 394562306a36Sopenharmony_ci return ICE_LUT_VSI_SIZE; 394662306a36Sopenharmony_ci} 394762306a36Sopenharmony_ci 394862306a36Sopenharmony_cistatic enum ice_aqc_lut_flags ice_lut_size_to_flag(enum ice_lut_size size) 394962306a36Sopenharmony_ci{ 395062306a36Sopenharmony_ci switch (size) { 395162306a36Sopenharmony_ci case ICE_LUT_VSI_SIZE: 395262306a36Sopenharmony_ci return ICE_AQC_LUT_SIZE_SMALL; 395362306a36Sopenharmony_ci case ICE_LUT_GLOBAL_SIZE: 395462306a36Sopenharmony_ci return ICE_AQC_LUT_SIZE_512; 395562306a36Sopenharmony_ci case ICE_LUT_PF_SIZE: 395662306a36Sopenharmony_ci return ICE_AQC_LUT_SIZE_2K; 395762306a36Sopenharmony_ci } 395862306a36Sopenharmony_ci WARN_ONCE(1, "incorrect size passed"); 395962306a36Sopenharmony_ci return 0; 396062306a36Sopenharmony_ci} 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci/** 396362306a36Sopenharmony_ci * __ice_aq_get_set_rss_lut 396462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 396562306a36Sopenharmony_ci * @params: RSS LUT parameters 396662306a36Sopenharmony_ci * @set: set true to set the table, false to get the table 396762306a36Sopenharmony_ci * 396862306a36Sopenharmony_ci * Internal function to get (0x0B05) or set (0x0B03) RSS look up table 396962306a36Sopenharmony_ci */ 397062306a36Sopenharmony_cistatic int 397162306a36Sopenharmony_ci__ice_aq_get_set_rss_lut(struct ice_hw *hw, 397262306a36Sopenharmony_ci struct ice_aq_get_set_rss_lut_params *params, bool set) 397362306a36Sopenharmony_ci{ 397462306a36Sopenharmony_ci u16 opcode, vsi_id, vsi_handle = params->vsi_handle, glob_lut_idx = 0; 397562306a36Sopenharmony_ci enum ice_lut_type lut_type = params->lut_type; 397662306a36Sopenharmony_ci struct ice_aqc_get_set_rss_lut *desc_params; 397762306a36Sopenharmony_ci enum ice_aqc_lut_flags flags; 397862306a36Sopenharmony_ci enum ice_lut_size lut_size; 397962306a36Sopenharmony_ci struct ice_aq_desc desc; 398062306a36Sopenharmony_ci u8 *lut = params->lut; 398162306a36Sopenharmony_ci 398262306a36Sopenharmony_ci 398362306a36Sopenharmony_ci if (!lut || !ice_is_vsi_valid(hw, vsi_handle)) 398462306a36Sopenharmony_ci return -EINVAL; 398562306a36Sopenharmony_ci 398662306a36Sopenharmony_ci lut_size = ice_lut_type_to_size(lut_type); 398762306a36Sopenharmony_ci if (lut_size > params->lut_size) 398862306a36Sopenharmony_ci return -EINVAL; 398962306a36Sopenharmony_ci else if (set && lut_size != params->lut_size) 399062306a36Sopenharmony_ci return -EINVAL; 399162306a36Sopenharmony_ci 399262306a36Sopenharmony_ci opcode = set ? ice_aqc_opc_set_rss_lut : ice_aqc_opc_get_rss_lut; 399362306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, opcode); 399462306a36Sopenharmony_ci if (set) 399562306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 399662306a36Sopenharmony_ci 399762306a36Sopenharmony_ci desc_params = &desc.params.get_set_rss_lut; 399862306a36Sopenharmony_ci vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 399962306a36Sopenharmony_ci desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID); 400062306a36Sopenharmony_ci 400162306a36Sopenharmony_ci if (lut_type == ICE_LUT_GLOBAL) 400262306a36Sopenharmony_ci glob_lut_idx = FIELD_PREP(ICE_AQC_LUT_GLOBAL_IDX, 400362306a36Sopenharmony_ci params->global_lut_id); 400462306a36Sopenharmony_ci 400562306a36Sopenharmony_ci flags = lut_type | glob_lut_idx | ice_lut_size_to_flag(lut_size); 400662306a36Sopenharmony_ci desc_params->flags = cpu_to_le16(flags); 400762306a36Sopenharmony_ci 400862306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL); 400962306a36Sopenharmony_ci} 401062306a36Sopenharmony_ci 401162306a36Sopenharmony_ci/** 401262306a36Sopenharmony_ci * ice_aq_get_rss_lut 401362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 401462306a36Sopenharmony_ci * @get_params: RSS LUT parameters used to specify which RSS LUT to get 401562306a36Sopenharmony_ci * 401662306a36Sopenharmony_ci * get the RSS lookup table, PF or VSI type 401762306a36Sopenharmony_ci */ 401862306a36Sopenharmony_ciint 401962306a36Sopenharmony_ciice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params) 402062306a36Sopenharmony_ci{ 402162306a36Sopenharmony_ci return __ice_aq_get_set_rss_lut(hw, get_params, false); 402262306a36Sopenharmony_ci} 402362306a36Sopenharmony_ci 402462306a36Sopenharmony_ci/** 402562306a36Sopenharmony_ci * ice_aq_set_rss_lut 402662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 402762306a36Sopenharmony_ci * @set_params: RSS LUT parameters used to specify how to set the RSS LUT 402862306a36Sopenharmony_ci * 402962306a36Sopenharmony_ci * set the RSS lookup table, PF or VSI type 403062306a36Sopenharmony_ci */ 403162306a36Sopenharmony_ciint 403262306a36Sopenharmony_ciice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params) 403362306a36Sopenharmony_ci{ 403462306a36Sopenharmony_ci return __ice_aq_get_set_rss_lut(hw, set_params, true); 403562306a36Sopenharmony_ci} 403662306a36Sopenharmony_ci 403762306a36Sopenharmony_ci/** 403862306a36Sopenharmony_ci * __ice_aq_get_set_rss_key 403962306a36Sopenharmony_ci * @hw: pointer to the HW struct 404062306a36Sopenharmony_ci * @vsi_id: VSI FW index 404162306a36Sopenharmony_ci * @key: pointer to key info struct 404262306a36Sopenharmony_ci * @set: set true to set the key, false to get the key 404362306a36Sopenharmony_ci * 404462306a36Sopenharmony_ci * get (0x0B04) or set (0x0B02) the RSS key per VSI 404562306a36Sopenharmony_ci */ 404662306a36Sopenharmony_cistatic int 404762306a36Sopenharmony_ci__ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id, 404862306a36Sopenharmony_ci struct ice_aqc_get_set_rss_keys *key, bool set) 404962306a36Sopenharmony_ci{ 405062306a36Sopenharmony_ci struct ice_aqc_get_set_rss_key *desc_params; 405162306a36Sopenharmony_ci u16 key_size = sizeof(*key); 405262306a36Sopenharmony_ci struct ice_aq_desc desc; 405362306a36Sopenharmony_ci 405462306a36Sopenharmony_ci if (set) { 405562306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key); 405662306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 405762306a36Sopenharmony_ci } else { 405862306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key); 405962306a36Sopenharmony_ci } 406062306a36Sopenharmony_ci 406162306a36Sopenharmony_ci desc_params = &desc.params.get_set_rss_key; 406262306a36Sopenharmony_ci desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID); 406362306a36Sopenharmony_ci 406462306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, key, key_size, NULL); 406562306a36Sopenharmony_ci} 406662306a36Sopenharmony_ci 406762306a36Sopenharmony_ci/** 406862306a36Sopenharmony_ci * ice_aq_get_rss_key 406962306a36Sopenharmony_ci * @hw: pointer to the HW struct 407062306a36Sopenharmony_ci * @vsi_handle: software VSI handle 407162306a36Sopenharmony_ci * @key: pointer to key info struct 407262306a36Sopenharmony_ci * 407362306a36Sopenharmony_ci * get the RSS key per VSI 407462306a36Sopenharmony_ci */ 407562306a36Sopenharmony_ciint 407662306a36Sopenharmony_ciice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle, 407762306a36Sopenharmony_ci struct ice_aqc_get_set_rss_keys *key) 407862306a36Sopenharmony_ci{ 407962306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle) || !key) 408062306a36Sopenharmony_ci return -EINVAL; 408162306a36Sopenharmony_ci 408262306a36Sopenharmony_ci return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle), 408362306a36Sopenharmony_ci key, false); 408462306a36Sopenharmony_ci} 408562306a36Sopenharmony_ci 408662306a36Sopenharmony_ci/** 408762306a36Sopenharmony_ci * ice_aq_set_rss_key 408862306a36Sopenharmony_ci * @hw: pointer to the HW struct 408962306a36Sopenharmony_ci * @vsi_handle: software VSI handle 409062306a36Sopenharmony_ci * @keys: pointer to key info struct 409162306a36Sopenharmony_ci * 409262306a36Sopenharmony_ci * set the RSS key per VSI 409362306a36Sopenharmony_ci */ 409462306a36Sopenharmony_ciint 409562306a36Sopenharmony_ciice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle, 409662306a36Sopenharmony_ci struct ice_aqc_get_set_rss_keys *keys) 409762306a36Sopenharmony_ci{ 409862306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle) || !keys) 409962306a36Sopenharmony_ci return -EINVAL; 410062306a36Sopenharmony_ci 410162306a36Sopenharmony_ci return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle), 410262306a36Sopenharmony_ci keys, true); 410362306a36Sopenharmony_ci} 410462306a36Sopenharmony_ci 410562306a36Sopenharmony_ci/** 410662306a36Sopenharmony_ci * ice_aq_add_lan_txq 410762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 410862306a36Sopenharmony_ci * @num_qgrps: Number of added queue groups 410962306a36Sopenharmony_ci * @qg_list: list of queue groups to be added 411062306a36Sopenharmony_ci * @buf_size: size of buffer for indirect command 411162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 411262306a36Sopenharmony_ci * 411362306a36Sopenharmony_ci * Add Tx LAN queue (0x0C30) 411462306a36Sopenharmony_ci * 411562306a36Sopenharmony_ci * NOTE: 411662306a36Sopenharmony_ci * Prior to calling add Tx LAN queue: 411762306a36Sopenharmony_ci * Initialize the following as part of the Tx queue context: 411862306a36Sopenharmony_ci * Completion queue ID if the queue uses Completion queue, Quanta profile, 411962306a36Sopenharmony_ci * Cache profile and Packet shaper profile. 412062306a36Sopenharmony_ci * 412162306a36Sopenharmony_ci * After add Tx LAN queue AQ command is completed: 412262306a36Sopenharmony_ci * Interrupts should be associated with specific queues, 412362306a36Sopenharmony_ci * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue 412462306a36Sopenharmony_ci * flow. 412562306a36Sopenharmony_ci */ 412662306a36Sopenharmony_cistatic int 412762306a36Sopenharmony_ciice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps, 412862306a36Sopenharmony_ci struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size, 412962306a36Sopenharmony_ci struct ice_sq_cd *cd) 413062306a36Sopenharmony_ci{ 413162306a36Sopenharmony_ci struct ice_aqc_add_tx_qgrp *list; 413262306a36Sopenharmony_ci struct ice_aqc_add_txqs *cmd; 413362306a36Sopenharmony_ci struct ice_aq_desc desc; 413462306a36Sopenharmony_ci u16 i, sum_size = 0; 413562306a36Sopenharmony_ci 413662306a36Sopenharmony_ci cmd = &desc.params.add_txqs; 413762306a36Sopenharmony_ci 413862306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs); 413962306a36Sopenharmony_ci 414062306a36Sopenharmony_ci if (!qg_list) 414162306a36Sopenharmony_ci return -EINVAL; 414262306a36Sopenharmony_ci 414362306a36Sopenharmony_ci if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS) 414462306a36Sopenharmony_ci return -EINVAL; 414562306a36Sopenharmony_ci 414662306a36Sopenharmony_ci for (i = 0, list = qg_list; i < num_qgrps; i++) { 414762306a36Sopenharmony_ci sum_size += struct_size(list, txqs, list->num_txqs); 414862306a36Sopenharmony_ci list = (struct ice_aqc_add_tx_qgrp *)(list->txqs + 414962306a36Sopenharmony_ci list->num_txqs); 415062306a36Sopenharmony_ci } 415162306a36Sopenharmony_ci 415262306a36Sopenharmony_ci if (buf_size != sum_size) 415362306a36Sopenharmony_ci return -EINVAL; 415462306a36Sopenharmony_ci 415562306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 415662306a36Sopenharmony_ci 415762306a36Sopenharmony_ci cmd->num_qgrps = num_qgrps; 415862306a36Sopenharmony_ci 415962306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); 416062306a36Sopenharmony_ci} 416162306a36Sopenharmony_ci 416262306a36Sopenharmony_ci/** 416362306a36Sopenharmony_ci * ice_aq_dis_lan_txq 416462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 416562306a36Sopenharmony_ci * @num_qgrps: number of groups in the list 416662306a36Sopenharmony_ci * @qg_list: the list of groups to disable 416762306a36Sopenharmony_ci * @buf_size: the total size of the qg_list buffer in bytes 416862306a36Sopenharmony_ci * @rst_src: if called due to reset, specifies the reset source 416962306a36Sopenharmony_ci * @vmvf_num: the relative VM or VF number that is undergoing the reset 417062306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 417162306a36Sopenharmony_ci * 417262306a36Sopenharmony_ci * Disable LAN Tx queue (0x0C31) 417362306a36Sopenharmony_ci */ 417462306a36Sopenharmony_cistatic int 417562306a36Sopenharmony_ciice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, 417662306a36Sopenharmony_ci struct ice_aqc_dis_txq_item *qg_list, u16 buf_size, 417762306a36Sopenharmony_ci enum ice_disq_rst_src rst_src, u16 vmvf_num, 417862306a36Sopenharmony_ci struct ice_sq_cd *cd) 417962306a36Sopenharmony_ci{ 418062306a36Sopenharmony_ci struct ice_aqc_dis_txq_item *item; 418162306a36Sopenharmony_ci struct ice_aqc_dis_txqs *cmd; 418262306a36Sopenharmony_ci struct ice_aq_desc desc; 418362306a36Sopenharmony_ci u16 i, sz = 0; 418462306a36Sopenharmony_ci int status; 418562306a36Sopenharmony_ci 418662306a36Sopenharmony_ci cmd = &desc.params.dis_txqs; 418762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs); 418862306a36Sopenharmony_ci 418962306a36Sopenharmony_ci /* qg_list can be NULL only in VM/VF reset flow */ 419062306a36Sopenharmony_ci if (!qg_list && !rst_src) 419162306a36Sopenharmony_ci return -EINVAL; 419262306a36Sopenharmony_ci 419362306a36Sopenharmony_ci if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS) 419462306a36Sopenharmony_ci return -EINVAL; 419562306a36Sopenharmony_ci 419662306a36Sopenharmony_ci cmd->num_entries = num_qgrps; 419762306a36Sopenharmony_ci 419862306a36Sopenharmony_ci cmd->vmvf_and_timeout = cpu_to_le16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) & 419962306a36Sopenharmony_ci ICE_AQC_Q_DIS_TIMEOUT_M); 420062306a36Sopenharmony_ci 420162306a36Sopenharmony_ci switch (rst_src) { 420262306a36Sopenharmony_ci case ICE_VM_RESET: 420362306a36Sopenharmony_ci cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET; 420462306a36Sopenharmony_ci cmd->vmvf_and_timeout |= 420562306a36Sopenharmony_ci cpu_to_le16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M); 420662306a36Sopenharmony_ci break; 420762306a36Sopenharmony_ci case ICE_VF_RESET: 420862306a36Sopenharmony_ci cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET; 420962306a36Sopenharmony_ci /* In this case, FW expects vmvf_num to be absolute VF ID */ 421062306a36Sopenharmony_ci cmd->vmvf_and_timeout |= 421162306a36Sopenharmony_ci cpu_to_le16((vmvf_num + hw->func_caps.vf_base_id) & 421262306a36Sopenharmony_ci ICE_AQC_Q_DIS_VMVF_NUM_M); 421362306a36Sopenharmony_ci break; 421462306a36Sopenharmony_ci case ICE_NO_RESET: 421562306a36Sopenharmony_ci default: 421662306a36Sopenharmony_ci break; 421762306a36Sopenharmony_ci } 421862306a36Sopenharmony_ci 421962306a36Sopenharmony_ci /* flush pipe on time out */ 422062306a36Sopenharmony_ci cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE; 422162306a36Sopenharmony_ci /* If no queue group info, we are in a reset flow. Issue the AQ */ 422262306a36Sopenharmony_ci if (!qg_list) 422362306a36Sopenharmony_ci goto do_aq; 422462306a36Sopenharmony_ci 422562306a36Sopenharmony_ci /* set RD bit to indicate that command buffer is provided by the driver 422662306a36Sopenharmony_ci * and it needs to be read by the firmware 422762306a36Sopenharmony_ci */ 422862306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 422962306a36Sopenharmony_ci 423062306a36Sopenharmony_ci for (i = 0, item = qg_list; i < num_qgrps; i++) { 423162306a36Sopenharmony_ci u16 item_size = struct_size(item, q_id, item->num_qs); 423262306a36Sopenharmony_ci 423362306a36Sopenharmony_ci /* If the num of queues is even, add 2 bytes of padding */ 423462306a36Sopenharmony_ci if ((item->num_qs % 2) == 0) 423562306a36Sopenharmony_ci item_size += 2; 423662306a36Sopenharmony_ci 423762306a36Sopenharmony_ci sz += item_size; 423862306a36Sopenharmony_ci 423962306a36Sopenharmony_ci item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size); 424062306a36Sopenharmony_ci } 424162306a36Sopenharmony_ci 424262306a36Sopenharmony_ci if (buf_size != sz) 424362306a36Sopenharmony_ci return -EINVAL; 424462306a36Sopenharmony_ci 424562306a36Sopenharmony_cido_aq: 424662306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); 424762306a36Sopenharmony_ci if (status) { 424862306a36Sopenharmony_ci if (!qg_list) 424962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n", 425062306a36Sopenharmony_ci vmvf_num, hw->adminq.sq_last_status); 425162306a36Sopenharmony_ci else 425262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n", 425362306a36Sopenharmony_ci le16_to_cpu(qg_list[0].q_id[0]), 425462306a36Sopenharmony_ci hw->adminq.sq_last_status); 425562306a36Sopenharmony_ci } 425662306a36Sopenharmony_ci return status; 425762306a36Sopenharmony_ci} 425862306a36Sopenharmony_ci 425962306a36Sopenharmony_ci/** 426062306a36Sopenharmony_ci * ice_aq_cfg_lan_txq 426162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 426262306a36Sopenharmony_ci * @buf: buffer for command 426362306a36Sopenharmony_ci * @buf_size: size of buffer in bytes 426462306a36Sopenharmony_ci * @num_qs: number of queues being configured 426562306a36Sopenharmony_ci * @oldport: origination lport 426662306a36Sopenharmony_ci * @newport: destination lport 426762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 426862306a36Sopenharmony_ci * 426962306a36Sopenharmony_ci * Move/Configure LAN Tx queue (0x0C32) 427062306a36Sopenharmony_ci * 427162306a36Sopenharmony_ci * There is a better AQ command to use for moving nodes, so only coding 427262306a36Sopenharmony_ci * this one for configuring the node. 427362306a36Sopenharmony_ci */ 427462306a36Sopenharmony_ciint 427562306a36Sopenharmony_ciice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, 427662306a36Sopenharmony_ci u16 buf_size, u16 num_qs, u8 oldport, u8 newport, 427762306a36Sopenharmony_ci struct ice_sq_cd *cd) 427862306a36Sopenharmony_ci{ 427962306a36Sopenharmony_ci struct ice_aqc_cfg_txqs *cmd; 428062306a36Sopenharmony_ci struct ice_aq_desc desc; 428162306a36Sopenharmony_ci int status; 428262306a36Sopenharmony_ci 428362306a36Sopenharmony_ci cmd = &desc.params.cfg_txqs; 428462306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_cfg_txqs); 428562306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 428662306a36Sopenharmony_ci 428762306a36Sopenharmony_ci if (!buf) 428862306a36Sopenharmony_ci return -EINVAL; 428962306a36Sopenharmony_ci 429062306a36Sopenharmony_ci cmd->cmd_type = ICE_AQC_Q_CFG_TC_CHNG; 429162306a36Sopenharmony_ci cmd->num_qs = num_qs; 429262306a36Sopenharmony_ci cmd->port_num_chng = (oldport & ICE_AQC_Q_CFG_SRC_PRT_M); 429362306a36Sopenharmony_ci cmd->port_num_chng |= (newport << ICE_AQC_Q_CFG_DST_PRT_S) & 429462306a36Sopenharmony_ci ICE_AQC_Q_CFG_DST_PRT_M; 429562306a36Sopenharmony_ci cmd->time_out = (5 << ICE_AQC_Q_CFG_TIMEOUT_S) & 429662306a36Sopenharmony_ci ICE_AQC_Q_CFG_TIMEOUT_M; 429762306a36Sopenharmony_ci cmd->blocked_cgds = 0; 429862306a36Sopenharmony_ci 429962306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 430062306a36Sopenharmony_ci if (status) 430162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "Failed to reconfigure nodes %d\n", 430262306a36Sopenharmony_ci hw->adminq.sq_last_status); 430362306a36Sopenharmony_ci return status; 430462306a36Sopenharmony_ci} 430562306a36Sopenharmony_ci 430662306a36Sopenharmony_ci/** 430762306a36Sopenharmony_ci * ice_aq_add_rdma_qsets 430862306a36Sopenharmony_ci * @hw: pointer to the hardware structure 430962306a36Sopenharmony_ci * @num_qset_grps: Number of RDMA Qset groups 431062306a36Sopenharmony_ci * @qset_list: list of Qset groups to be added 431162306a36Sopenharmony_ci * @buf_size: size of buffer for indirect command 431262306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 431362306a36Sopenharmony_ci * 431462306a36Sopenharmony_ci * Add Tx RDMA Qsets (0x0C33) 431562306a36Sopenharmony_ci */ 431662306a36Sopenharmony_cistatic int 431762306a36Sopenharmony_ciice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps, 431862306a36Sopenharmony_ci struct ice_aqc_add_rdma_qset_data *qset_list, 431962306a36Sopenharmony_ci u16 buf_size, struct ice_sq_cd *cd) 432062306a36Sopenharmony_ci{ 432162306a36Sopenharmony_ci struct ice_aqc_add_rdma_qset_data *list; 432262306a36Sopenharmony_ci struct ice_aqc_add_rdma_qset *cmd; 432362306a36Sopenharmony_ci struct ice_aq_desc desc; 432462306a36Sopenharmony_ci u16 i, sum_size = 0; 432562306a36Sopenharmony_ci 432662306a36Sopenharmony_ci cmd = &desc.params.add_rdma_qset; 432762306a36Sopenharmony_ci 432862306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_rdma_qset); 432962306a36Sopenharmony_ci 433062306a36Sopenharmony_ci if (num_qset_grps > ICE_LAN_TXQ_MAX_QGRPS) 433162306a36Sopenharmony_ci return -EINVAL; 433262306a36Sopenharmony_ci 433362306a36Sopenharmony_ci for (i = 0, list = qset_list; i < num_qset_grps; i++) { 433462306a36Sopenharmony_ci u16 num_qsets = le16_to_cpu(list->num_qsets); 433562306a36Sopenharmony_ci 433662306a36Sopenharmony_ci sum_size += struct_size(list, rdma_qsets, num_qsets); 433762306a36Sopenharmony_ci list = (struct ice_aqc_add_rdma_qset_data *)(list->rdma_qsets + 433862306a36Sopenharmony_ci num_qsets); 433962306a36Sopenharmony_ci } 434062306a36Sopenharmony_ci 434162306a36Sopenharmony_ci if (buf_size != sum_size) 434262306a36Sopenharmony_ci return -EINVAL; 434362306a36Sopenharmony_ci 434462306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 434562306a36Sopenharmony_ci 434662306a36Sopenharmony_ci cmd->num_qset_grps = num_qset_grps; 434762306a36Sopenharmony_ci 434862306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, qset_list, buf_size, cd); 434962306a36Sopenharmony_ci} 435062306a36Sopenharmony_ci 435162306a36Sopenharmony_ci/* End of FW Admin Queue command wrappers */ 435262306a36Sopenharmony_ci 435362306a36Sopenharmony_ci/** 435462306a36Sopenharmony_ci * ice_write_byte - write a byte to a packed context structure 435562306a36Sopenharmony_ci * @src_ctx: the context structure to read from 435662306a36Sopenharmony_ci * @dest_ctx: the context to be written to 435762306a36Sopenharmony_ci * @ce_info: a description of the struct to be filled 435862306a36Sopenharmony_ci */ 435962306a36Sopenharmony_cistatic void 436062306a36Sopenharmony_ciice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 436162306a36Sopenharmony_ci{ 436262306a36Sopenharmony_ci u8 src_byte, dest_byte, mask; 436362306a36Sopenharmony_ci u8 *from, *dest; 436462306a36Sopenharmony_ci u16 shift_width; 436562306a36Sopenharmony_ci 436662306a36Sopenharmony_ci /* copy from the next struct field */ 436762306a36Sopenharmony_ci from = src_ctx + ce_info->offset; 436862306a36Sopenharmony_ci 436962306a36Sopenharmony_ci /* prepare the bits and mask */ 437062306a36Sopenharmony_ci shift_width = ce_info->lsb % 8; 437162306a36Sopenharmony_ci mask = (u8)(BIT(ce_info->width) - 1); 437262306a36Sopenharmony_ci 437362306a36Sopenharmony_ci src_byte = *from; 437462306a36Sopenharmony_ci src_byte &= mask; 437562306a36Sopenharmony_ci 437662306a36Sopenharmony_ci /* shift to correct alignment */ 437762306a36Sopenharmony_ci mask <<= shift_width; 437862306a36Sopenharmony_ci src_byte <<= shift_width; 437962306a36Sopenharmony_ci 438062306a36Sopenharmony_ci /* get the current bits from the target bit string */ 438162306a36Sopenharmony_ci dest = dest_ctx + (ce_info->lsb / 8); 438262306a36Sopenharmony_ci 438362306a36Sopenharmony_ci memcpy(&dest_byte, dest, sizeof(dest_byte)); 438462306a36Sopenharmony_ci 438562306a36Sopenharmony_ci dest_byte &= ~mask; /* get the bits not changing */ 438662306a36Sopenharmony_ci dest_byte |= src_byte; /* add in the new bits */ 438762306a36Sopenharmony_ci 438862306a36Sopenharmony_ci /* put it all back */ 438962306a36Sopenharmony_ci memcpy(dest, &dest_byte, sizeof(dest_byte)); 439062306a36Sopenharmony_ci} 439162306a36Sopenharmony_ci 439262306a36Sopenharmony_ci/** 439362306a36Sopenharmony_ci * ice_write_word - write a word to a packed context structure 439462306a36Sopenharmony_ci * @src_ctx: the context structure to read from 439562306a36Sopenharmony_ci * @dest_ctx: the context to be written to 439662306a36Sopenharmony_ci * @ce_info: a description of the struct to be filled 439762306a36Sopenharmony_ci */ 439862306a36Sopenharmony_cistatic void 439962306a36Sopenharmony_ciice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 440062306a36Sopenharmony_ci{ 440162306a36Sopenharmony_ci u16 src_word, mask; 440262306a36Sopenharmony_ci __le16 dest_word; 440362306a36Sopenharmony_ci u8 *from, *dest; 440462306a36Sopenharmony_ci u16 shift_width; 440562306a36Sopenharmony_ci 440662306a36Sopenharmony_ci /* copy from the next struct field */ 440762306a36Sopenharmony_ci from = src_ctx + ce_info->offset; 440862306a36Sopenharmony_ci 440962306a36Sopenharmony_ci /* prepare the bits and mask */ 441062306a36Sopenharmony_ci shift_width = ce_info->lsb % 8; 441162306a36Sopenharmony_ci mask = BIT(ce_info->width) - 1; 441262306a36Sopenharmony_ci 441362306a36Sopenharmony_ci /* don't swizzle the bits until after the mask because the mask bits 441462306a36Sopenharmony_ci * will be in a different bit position on big endian machines 441562306a36Sopenharmony_ci */ 441662306a36Sopenharmony_ci src_word = *(u16 *)from; 441762306a36Sopenharmony_ci src_word &= mask; 441862306a36Sopenharmony_ci 441962306a36Sopenharmony_ci /* shift to correct alignment */ 442062306a36Sopenharmony_ci mask <<= shift_width; 442162306a36Sopenharmony_ci src_word <<= shift_width; 442262306a36Sopenharmony_ci 442362306a36Sopenharmony_ci /* get the current bits from the target bit string */ 442462306a36Sopenharmony_ci dest = dest_ctx + (ce_info->lsb / 8); 442562306a36Sopenharmony_ci 442662306a36Sopenharmony_ci memcpy(&dest_word, dest, sizeof(dest_word)); 442762306a36Sopenharmony_ci 442862306a36Sopenharmony_ci dest_word &= ~(cpu_to_le16(mask)); /* get the bits not changing */ 442962306a36Sopenharmony_ci dest_word |= cpu_to_le16(src_word); /* add in the new bits */ 443062306a36Sopenharmony_ci 443162306a36Sopenharmony_ci /* put it all back */ 443262306a36Sopenharmony_ci memcpy(dest, &dest_word, sizeof(dest_word)); 443362306a36Sopenharmony_ci} 443462306a36Sopenharmony_ci 443562306a36Sopenharmony_ci/** 443662306a36Sopenharmony_ci * ice_write_dword - write a dword to a packed context structure 443762306a36Sopenharmony_ci * @src_ctx: the context structure to read from 443862306a36Sopenharmony_ci * @dest_ctx: the context to be written to 443962306a36Sopenharmony_ci * @ce_info: a description of the struct to be filled 444062306a36Sopenharmony_ci */ 444162306a36Sopenharmony_cistatic void 444262306a36Sopenharmony_ciice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 444362306a36Sopenharmony_ci{ 444462306a36Sopenharmony_ci u32 src_dword, mask; 444562306a36Sopenharmony_ci __le32 dest_dword; 444662306a36Sopenharmony_ci u8 *from, *dest; 444762306a36Sopenharmony_ci u16 shift_width; 444862306a36Sopenharmony_ci 444962306a36Sopenharmony_ci /* copy from the next struct field */ 445062306a36Sopenharmony_ci from = src_ctx + ce_info->offset; 445162306a36Sopenharmony_ci 445262306a36Sopenharmony_ci /* prepare the bits and mask */ 445362306a36Sopenharmony_ci shift_width = ce_info->lsb % 8; 445462306a36Sopenharmony_ci 445562306a36Sopenharmony_ci /* if the field width is exactly 32 on an x86 machine, then the shift 445662306a36Sopenharmony_ci * operation will not work because the SHL instructions count is masked 445762306a36Sopenharmony_ci * to 5 bits so the shift will do nothing 445862306a36Sopenharmony_ci */ 445962306a36Sopenharmony_ci if (ce_info->width < 32) 446062306a36Sopenharmony_ci mask = BIT(ce_info->width) - 1; 446162306a36Sopenharmony_ci else 446262306a36Sopenharmony_ci mask = (u32)~0; 446362306a36Sopenharmony_ci 446462306a36Sopenharmony_ci /* don't swizzle the bits until after the mask because the mask bits 446562306a36Sopenharmony_ci * will be in a different bit position on big endian machines 446662306a36Sopenharmony_ci */ 446762306a36Sopenharmony_ci src_dword = *(u32 *)from; 446862306a36Sopenharmony_ci src_dword &= mask; 446962306a36Sopenharmony_ci 447062306a36Sopenharmony_ci /* shift to correct alignment */ 447162306a36Sopenharmony_ci mask <<= shift_width; 447262306a36Sopenharmony_ci src_dword <<= shift_width; 447362306a36Sopenharmony_ci 447462306a36Sopenharmony_ci /* get the current bits from the target bit string */ 447562306a36Sopenharmony_ci dest = dest_ctx + (ce_info->lsb / 8); 447662306a36Sopenharmony_ci 447762306a36Sopenharmony_ci memcpy(&dest_dword, dest, sizeof(dest_dword)); 447862306a36Sopenharmony_ci 447962306a36Sopenharmony_ci dest_dword &= ~(cpu_to_le32(mask)); /* get the bits not changing */ 448062306a36Sopenharmony_ci dest_dword |= cpu_to_le32(src_dword); /* add in the new bits */ 448162306a36Sopenharmony_ci 448262306a36Sopenharmony_ci /* put it all back */ 448362306a36Sopenharmony_ci memcpy(dest, &dest_dword, sizeof(dest_dword)); 448462306a36Sopenharmony_ci} 448562306a36Sopenharmony_ci 448662306a36Sopenharmony_ci/** 448762306a36Sopenharmony_ci * ice_write_qword - write a qword to a packed context structure 448862306a36Sopenharmony_ci * @src_ctx: the context structure to read from 448962306a36Sopenharmony_ci * @dest_ctx: the context to be written to 449062306a36Sopenharmony_ci * @ce_info: a description of the struct to be filled 449162306a36Sopenharmony_ci */ 449262306a36Sopenharmony_cistatic void 449362306a36Sopenharmony_ciice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 449462306a36Sopenharmony_ci{ 449562306a36Sopenharmony_ci u64 src_qword, mask; 449662306a36Sopenharmony_ci __le64 dest_qword; 449762306a36Sopenharmony_ci u8 *from, *dest; 449862306a36Sopenharmony_ci u16 shift_width; 449962306a36Sopenharmony_ci 450062306a36Sopenharmony_ci /* copy from the next struct field */ 450162306a36Sopenharmony_ci from = src_ctx + ce_info->offset; 450262306a36Sopenharmony_ci 450362306a36Sopenharmony_ci /* prepare the bits and mask */ 450462306a36Sopenharmony_ci shift_width = ce_info->lsb % 8; 450562306a36Sopenharmony_ci 450662306a36Sopenharmony_ci /* if the field width is exactly 64 on an x86 machine, then the shift 450762306a36Sopenharmony_ci * operation will not work because the SHL instructions count is masked 450862306a36Sopenharmony_ci * to 6 bits so the shift will do nothing 450962306a36Sopenharmony_ci */ 451062306a36Sopenharmony_ci if (ce_info->width < 64) 451162306a36Sopenharmony_ci mask = BIT_ULL(ce_info->width) - 1; 451262306a36Sopenharmony_ci else 451362306a36Sopenharmony_ci mask = (u64)~0; 451462306a36Sopenharmony_ci 451562306a36Sopenharmony_ci /* don't swizzle the bits until after the mask because the mask bits 451662306a36Sopenharmony_ci * will be in a different bit position on big endian machines 451762306a36Sopenharmony_ci */ 451862306a36Sopenharmony_ci src_qword = *(u64 *)from; 451962306a36Sopenharmony_ci src_qword &= mask; 452062306a36Sopenharmony_ci 452162306a36Sopenharmony_ci /* shift to correct alignment */ 452262306a36Sopenharmony_ci mask <<= shift_width; 452362306a36Sopenharmony_ci src_qword <<= shift_width; 452462306a36Sopenharmony_ci 452562306a36Sopenharmony_ci /* get the current bits from the target bit string */ 452662306a36Sopenharmony_ci dest = dest_ctx + (ce_info->lsb / 8); 452762306a36Sopenharmony_ci 452862306a36Sopenharmony_ci memcpy(&dest_qword, dest, sizeof(dest_qword)); 452962306a36Sopenharmony_ci 453062306a36Sopenharmony_ci dest_qword &= ~(cpu_to_le64(mask)); /* get the bits not changing */ 453162306a36Sopenharmony_ci dest_qword |= cpu_to_le64(src_qword); /* add in the new bits */ 453262306a36Sopenharmony_ci 453362306a36Sopenharmony_ci /* put it all back */ 453462306a36Sopenharmony_ci memcpy(dest, &dest_qword, sizeof(dest_qword)); 453562306a36Sopenharmony_ci} 453662306a36Sopenharmony_ci 453762306a36Sopenharmony_ci/** 453862306a36Sopenharmony_ci * ice_set_ctx - set context bits in packed structure 453962306a36Sopenharmony_ci * @hw: pointer to the hardware structure 454062306a36Sopenharmony_ci * @src_ctx: pointer to a generic non-packed context structure 454162306a36Sopenharmony_ci * @dest_ctx: pointer to memory for the packed structure 454262306a36Sopenharmony_ci * @ce_info: a description of the structure to be transformed 454362306a36Sopenharmony_ci */ 454462306a36Sopenharmony_ciint 454562306a36Sopenharmony_ciice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx, 454662306a36Sopenharmony_ci const struct ice_ctx_ele *ce_info) 454762306a36Sopenharmony_ci{ 454862306a36Sopenharmony_ci int f; 454962306a36Sopenharmony_ci 455062306a36Sopenharmony_ci for (f = 0; ce_info[f].width; f++) { 455162306a36Sopenharmony_ci /* We have to deal with each element of the FW response 455262306a36Sopenharmony_ci * using the correct size so that we are correct regardless 455362306a36Sopenharmony_ci * of the endianness of the machine. 455462306a36Sopenharmony_ci */ 455562306a36Sopenharmony_ci if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) { 455662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n", 455762306a36Sopenharmony_ci f, ce_info[f].width, ce_info[f].size_of); 455862306a36Sopenharmony_ci continue; 455962306a36Sopenharmony_ci } 456062306a36Sopenharmony_ci switch (ce_info[f].size_of) { 456162306a36Sopenharmony_ci case sizeof(u8): 456262306a36Sopenharmony_ci ice_write_byte(src_ctx, dest_ctx, &ce_info[f]); 456362306a36Sopenharmony_ci break; 456462306a36Sopenharmony_ci case sizeof(u16): 456562306a36Sopenharmony_ci ice_write_word(src_ctx, dest_ctx, &ce_info[f]); 456662306a36Sopenharmony_ci break; 456762306a36Sopenharmony_ci case sizeof(u32): 456862306a36Sopenharmony_ci ice_write_dword(src_ctx, dest_ctx, &ce_info[f]); 456962306a36Sopenharmony_ci break; 457062306a36Sopenharmony_ci case sizeof(u64): 457162306a36Sopenharmony_ci ice_write_qword(src_ctx, dest_ctx, &ce_info[f]); 457262306a36Sopenharmony_ci break; 457362306a36Sopenharmony_ci default: 457462306a36Sopenharmony_ci return -EINVAL; 457562306a36Sopenharmony_ci } 457662306a36Sopenharmony_ci } 457762306a36Sopenharmony_ci 457862306a36Sopenharmony_ci return 0; 457962306a36Sopenharmony_ci} 458062306a36Sopenharmony_ci 458162306a36Sopenharmony_ci/** 458262306a36Sopenharmony_ci * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC 458362306a36Sopenharmony_ci * @hw: pointer to the HW struct 458462306a36Sopenharmony_ci * @vsi_handle: software VSI handle 458562306a36Sopenharmony_ci * @tc: TC number 458662306a36Sopenharmony_ci * @q_handle: software queue handle 458762306a36Sopenharmony_ci */ 458862306a36Sopenharmony_cistruct ice_q_ctx * 458962306a36Sopenharmony_ciice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle) 459062306a36Sopenharmony_ci{ 459162306a36Sopenharmony_ci struct ice_vsi_ctx *vsi; 459262306a36Sopenharmony_ci struct ice_q_ctx *q_ctx; 459362306a36Sopenharmony_ci 459462306a36Sopenharmony_ci vsi = ice_get_vsi_ctx(hw, vsi_handle); 459562306a36Sopenharmony_ci if (!vsi) 459662306a36Sopenharmony_ci return NULL; 459762306a36Sopenharmony_ci if (q_handle >= vsi->num_lan_q_entries[tc]) 459862306a36Sopenharmony_ci return NULL; 459962306a36Sopenharmony_ci if (!vsi->lan_q_ctx[tc]) 460062306a36Sopenharmony_ci return NULL; 460162306a36Sopenharmony_ci q_ctx = vsi->lan_q_ctx[tc]; 460262306a36Sopenharmony_ci return &q_ctx[q_handle]; 460362306a36Sopenharmony_ci} 460462306a36Sopenharmony_ci 460562306a36Sopenharmony_ci/** 460662306a36Sopenharmony_ci * ice_ena_vsi_txq 460762306a36Sopenharmony_ci * @pi: port information structure 460862306a36Sopenharmony_ci * @vsi_handle: software VSI handle 460962306a36Sopenharmony_ci * @tc: TC number 461062306a36Sopenharmony_ci * @q_handle: software queue handle 461162306a36Sopenharmony_ci * @num_qgrps: Number of added queue groups 461262306a36Sopenharmony_ci * @buf: list of queue groups to be added 461362306a36Sopenharmony_ci * @buf_size: size of buffer for indirect command 461462306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 461562306a36Sopenharmony_ci * 461662306a36Sopenharmony_ci * This function adds one LAN queue 461762306a36Sopenharmony_ci */ 461862306a36Sopenharmony_ciint 461962306a36Sopenharmony_ciice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle, 462062306a36Sopenharmony_ci u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size, 462162306a36Sopenharmony_ci struct ice_sq_cd *cd) 462262306a36Sopenharmony_ci{ 462362306a36Sopenharmony_ci struct ice_aqc_txsched_elem_data node = { 0 }; 462462306a36Sopenharmony_ci struct ice_sched_node *parent; 462562306a36Sopenharmony_ci struct ice_q_ctx *q_ctx; 462662306a36Sopenharmony_ci struct ice_hw *hw; 462762306a36Sopenharmony_ci int status; 462862306a36Sopenharmony_ci 462962306a36Sopenharmony_ci if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 463062306a36Sopenharmony_ci return -EIO; 463162306a36Sopenharmony_ci 463262306a36Sopenharmony_ci if (num_qgrps > 1 || buf->num_txqs > 1) 463362306a36Sopenharmony_ci return -ENOSPC; 463462306a36Sopenharmony_ci 463562306a36Sopenharmony_ci hw = pi->hw; 463662306a36Sopenharmony_ci 463762306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 463862306a36Sopenharmony_ci return -EINVAL; 463962306a36Sopenharmony_ci 464062306a36Sopenharmony_ci mutex_lock(&pi->sched_lock); 464162306a36Sopenharmony_ci 464262306a36Sopenharmony_ci q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle); 464362306a36Sopenharmony_ci if (!q_ctx) { 464462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n", 464562306a36Sopenharmony_ci q_handle); 464662306a36Sopenharmony_ci status = -EINVAL; 464762306a36Sopenharmony_ci goto ena_txq_exit; 464862306a36Sopenharmony_ci } 464962306a36Sopenharmony_ci 465062306a36Sopenharmony_ci /* find a parent node */ 465162306a36Sopenharmony_ci parent = ice_sched_get_free_qparent(pi, vsi_handle, tc, 465262306a36Sopenharmony_ci ICE_SCHED_NODE_OWNER_LAN); 465362306a36Sopenharmony_ci if (!parent) { 465462306a36Sopenharmony_ci status = -EINVAL; 465562306a36Sopenharmony_ci goto ena_txq_exit; 465662306a36Sopenharmony_ci } 465762306a36Sopenharmony_ci 465862306a36Sopenharmony_ci buf->parent_teid = parent->info.node_teid; 465962306a36Sopenharmony_ci node.parent_teid = parent->info.node_teid; 466062306a36Sopenharmony_ci /* Mark that the values in the "generic" section as valid. The default 466162306a36Sopenharmony_ci * value in the "generic" section is zero. This means that : 466262306a36Sopenharmony_ci * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0. 466362306a36Sopenharmony_ci * - 0 priority among siblings, indicated by Bit 1-3. 466462306a36Sopenharmony_ci * - WFQ, indicated by Bit 4. 466562306a36Sopenharmony_ci * - 0 Adjustment value is used in PSM credit update flow, indicated by 466662306a36Sopenharmony_ci * Bit 5-6. 466762306a36Sopenharmony_ci * - Bit 7 is reserved. 466862306a36Sopenharmony_ci * Without setting the generic section as valid in valid_sections, the 466962306a36Sopenharmony_ci * Admin queue command will fail with error code ICE_AQ_RC_EINVAL. 467062306a36Sopenharmony_ci */ 467162306a36Sopenharmony_ci buf->txqs[0].info.valid_sections = 467262306a36Sopenharmony_ci ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR | 467362306a36Sopenharmony_ci ICE_AQC_ELEM_VALID_EIR; 467462306a36Sopenharmony_ci buf->txqs[0].info.generic = 0; 467562306a36Sopenharmony_ci buf->txqs[0].info.cir_bw.bw_profile_idx = 467662306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID); 467762306a36Sopenharmony_ci buf->txqs[0].info.cir_bw.bw_alloc = 467862306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_BW_WT); 467962306a36Sopenharmony_ci buf->txqs[0].info.eir_bw.bw_profile_idx = 468062306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID); 468162306a36Sopenharmony_ci buf->txqs[0].info.eir_bw.bw_alloc = 468262306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_BW_WT); 468362306a36Sopenharmony_ci 468462306a36Sopenharmony_ci /* add the LAN queue */ 468562306a36Sopenharmony_ci status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd); 468662306a36Sopenharmony_ci if (status) { 468762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n", 468862306a36Sopenharmony_ci le16_to_cpu(buf->txqs[0].txq_id), 468962306a36Sopenharmony_ci hw->adminq.sq_last_status); 469062306a36Sopenharmony_ci goto ena_txq_exit; 469162306a36Sopenharmony_ci } 469262306a36Sopenharmony_ci 469362306a36Sopenharmony_ci node.node_teid = buf->txqs[0].q_teid; 469462306a36Sopenharmony_ci node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF; 469562306a36Sopenharmony_ci q_ctx->q_handle = q_handle; 469662306a36Sopenharmony_ci q_ctx->q_teid = le32_to_cpu(node.node_teid); 469762306a36Sopenharmony_ci 469862306a36Sopenharmony_ci /* add a leaf node into scheduler tree queue layer */ 469962306a36Sopenharmony_ci status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node, NULL); 470062306a36Sopenharmony_ci if (!status) 470162306a36Sopenharmony_ci status = ice_sched_replay_q_bw(pi, q_ctx); 470262306a36Sopenharmony_ci 470362306a36Sopenharmony_ciena_txq_exit: 470462306a36Sopenharmony_ci mutex_unlock(&pi->sched_lock); 470562306a36Sopenharmony_ci return status; 470662306a36Sopenharmony_ci} 470762306a36Sopenharmony_ci 470862306a36Sopenharmony_ci/** 470962306a36Sopenharmony_ci * ice_dis_vsi_txq 471062306a36Sopenharmony_ci * @pi: port information structure 471162306a36Sopenharmony_ci * @vsi_handle: software VSI handle 471262306a36Sopenharmony_ci * @tc: TC number 471362306a36Sopenharmony_ci * @num_queues: number of queues 471462306a36Sopenharmony_ci * @q_handles: pointer to software queue handle array 471562306a36Sopenharmony_ci * @q_ids: pointer to the q_id array 471662306a36Sopenharmony_ci * @q_teids: pointer to queue node teids 471762306a36Sopenharmony_ci * @rst_src: if called due to reset, specifies the reset source 471862306a36Sopenharmony_ci * @vmvf_num: the relative VM or VF number that is undergoing the reset 471962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 472062306a36Sopenharmony_ci * 472162306a36Sopenharmony_ci * This function removes queues and their corresponding nodes in SW DB 472262306a36Sopenharmony_ci */ 472362306a36Sopenharmony_ciint 472462306a36Sopenharmony_ciice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues, 472562306a36Sopenharmony_ci u16 *q_handles, u16 *q_ids, u32 *q_teids, 472662306a36Sopenharmony_ci enum ice_disq_rst_src rst_src, u16 vmvf_num, 472762306a36Sopenharmony_ci struct ice_sq_cd *cd) 472862306a36Sopenharmony_ci{ 472962306a36Sopenharmony_ci struct ice_aqc_dis_txq_item *qg_list; 473062306a36Sopenharmony_ci struct ice_q_ctx *q_ctx; 473162306a36Sopenharmony_ci int status = -ENOENT; 473262306a36Sopenharmony_ci struct ice_hw *hw; 473362306a36Sopenharmony_ci u16 i, buf_size; 473462306a36Sopenharmony_ci 473562306a36Sopenharmony_ci if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 473662306a36Sopenharmony_ci return -EIO; 473762306a36Sopenharmony_ci 473862306a36Sopenharmony_ci hw = pi->hw; 473962306a36Sopenharmony_ci 474062306a36Sopenharmony_ci if (!num_queues) { 474162306a36Sopenharmony_ci /* if queue is disabled already yet the disable queue command 474262306a36Sopenharmony_ci * has to be sent to complete the VF reset, then call 474362306a36Sopenharmony_ci * ice_aq_dis_lan_txq without any queue information 474462306a36Sopenharmony_ci */ 474562306a36Sopenharmony_ci if (rst_src) 474662306a36Sopenharmony_ci return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src, 474762306a36Sopenharmony_ci vmvf_num, NULL); 474862306a36Sopenharmony_ci return -EIO; 474962306a36Sopenharmony_ci } 475062306a36Sopenharmony_ci 475162306a36Sopenharmony_ci buf_size = struct_size(qg_list, q_id, 1); 475262306a36Sopenharmony_ci qg_list = kzalloc(buf_size, GFP_KERNEL); 475362306a36Sopenharmony_ci if (!qg_list) 475462306a36Sopenharmony_ci return -ENOMEM; 475562306a36Sopenharmony_ci 475662306a36Sopenharmony_ci mutex_lock(&pi->sched_lock); 475762306a36Sopenharmony_ci 475862306a36Sopenharmony_ci for (i = 0; i < num_queues; i++) { 475962306a36Sopenharmony_ci struct ice_sched_node *node; 476062306a36Sopenharmony_ci 476162306a36Sopenharmony_ci node = ice_sched_find_node_by_teid(pi->root, q_teids[i]); 476262306a36Sopenharmony_ci if (!node) 476362306a36Sopenharmony_ci continue; 476462306a36Sopenharmony_ci q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]); 476562306a36Sopenharmony_ci if (!q_ctx) { 476662306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n", 476762306a36Sopenharmony_ci q_handles[i]); 476862306a36Sopenharmony_ci continue; 476962306a36Sopenharmony_ci } 477062306a36Sopenharmony_ci if (q_ctx->q_handle != q_handles[i]) { 477162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n", 477262306a36Sopenharmony_ci q_ctx->q_handle, q_handles[i]); 477362306a36Sopenharmony_ci continue; 477462306a36Sopenharmony_ci } 477562306a36Sopenharmony_ci qg_list->parent_teid = node->info.parent_teid; 477662306a36Sopenharmony_ci qg_list->num_qs = 1; 477762306a36Sopenharmony_ci qg_list->q_id[0] = cpu_to_le16(q_ids[i]); 477862306a36Sopenharmony_ci status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src, 477962306a36Sopenharmony_ci vmvf_num, cd); 478062306a36Sopenharmony_ci 478162306a36Sopenharmony_ci if (status) 478262306a36Sopenharmony_ci break; 478362306a36Sopenharmony_ci ice_free_sched_node(pi, node); 478462306a36Sopenharmony_ci q_ctx->q_handle = ICE_INVAL_Q_HANDLE; 478562306a36Sopenharmony_ci q_ctx->q_teid = ICE_INVAL_TEID; 478662306a36Sopenharmony_ci } 478762306a36Sopenharmony_ci mutex_unlock(&pi->sched_lock); 478862306a36Sopenharmony_ci kfree(qg_list); 478962306a36Sopenharmony_ci return status; 479062306a36Sopenharmony_ci} 479162306a36Sopenharmony_ci 479262306a36Sopenharmony_ci/** 479362306a36Sopenharmony_ci * ice_cfg_vsi_qs - configure the new/existing VSI queues 479462306a36Sopenharmony_ci * @pi: port information structure 479562306a36Sopenharmony_ci * @vsi_handle: software VSI handle 479662306a36Sopenharmony_ci * @tc_bitmap: TC bitmap 479762306a36Sopenharmony_ci * @maxqs: max queues array per TC 479862306a36Sopenharmony_ci * @owner: LAN or RDMA 479962306a36Sopenharmony_ci * 480062306a36Sopenharmony_ci * This function adds/updates the VSI queues per TC. 480162306a36Sopenharmony_ci */ 480262306a36Sopenharmony_cistatic int 480362306a36Sopenharmony_ciice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap, 480462306a36Sopenharmony_ci u16 *maxqs, u8 owner) 480562306a36Sopenharmony_ci{ 480662306a36Sopenharmony_ci int status = 0; 480762306a36Sopenharmony_ci u8 i; 480862306a36Sopenharmony_ci 480962306a36Sopenharmony_ci if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 481062306a36Sopenharmony_ci return -EIO; 481162306a36Sopenharmony_ci 481262306a36Sopenharmony_ci if (!ice_is_vsi_valid(pi->hw, vsi_handle)) 481362306a36Sopenharmony_ci return -EINVAL; 481462306a36Sopenharmony_ci 481562306a36Sopenharmony_ci mutex_lock(&pi->sched_lock); 481662306a36Sopenharmony_ci 481762306a36Sopenharmony_ci ice_for_each_traffic_class(i) { 481862306a36Sopenharmony_ci /* configuration is possible only if TC node is present */ 481962306a36Sopenharmony_ci if (!ice_sched_get_tc_node(pi, i)) 482062306a36Sopenharmony_ci continue; 482162306a36Sopenharmony_ci 482262306a36Sopenharmony_ci status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner, 482362306a36Sopenharmony_ci ice_is_tc_ena(tc_bitmap, i)); 482462306a36Sopenharmony_ci if (status) 482562306a36Sopenharmony_ci break; 482662306a36Sopenharmony_ci } 482762306a36Sopenharmony_ci 482862306a36Sopenharmony_ci mutex_unlock(&pi->sched_lock); 482962306a36Sopenharmony_ci return status; 483062306a36Sopenharmony_ci} 483162306a36Sopenharmony_ci 483262306a36Sopenharmony_ci/** 483362306a36Sopenharmony_ci * ice_cfg_vsi_lan - configure VSI LAN queues 483462306a36Sopenharmony_ci * @pi: port information structure 483562306a36Sopenharmony_ci * @vsi_handle: software VSI handle 483662306a36Sopenharmony_ci * @tc_bitmap: TC bitmap 483762306a36Sopenharmony_ci * @max_lanqs: max LAN queues array per TC 483862306a36Sopenharmony_ci * 483962306a36Sopenharmony_ci * This function adds/updates the VSI LAN queues per TC. 484062306a36Sopenharmony_ci */ 484162306a36Sopenharmony_ciint 484262306a36Sopenharmony_ciice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap, 484362306a36Sopenharmony_ci u16 *max_lanqs) 484462306a36Sopenharmony_ci{ 484562306a36Sopenharmony_ci return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs, 484662306a36Sopenharmony_ci ICE_SCHED_NODE_OWNER_LAN); 484762306a36Sopenharmony_ci} 484862306a36Sopenharmony_ci 484962306a36Sopenharmony_ci/** 485062306a36Sopenharmony_ci * ice_cfg_vsi_rdma - configure the VSI RDMA queues 485162306a36Sopenharmony_ci * @pi: port information structure 485262306a36Sopenharmony_ci * @vsi_handle: software VSI handle 485362306a36Sopenharmony_ci * @tc_bitmap: TC bitmap 485462306a36Sopenharmony_ci * @max_rdmaqs: max RDMA queues array per TC 485562306a36Sopenharmony_ci * 485662306a36Sopenharmony_ci * This function adds/updates the VSI RDMA queues per TC. 485762306a36Sopenharmony_ci */ 485862306a36Sopenharmony_ciint 485962306a36Sopenharmony_ciice_cfg_vsi_rdma(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap, 486062306a36Sopenharmony_ci u16 *max_rdmaqs) 486162306a36Sopenharmony_ci{ 486262306a36Sopenharmony_ci return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_rdmaqs, 486362306a36Sopenharmony_ci ICE_SCHED_NODE_OWNER_RDMA); 486462306a36Sopenharmony_ci} 486562306a36Sopenharmony_ci 486662306a36Sopenharmony_ci/** 486762306a36Sopenharmony_ci * ice_ena_vsi_rdma_qset 486862306a36Sopenharmony_ci * @pi: port information structure 486962306a36Sopenharmony_ci * @vsi_handle: software VSI handle 487062306a36Sopenharmony_ci * @tc: TC number 487162306a36Sopenharmony_ci * @rdma_qset: pointer to RDMA Qset 487262306a36Sopenharmony_ci * @num_qsets: number of RDMA Qsets 487362306a36Sopenharmony_ci * @qset_teid: pointer to Qset node TEIDs 487462306a36Sopenharmony_ci * 487562306a36Sopenharmony_ci * This function adds RDMA Qset 487662306a36Sopenharmony_ci */ 487762306a36Sopenharmony_ciint 487862306a36Sopenharmony_ciice_ena_vsi_rdma_qset(struct ice_port_info *pi, u16 vsi_handle, u8 tc, 487962306a36Sopenharmony_ci u16 *rdma_qset, u16 num_qsets, u32 *qset_teid) 488062306a36Sopenharmony_ci{ 488162306a36Sopenharmony_ci struct ice_aqc_txsched_elem_data node = { 0 }; 488262306a36Sopenharmony_ci struct ice_aqc_add_rdma_qset_data *buf; 488362306a36Sopenharmony_ci struct ice_sched_node *parent; 488462306a36Sopenharmony_ci struct ice_hw *hw; 488562306a36Sopenharmony_ci u16 i, buf_size; 488662306a36Sopenharmony_ci int ret; 488762306a36Sopenharmony_ci 488862306a36Sopenharmony_ci if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 488962306a36Sopenharmony_ci return -EIO; 489062306a36Sopenharmony_ci hw = pi->hw; 489162306a36Sopenharmony_ci 489262306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 489362306a36Sopenharmony_ci return -EINVAL; 489462306a36Sopenharmony_ci 489562306a36Sopenharmony_ci buf_size = struct_size(buf, rdma_qsets, num_qsets); 489662306a36Sopenharmony_ci buf = kzalloc(buf_size, GFP_KERNEL); 489762306a36Sopenharmony_ci if (!buf) 489862306a36Sopenharmony_ci return -ENOMEM; 489962306a36Sopenharmony_ci mutex_lock(&pi->sched_lock); 490062306a36Sopenharmony_ci 490162306a36Sopenharmony_ci parent = ice_sched_get_free_qparent(pi, vsi_handle, tc, 490262306a36Sopenharmony_ci ICE_SCHED_NODE_OWNER_RDMA); 490362306a36Sopenharmony_ci if (!parent) { 490462306a36Sopenharmony_ci ret = -EINVAL; 490562306a36Sopenharmony_ci goto rdma_error_exit; 490662306a36Sopenharmony_ci } 490762306a36Sopenharmony_ci buf->parent_teid = parent->info.node_teid; 490862306a36Sopenharmony_ci node.parent_teid = parent->info.node_teid; 490962306a36Sopenharmony_ci 491062306a36Sopenharmony_ci buf->num_qsets = cpu_to_le16(num_qsets); 491162306a36Sopenharmony_ci for (i = 0; i < num_qsets; i++) { 491262306a36Sopenharmony_ci buf->rdma_qsets[i].tx_qset_id = cpu_to_le16(rdma_qset[i]); 491362306a36Sopenharmony_ci buf->rdma_qsets[i].info.valid_sections = 491462306a36Sopenharmony_ci ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR | 491562306a36Sopenharmony_ci ICE_AQC_ELEM_VALID_EIR; 491662306a36Sopenharmony_ci buf->rdma_qsets[i].info.generic = 0; 491762306a36Sopenharmony_ci buf->rdma_qsets[i].info.cir_bw.bw_profile_idx = 491862306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID); 491962306a36Sopenharmony_ci buf->rdma_qsets[i].info.cir_bw.bw_alloc = 492062306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_BW_WT); 492162306a36Sopenharmony_ci buf->rdma_qsets[i].info.eir_bw.bw_profile_idx = 492262306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID); 492362306a36Sopenharmony_ci buf->rdma_qsets[i].info.eir_bw.bw_alloc = 492462306a36Sopenharmony_ci cpu_to_le16(ICE_SCHED_DFLT_BW_WT); 492562306a36Sopenharmony_ci } 492662306a36Sopenharmony_ci ret = ice_aq_add_rdma_qsets(hw, 1, buf, buf_size, NULL); 492762306a36Sopenharmony_ci if (ret) { 492862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_RDMA, "add RDMA qset failed\n"); 492962306a36Sopenharmony_ci goto rdma_error_exit; 493062306a36Sopenharmony_ci } 493162306a36Sopenharmony_ci node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF; 493262306a36Sopenharmony_ci for (i = 0; i < num_qsets; i++) { 493362306a36Sopenharmony_ci node.node_teid = buf->rdma_qsets[i].qset_teid; 493462306a36Sopenharmony_ci ret = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, 493562306a36Sopenharmony_ci &node, NULL); 493662306a36Sopenharmony_ci if (ret) 493762306a36Sopenharmony_ci break; 493862306a36Sopenharmony_ci qset_teid[i] = le32_to_cpu(node.node_teid); 493962306a36Sopenharmony_ci } 494062306a36Sopenharmony_cirdma_error_exit: 494162306a36Sopenharmony_ci mutex_unlock(&pi->sched_lock); 494262306a36Sopenharmony_ci kfree(buf); 494362306a36Sopenharmony_ci return ret; 494462306a36Sopenharmony_ci} 494562306a36Sopenharmony_ci 494662306a36Sopenharmony_ci/** 494762306a36Sopenharmony_ci * ice_dis_vsi_rdma_qset - free RDMA resources 494862306a36Sopenharmony_ci * @pi: port_info struct 494962306a36Sopenharmony_ci * @count: number of RDMA Qsets to free 495062306a36Sopenharmony_ci * @qset_teid: TEID of Qset node 495162306a36Sopenharmony_ci * @q_id: list of queue IDs being disabled 495262306a36Sopenharmony_ci */ 495362306a36Sopenharmony_ciint 495462306a36Sopenharmony_ciice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid, 495562306a36Sopenharmony_ci u16 *q_id) 495662306a36Sopenharmony_ci{ 495762306a36Sopenharmony_ci struct ice_aqc_dis_txq_item *qg_list; 495862306a36Sopenharmony_ci struct ice_hw *hw; 495962306a36Sopenharmony_ci int status = 0; 496062306a36Sopenharmony_ci u16 qg_size; 496162306a36Sopenharmony_ci int i; 496262306a36Sopenharmony_ci 496362306a36Sopenharmony_ci if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 496462306a36Sopenharmony_ci return -EIO; 496562306a36Sopenharmony_ci 496662306a36Sopenharmony_ci hw = pi->hw; 496762306a36Sopenharmony_ci 496862306a36Sopenharmony_ci qg_size = struct_size(qg_list, q_id, 1); 496962306a36Sopenharmony_ci qg_list = kzalloc(qg_size, GFP_KERNEL); 497062306a36Sopenharmony_ci if (!qg_list) 497162306a36Sopenharmony_ci return -ENOMEM; 497262306a36Sopenharmony_ci 497362306a36Sopenharmony_ci mutex_lock(&pi->sched_lock); 497462306a36Sopenharmony_ci 497562306a36Sopenharmony_ci for (i = 0; i < count; i++) { 497662306a36Sopenharmony_ci struct ice_sched_node *node; 497762306a36Sopenharmony_ci 497862306a36Sopenharmony_ci node = ice_sched_find_node_by_teid(pi->root, qset_teid[i]); 497962306a36Sopenharmony_ci if (!node) 498062306a36Sopenharmony_ci continue; 498162306a36Sopenharmony_ci 498262306a36Sopenharmony_ci qg_list->parent_teid = node->info.parent_teid; 498362306a36Sopenharmony_ci qg_list->num_qs = 1; 498462306a36Sopenharmony_ci qg_list->q_id[0] = 498562306a36Sopenharmony_ci cpu_to_le16(q_id[i] | 498662306a36Sopenharmony_ci ICE_AQC_Q_DIS_BUF_ELEM_TYPE_RDMA_QSET); 498762306a36Sopenharmony_ci 498862306a36Sopenharmony_ci status = ice_aq_dis_lan_txq(hw, 1, qg_list, qg_size, 498962306a36Sopenharmony_ci ICE_NO_RESET, 0, NULL); 499062306a36Sopenharmony_ci if (status) 499162306a36Sopenharmony_ci break; 499262306a36Sopenharmony_ci 499362306a36Sopenharmony_ci ice_free_sched_node(pi, node); 499462306a36Sopenharmony_ci } 499562306a36Sopenharmony_ci 499662306a36Sopenharmony_ci mutex_unlock(&pi->sched_lock); 499762306a36Sopenharmony_ci kfree(qg_list); 499862306a36Sopenharmony_ci return status; 499962306a36Sopenharmony_ci} 500062306a36Sopenharmony_ci 500162306a36Sopenharmony_ci/** 500262306a36Sopenharmony_ci * ice_replay_pre_init - replay pre initialization 500362306a36Sopenharmony_ci * @hw: pointer to the HW struct 500462306a36Sopenharmony_ci * 500562306a36Sopenharmony_ci * Initializes required config data for VSI, FD, ACL, and RSS before replay. 500662306a36Sopenharmony_ci */ 500762306a36Sopenharmony_cistatic int ice_replay_pre_init(struct ice_hw *hw) 500862306a36Sopenharmony_ci{ 500962306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 501062306a36Sopenharmony_ci u8 i; 501162306a36Sopenharmony_ci 501262306a36Sopenharmony_ci /* Delete old entries from replay filter list head if there is any */ 501362306a36Sopenharmony_ci ice_rm_all_sw_replay_rule_info(hw); 501462306a36Sopenharmony_ci /* In start of replay, move entries into replay_rules list, it 501562306a36Sopenharmony_ci * will allow adding rules entries back to filt_rules list, 501662306a36Sopenharmony_ci * which is operational list. 501762306a36Sopenharmony_ci */ 501862306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) 501962306a36Sopenharmony_ci list_replace_init(&sw->recp_list[i].filt_rules, 502062306a36Sopenharmony_ci &sw->recp_list[i].filt_replay_rules); 502162306a36Sopenharmony_ci ice_sched_replay_agg_vsi_preinit(hw); 502262306a36Sopenharmony_ci 502362306a36Sopenharmony_ci return 0; 502462306a36Sopenharmony_ci} 502562306a36Sopenharmony_ci 502662306a36Sopenharmony_ci/** 502762306a36Sopenharmony_ci * ice_replay_vsi - replay VSI configuration 502862306a36Sopenharmony_ci * @hw: pointer to the HW struct 502962306a36Sopenharmony_ci * @vsi_handle: driver VSI handle 503062306a36Sopenharmony_ci * 503162306a36Sopenharmony_ci * Restore all VSI configuration after reset. It is required to call this 503262306a36Sopenharmony_ci * function with main VSI first. 503362306a36Sopenharmony_ci */ 503462306a36Sopenharmony_ciint ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle) 503562306a36Sopenharmony_ci{ 503662306a36Sopenharmony_ci int status; 503762306a36Sopenharmony_ci 503862306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 503962306a36Sopenharmony_ci return -EINVAL; 504062306a36Sopenharmony_ci 504162306a36Sopenharmony_ci /* Replay pre-initialization if there is any */ 504262306a36Sopenharmony_ci if (vsi_handle == ICE_MAIN_VSI_HANDLE) { 504362306a36Sopenharmony_ci status = ice_replay_pre_init(hw); 504462306a36Sopenharmony_ci if (status) 504562306a36Sopenharmony_ci return status; 504662306a36Sopenharmony_ci } 504762306a36Sopenharmony_ci /* Replay per VSI all RSS configurations */ 504862306a36Sopenharmony_ci status = ice_replay_rss_cfg(hw, vsi_handle); 504962306a36Sopenharmony_ci if (status) 505062306a36Sopenharmony_ci return status; 505162306a36Sopenharmony_ci /* Replay per VSI all filters */ 505262306a36Sopenharmony_ci status = ice_replay_vsi_all_fltr(hw, vsi_handle); 505362306a36Sopenharmony_ci if (!status) 505462306a36Sopenharmony_ci status = ice_replay_vsi_agg(hw, vsi_handle); 505562306a36Sopenharmony_ci return status; 505662306a36Sopenharmony_ci} 505762306a36Sopenharmony_ci 505862306a36Sopenharmony_ci/** 505962306a36Sopenharmony_ci * ice_replay_post - post replay configuration cleanup 506062306a36Sopenharmony_ci * @hw: pointer to the HW struct 506162306a36Sopenharmony_ci * 506262306a36Sopenharmony_ci * Post replay cleanup. 506362306a36Sopenharmony_ci */ 506462306a36Sopenharmony_civoid ice_replay_post(struct ice_hw *hw) 506562306a36Sopenharmony_ci{ 506662306a36Sopenharmony_ci /* Delete old entries from replay filter list head */ 506762306a36Sopenharmony_ci ice_rm_all_sw_replay_rule_info(hw); 506862306a36Sopenharmony_ci ice_sched_replay_agg(hw); 506962306a36Sopenharmony_ci} 507062306a36Sopenharmony_ci 507162306a36Sopenharmony_ci/** 507262306a36Sopenharmony_ci * ice_stat_update40 - read 40 bit stat from the chip and update stat values 507362306a36Sopenharmony_ci * @hw: ptr to the hardware info 507462306a36Sopenharmony_ci * @reg: offset of 64 bit HW register to read from 507562306a36Sopenharmony_ci * @prev_stat_loaded: bool to specify if previous stats are loaded 507662306a36Sopenharmony_ci * @prev_stat: ptr to previous loaded stat value 507762306a36Sopenharmony_ci * @cur_stat: ptr to current stat value 507862306a36Sopenharmony_ci */ 507962306a36Sopenharmony_civoid 508062306a36Sopenharmony_ciice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, 508162306a36Sopenharmony_ci u64 *prev_stat, u64 *cur_stat) 508262306a36Sopenharmony_ci{ 508362306a36Sopenharmony_ci u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1); 508462306a36Sopenharmony_ci 508562306a36Sopenharmony_ci /* device stats are not reset at PFR, they likely will not be zeroed 508662306a36Sopenharmony_ci * when the driver starts. Thus, save the value from the first read 508762306a36Sopenharmony_ci * without adding to the statistic value so that we report stats which 508862306a36Sopenharmony_ci * count up from zero. 508962306a36Sopenharmony_ci */ 509062306a36Sopenharmony_ci if (!prev_stat_loaded) { 509162306a36Sopenharmony_ci *prev_stat = new_data; 509262306a36Sopenharmony_ci return; 509362306a36Sopenharmony_ci } 509462306a36Sopenharmony_ci 509562306a36Sopenharmony_ci /* Calculate the difference between the new and old values, and then 509662306a36Sopenharmony_ci * add it to the software stat value. 509762306a36Sopenharmony_ci */ 509862306a36Sopenharmony_ci if (new_data >= *prev_stat) 509962306a36Sopenharmony_ci *cur_stat += new_data - *prev_stat; 510062306a36Sopenharmony_ci else 510162306a36Sopenharmony_ci /* to manage the potential roll-over */ 510262306a36Sopenharmony_ci *cur_stat += (new_data + BIT_ULL(40)) - *prev_stat; 510362306a36Sopenharmony_ci 510462306a36Sopenharmony_ci /* Update the previously stored value to prepare for next read */ 510562306a36Sopenharmony_ci *prev_stat = new_data; 510662306a36Sopenharmony_ci} 510762306a36Sopenharmony_ci 510862306a36Sopenharmony_ci/** 510962306a36Sopenharmony_ci * ice_stat_update32 - read 32 bit stat from the chip and update stat values 511062306a36Sopenharmony_ci * @hw: ptr to the hardware info 511162306a36Sopenharmony_ci * @reg: offset of HW register to read from 511262306a36Sopenharmony_ci * @prev_stat_loaded: bool to specify if previous stats are loaded 511362306a36Sopenharmony_ci * @prev_stat: ptr to previous loaded stat value 511462306a36Sopenharmony_ci * @cur_stat: ptr to current stat value 511562306a36Sopenharmony_ci */ 511662306a36Sopenharmony_civoid 511762306a36Sopenharmony_ciice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, 511862306a36Sopenharmony_ci u64 *prev_stat, u64 *cur_stat) 511962306a36Sopenharmony_ci{ 512062306a36Sopenharmony_ci u32 new_data; 512162306a36Sopenharmony_ci 512262306a36Sopenharmony_ci new_data = rd32(hw, reg); 512362306a36Sopenharmony_ci 512462306a36Sopenharmony_ci /* device stats are not reset at PFR, they likely will not be zeroed 512562306a36Sopenharmony_ci * when the driver starts. Thus, save the value from the first read 512662306a36Sopenharmony_ci * without adding to the statistic value so that we report stats which 512762306a36Sopenharmony_ci * count up from zero. 512862306a36Sopenharmony_ci */ 512962306a36Sopenharmony_ci if (!prev_stat_loaded) { 513062306a36Sopenharmony_ci *prev_stat = new_data; 513162306a36Sopenharmony_ci return; 513262306a36Sopenharmony_ci } 513362306a36Sopenharmony_ci 513462306a36Sopenharmony_ci /* Calculate the difference between the new and old values, and then 513562306a36Sopenharmony_ci * add it to the software stat value. 513662306a36Sopenharmony_ci */ 513762306a36Sopenharmony_ci if (new_data >= *prev_stat) 513862306a36Sopenharmony_ci *cur_stat += new_data - *prev_stat; 513962306a36Sopenharmony_ci else 514062306a36Sopenharmony_ci /* to manage the potential roll-over */ 514162306a36Sopenharmony_ci *cur_stat += (new_data + BIT_ULL(32)) - *prev_stat; 514262306a36Sopenharmony_ci 514362306a36Sopenharmony_ci /* Update the previously stored value to prepare for next read */ 514462306a36Sopenharmony_ci *prev_stat = new_data; 514562306a36Sopenharmony_ci} 514662306a36Sopenharmony_ci 514762306a36Sopenharmony_ci/** 514862306a36Sopenharmony_ci * ice_sched_query_elem - query element information from HW 514962306a36Sopenharmony_ci * @hw: pointer to the HW struct 515062306a36Sopenharmony_ci * @node_teid: node TEID to be queried 515162306a36Sopenharmony_ci * @buf: buffer to element information 515262306a36Sopenharmony_ci * 515362306a36Sopenharmony_ci * This function queries HW element information 515462306a36Sopenharmony_ci */ 515562306a36Sopenharmony_ciint 515662306a36Sopenharmony_ciice_sched_query_elem(struct ice_hw *hw, u32 node_teid, 515762306a36Sopenharmony_ci struct ice_aqc_txsched_elem_data *buf) 515862306a36Sopenharmony_ci{ 515962306a36Sopenharmony_ci u16 buf_size, num_elem_ret = 0; 516062306a36Sopenharmony_ci int status; 516162306a36Sopenharmony_ci 516262306a36Sopenharmony_ci buf_size = sizeof(*buf); 516362306a36Sopenharmony_ci memset(buf, 0, buf_size); 516462306a36Sopenharmony_ci buf->node_teid = cpu_to_le32(node_teid); 516562306a36Sopenharmony_ci status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret, 516662306a36Sopenharmony_ci NULL); 516762306a36Sopenharmony_ci if (status || num_elem_ret != 1) 516862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SCHED, "query element failed\n"); 516962306a36Sopenharmony_ci return status; 517062306a36Sopenharmony_ci} 517162306a36Sopenharmony_ci 517262306a36Sopenharmony_ci/** 517362306a36Sopenharmony_ci * ice_aq_read_i2c 517462306a36Sopenharmony_ci * @hw: pointer to the hw struct 517562306a36Sopenharmony_ci * @topo_addr: topology address for a device to communicate with 517662306a36Sopenharmony_ci * @bus_addr: 7-bit I2C bus address 517762306a36Sopenharmony_ci * @addr: I2C memory address (I2C offset) with up to 16 bits 517862306a36Sopenharmony_ci * @params: I2C parameters: bit [7] - Repeated start, 517962306a36Sopenharmony_ci * bits [6:5] data offset size, 518062306a36Sopenharmony_ci * bit [4] - I2C address type, 518162306a36Sopenharmony_ci * bits [3:0] - data size to read (0-16 bytes) 518262306a36Sopenharmony_ci * @data: pointer to data (0 to 16 bytes) to be read from the I2C device 518362306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 518462306a36Sopenharmony_ci * 518562306a36Sopenharmony_ci * Read I2C (0x06E2) 518662306a36Sopenharmony_ci */ 518762306a36Sopenharmony_ciint 518862306a36Sopenharmony_ciice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, 518962306a36Sopenharmony_ci u16 bus_addr, __le16 addr, u8 params, u8 *data, 519062306a36Sopenharmony_ci struct ice_sq_cd *cd) 519162306a36Sopenharmony_ci{ 519262306a36Sopenharmony_ci struct ice_aq_desc desc = { 0 }; 519362306a36Sopenharmony_ci struct ice_aqc_i2c *cmd; 519462306a36Sopenharmony_ci u8 data_size; 519562306a36Sopenharmony_ci int status; 519662306a36Sopenharmony_ci 519762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c); 519862306a36Sopenharmony_ci cmd = &desc.params.read_write_i2c; 519962306a36Sopenharmony_ci 520062306a36Sopenharmony_ci if (!data) 520162306a36Sopenharmony_ci return -EINVAL; 520262306a36Sopenharmony_ci 520362306a36Sopenharmony_ci data_size = FIELD_GET(ICE_AQC_I2C_DATA_SIZE_M, params); 520462306a36Sopenharmony_ci 520562306a36Sopenharmony_ci cmd->i2c_bus_addr = cpu_to_le16(bus_addr); 520662306a36Sopenharmony_ci cmd->topo_addr = topo_addr; 520762306a36Sopenharmony_ci cmd->i2c_params = params; 520862306a36Sopenharmony_ci cmd->i2c_addr = addr; 520962306a36Sopenharmony_ci 521062306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 521162306a36Sopenharmony_ci if (!status) { 521262306a36Sopenharmony_ci struct ice_aqc_read_i2c_resp *resp; 521362306a36Sopenharmony_ci u8 i; 521462306a36Sopenharmony_ci 521562306a36Sopenharmony_ci resp = &desc.params.read_i2c_resp; 521662306a36Sopenharmony_ci for (i = 0; i < data_size; i++) { 521762306a36Sopenharmony_ci *data = resp->i2c_data[i]; 521862306a36Sopenharmony_ci data++; 521962306a36Sopenharmony_ci } 522062306a36Sopenharmony_ci } 522162306a36Sopenharmony_ci 522262306a36Sopenharmony_ci return status; 522362306a36Sopenharmony_ci} 522462306a36Sopenharmony_ci 522562306a36Sopenharmony_ci/** 522662306a36Sopenharmony_ci * ice_aq_write_i2c 522762306a36Sopenharmony_ci * @hw: pointer to the hw struct 522862306a36Sopenharmony_ci * @topo_addr: topology address for a device to communicate with 522962306a36Sopenharmony_ci * @bus_addr: 7-bit I2C bus address 523062306a36Sopenharmony_ci * @addr: I2C memory address (I2C offset) with up to 16 bits 523162306a36Sopenharmony_ci * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes) 523262306a36Sopenharmony_ci * @data: pointer to data (0 to 4 bytes) to be written to the I2C device 523362306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 523462306a36Sopenharmony_ci * 523562306a36Sopenharmony_ci * Write I2C (0x06E3) 523662306a36Sopenharmony_ci * 523762306a36Sopenharmony_ci * * Return: 523862306a36Sopenharmony_ci * * 0 - Successful write to the i2c device 523962306a36Sopenharmony_ci * * -EINVAL - Data size greater than 4 bytes 524062306a36Sopenharmony_ci * * -EIO - FW error 524162306a36Sopenharmony_ci */ 524262306a36Sopenharmony_ciint 524362306a36Sopenharmony_ciice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, 524462306a36Sopenharmony_ci u16 bus_addr, __le16 addr, u8 params, const u8 *data, 524562306a36Sopenharmony_ci struct ice_sq_cd *cd) 524662306a36Sopenharmony_ci{ 524762306a36Sopenharmony_ci struct ice_aq_desc desc = { 0 }; 524862306a36Sopenharmony_ci struct ice_aqc_i2c *cmd; 524962306a36Sopenharmony_ci u8 data_size; 525062306a36Sopenharmony_ci 525162306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c); 525262306a36Sopenharmony_ci cmd = &desc.params.read_write_i2c; 525362306a36Sopenharmony_ci 525462306a36Sopenharmony_ci data_size = FIELD_GET(ICE_AQC_I2C_DATA_SIZE_M, params); 525562306a36Sopenharmony_ci 525662306a36Sopenharmony_ci /* data_size limited to 4 */ 525762306a36Sopenharmony_ci if (data_size > 4) 525862306a36Sopenharmony_ci return -EINVAL; 525962306a36Sopenharmony_ci 526062306a36Sopenharmony_ci cmd->i2c_bus_addr = cpu_to_le16(bus_addr); 526162306a36Sopenharmony_ci cmd->topo_addr = topo_addr; 526262306a36Sopenharmony_ci cmd->i2c_params = params; 526362306a36Sopenharmony_ci cmd->i2c_addr = addr; 526462306a36Sopenharmony_ci 526562306a36Sopenharmony_ci memcpy(cmd->i2c_data, data, data_size); 526662306a36Sopenharmony_ci 526762306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 526862306a36Sopenharmony_ci} 526962306a36Sopenharmony_ci 527062306a36Sopenharmony_ci/** 527162306a36Sopenharmony_ci * ice_aq_set_driver_param - Set driver parameter to share via firmware 527262306a36Sopenharmony_ci * @hw: pointer to the HW struct 527362306a36Sopenharmony_ci * @idx: parameter index to set 527462306a36Sopenharmony_ci * @value: the value to set the parameter to 527562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 527662306a36Sopenharmony_ci * 527762306a36Sopenharmony_ci * Set the value of one of the software defined parameters. All PFs connected 527862306a36Sopenharmony_ci * to this device can read the value using ice_aq_get_driver_param. 527962306a36Sopenharmony_ci * 528062306a36Sopenharmony_ci * Note that firmware provides no synchronization or locking, and will not 528162306a36Sopenharmony_ci * save the parameter value during a device reset. It is expected that 528262306a36Sopenharmony_ci * a single PF will write the parameter value, while all other PFs will only 528362306a36Sopenharmony_ci * read it. 528462306a36Sopenharmony_ci */ 528562306a36Sopenharmony_ciint 528662306a36Sopenharmony_ciice_aq_set_driver_param(struct ice_hw *hw, enum ice_aqc_driver_params idx, 528762306a36Sopenharmony_ci u32 value, struct ice_sq_cd *cd) 528862306a36Sopenharmony_ci{ 528962306a36Sopenharmony_ci struct ice_aqc_driver_shared_params *cmd; 529062306a36Sopenharmony_ci struct ice_aq_desc desc; 529162306a36Sopenharmony_ci 529262306a36Sopenharmony_ci if (idx >= ICE_AQC_DRIVER_PARAM_MAX) 529362306a36Sopenharmony_ci return -EIO; 529462306a36Sopenharmony_ci 529562306a36Sopenharmony_ci cmd = &desc.params.drv_shared_params; 529662306a36Sopenharmony_ci 529762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_shared_params); 529862306a36Sopenharmony_ci 529962306a36Sopenharmony_ci cmd->set_or_get_op = ICE_AQC_DRIVER_PARAM_SET; 530062306a36Sopenharmony_ci cmd->param_indx = idx; 530162306a36Sopenharmony_ci cmd->param_val = cpu_to_le32(value); 530262306a36Sopenharmony_ci 530362306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 530462306a36Sopenharmony_ci} 530562306a36Sopenharmony_ci 530662306a36Sopenharmony_ci/** 530762306a36Sopenharmony_ci * ice_aq_get_driver_param - Get driver parameter shared via firmware 530862306a36Sopenharmony_ci * @hw: pointer to the HW struct 530962306a36Sopenharmony_ci * @idx: parameter index to set 531062306a36Sopenharmony_ci * @value: storage to return the shared parameter 531162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 531262306a36Sopenharmony_ci * 531362306a36Sopenharmony_ci * Get the value of one of the software defined parameters. 531462306a36Sopenharmony_ci * 531562306a36Sopenharmony_ci * Note that firmware provides no synchronization or locking. It is expected 531662306a36Sopenharmony_ci * that only a single PF will write a given parameter. 531762306a36Sopenharmony_ci */ 531862306a36Sopenharmony_ciint 531962306a36Sopenharmony_ciice_aq_get_driver_param(struct ice_hw *hw, enum ice_aqc_driver_params idx, 532062306a36Sopenharmony_ci u32 *value, struct ice_sq_cd *cd) 532162306a36Sopenharmony_ci{ 532262306a36Sopenharmony_ci struct ice_aqc_driver_shared_params *cmd; 532362306a36Sopenharmony_ci struct ice_aq_desc desc; 532462306a36Sopenharmony_ci int status; 532562306a36Sopenharmony_ci 532662306a36Sopenharmony_ci if (idx >= ICE_AQC_DRIVER_PARAM_MAX) 532762306a36Sopenharmony_ci return -EIO; 532862306a36Sopenharmony_ci 532962306a36Sopenharmony_ci cmd = &desc.params.drv_shared_params; 533062306a36Sopenharmony_ci 533162306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_shared_params); 533262306a36Sopenharmony_ci 533362306a36Sopenharmony_ci cmd->set_or_get_op = ICE_AQC_DRIVER_PARAM_GET; 533462306a36Sopenharmony_ci cmd->param_indx = idx; 533562306a36Sopenharmony_ci 533662306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 533762306a36Sopenharmony_ci if (status) 533862306a36Sopenharmony_ci return status; 533962306a36Sopenharmony_ci 534062306a36Sopenharmony_ci *value = le32_to_cpu(cmd->param_val); 534162306a36Sopenharmony_ci 534262306a36Sopenharmony_ci return 0; 534362306a36Sopenharmony_ci} 534462306a36Sopenharmony_ci 534562306a36Sopenharmony_ci/** 534662306a36Sopenharmony_ci * ice_aq_set_gpio 534762306a36Sopenharmony_ci * @hw: pointer to the hw struct 534862306a36Sopenharmony_ci * @gpio_ctrl_handle: GPIO controller node handle 534962306a36Sopenharmony_ci * @pin_idx: IO Number of the GPIO that needs to be set 535062306a36Sopenharmony_ci * @value: SW provide IO value to set in the LSB 535162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 535262306a36Sopenharmony_ci * 535362306a36Sopenharmony_ci * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology 535462306a36Sopenharmony_ci */ 535562306a36Sopenharmony_ciint 535662306a36Sopenharmony_ciice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value, 535762306a36Sopenharmony_ci struct ice_sq_cd *cd) 535862306a36Sopenharmony_ci{ 535962306a36Sopenharmony_ci struct ice_aqc_gpio *cmd; 536062306a36Sopenharmony_ci struct ice_aq_desc desc; 536162306a36Sopenharmony_ci 536262306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio); 536362306a36Sopenharmony_ci cmd = &desc.params.read_write_gpio; 536462306a36Sopenharmony_ci cmd->gpio_ctrl_handle = cpu_to_le16(gpio_ctrl_handle); 536562306a36Sopenharmony_ci cmd->gpio_num = pin_idx; 536662306a36Sopenharmony_ci cmd->gpio_val = value ? 1 : 0; 536762306a36Sopenharmony_ci 536862306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 536962306a36Sopenharmony_ci} 537062306a36Sopenharmony_ci 537162306a36Sopenharmony_ci/** 537262306a36Sopenharmony_ci * ice_aq_get_gpio 537362306a36Sopenharmony_ci * @hw: pointer to the hw struct 537462306a36Sopenharmony_ci * @gpio_ctrl_handle: GPIO controller node handle 537562306a36Sopenharmony_ci * @pin_idx: IO Number of the GPIO that needs to be set 537662306a36Sopenharmony_ci * @value: IO value read 537762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 537862306a36Sopenharmony_ci * 537962306a36Sopenharmony_ci * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of 538062306a36Sopenharmony_ci * the topology 538162306a36Sopenharmony_ci */ 538262306a36Sopenharmony_ciint 538362306a36Sopenharmony_ciice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, 538462306a36Sopenharmony_ci bool *value, struct ice_sq_cd *cd) 538562306a36Sopenharmony_ci{ 538662306a36Sopenharmony_ci struct ice_aqc_gpio *cmd; 538762306a36Sopenharmony_ci struct ice_aq_desc desc; 538862306a36Sopenharmony_ci int status; 538962306a36Sopenharmony_ci 539062306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio); 539162306a36Sopenharmony_ci cmd = &desc.params.read_write_gpio; 539262306a36Sopenharmony_ci cmd->gpio_ctrl_handle = cpu_to_le16(gpio_ctrl_handle); 539362306a36Sopenharmony_ci cmd->gpio_num = pin_idx; 539462306a36Sopenharmony_ci 539562306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 539662306a36Sopenharmony_ci if (status) 539762306a36Sopenharmony_ci return status; 539862306a36Sopenharmony_ci 539962306a36Sopenharmony_ci *value = !!cmd->gpio_val; 540062306a36Sopenharmony_ci return 0; 540162306a36Sopenharmony_ci} 540262306a36Sopenharmony_ci 540362306a36Sopenharmony_ci/** 540462306a36Sopenharmony_ci * ice_is_fw_api_min_ver 540562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 540662306a36Sopenharmony_ci * @maj: major version 540762306a36Sopenharmony_ci * @min: minor version 540862306a36Sopenharmony_ci * @patch: patch version 540962306a36Sopenharmony_ci * 541062306a36Sopenharmony_ci * Checks if the firmware API is minimum version 541162306a36Sopenharmony_ci */ 541262306a36Sopenharmony_cistatic bool ice_is_fw_api_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch) 541362306a36Sopenharmony_ci{ 541462306a36Sopenharmony_ci if (hw->api_maj_ver == maj) { 541562306a36Sopenharmony_ci if (hw->api_min_ver > min) 541662306a36Sopenharmony_ci return true; 541762306a36Sopenharmony_ci if (hw->api_min_ver == min && hw->api_patch >= patch) 541862306a36Sopenharmony_ci return true; 541962306a36Sopenharmony_ci } else if (hw->api_maj_ver > maj) { 542062306a36Sopenharmony_ci return true; 542162306a36Sopenharmony_ci } 542262306a36Sopenharmony_ci 542362306a36Sopenharmony_ci return false; 542462306a36Sopenharmony_ci} 542562306a36Sopenharmony_ci 542662306a36Sopenharmony_ci/** 542762306a36Sopenharmony_ci * ice_fw_supports_link_override 542862306a36Sopenharmony_ci * @hw: pointer to the hardware structure 542962306a36Sopenharmony_ci * 543062306a36Sopenharmony_ci * Checks if the firmware supports link override 543162306a36Sopenharmony_ci */ 543262306a36Sopenharmony_cibool ice_fw_supports_link_override(struct ice_hw *hw) 543362306a36Sopenharmony_ci{ 543462306a36Sopenharmony_ci return ice_is_fw_api_min_ver(hw, ICE_FW_API_LINK_OVERRIDE_MAJ, 543562306a36Sopenharmony_ci ICE_FW_API_LINK_OVERRIDE_MIN, 543662306a36Sopenharmony_ci ICE_FW_API_LINK_OVERRIDE_PATCH); 543762306a36Sopenharmony_ci} 543862306a36Sopenharmony_ci 543962306a36Sopenharmony_ci/** 544062306a36Sopenharmony_ci * ice_get_link_default_override 544162306a36Sopenharmony_ci * @ldo: pointer to the link default override struct 544262306a36Sopenharmony_ci * @pi: pointer to the port info struct 544362306a36Sopenharmony_ci * 544462306a36Sopenharmony_ci * Gets the link default override for a port 544562306a36Sopenharmony_ci */ 544662306a36Sopenharmony_ciint 544762306a36Sopenharmony_ciice_get_link_default_override(struct ice_link_default_override_tlv *ldo, 544862306a36Sopenharmony_ci struct ice_port_info *pi) 544962306a36Sopenharmony_ci{ 545062306a36Sopenharmony_ci u16 i, tlv, tlv_len, tlv_start, buf, offset; 545162306a36Sopenharmony_ci struct ice_hw *hw = pi->hw; 545262306a36Sopenharmony_ci int status; 545362306a36Sopenharmony_ci 545462306a36Sopenharmony_ci status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len, 545562306a36Sopenharmony_ci ICE_SR_LINK_DEFAULT_OVERRIDE_PTR); 545662306a36Sopenharmony_ci if (status) { 545762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n"); 545862306a36Sopenharmony_ci return status; 545962306a36Sopenharmony_ci } 546062306a36Sopenharmony_ci 546162306a36Sopenharmony_ci /* Each port has its own config; calculate for our port */ 546262306a36Sopenharmony_ci tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS + 546362306a36Sopenharmony_ci ICE_SR_PFA_LINK_OVERRIDE_OFFSET; 546462306a36Sopenharmony_ci 546562306a36Sopenharmony_ci /* link options first */ 546662306a36Sopenharmony_ci status = ice_read_sr_word(hw, tlv_start, &buf); 546762306a36Sopenharmony_ci if (status) { 546862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n"); 546962306a36Sopenharmony_ci return status; 547062306a36Sopenharmony_ci } 547162306a36Sopenharmony_ci ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M; 547262306a36Sopenharmony_ci ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >> 547362306a36Sopenharmony_ci ICE_LINK_OVERRIDE_PHY_CFG_S; 547462306a36Sopenharmony_ci 547562306a36Sopenharmony_ci /* link PHY config */ 547662306a36Sopenharmony_ci offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET; 547762306a36Sopenharmony_ci status = ice_read_sr_word(hw, offset, &buf); 547862306a36Sopenharmony_ci if (status) { 547962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n"); 548062306a36Sopenharmony_ci return status; 548162306a36Sopenharmony_ci } 548262306a36Sopenharmony_ci ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M; 548362306a36Sopenharmony_ci 548462306a36Sopenharmony_ci /* PHY types low */ 548562306a36Sopenharmony_ci offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET; 548662306a36Sopenharmony_ci for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) { 548762306a36Sopenharmony_ci status = ice_read_sr_word(hw, (offset + i), &buf); 548862306a36Sopenharmony_ci if (status) { 548962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n"); 549062306a36Sopenharmony_ci return status; 549162306a36Sopenharmony_ci } 549262306a36Sopenharmony_ci /* shift 16 bits at a time to fill 64 bits */ 549362306a36Sopenharmony_ci ldo->phy_type_low |= ((u64)buf << (i * 16)); 549462306a36Sopenharmony_ci } 549562306a36Sopenharmony_ci 549662306a36Sopenharmony_ci /* PHY types high */ 549762306a36Sopenharmony_ci offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET + 549862306a36Sopenharmony_ci ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; 549962306a36Sopenharmony_ci for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) { 550062306a36Sopenharmony_ci status = ice_read_sr_word(hw, (offset + i), &buf); 550162306a36Sopenharmony_ci if (status) { 550262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n"); 550362306a36Sopenharmony_ci return status; 550462306a36Sopenharmony_ci } 550562306a36Sopenharmony_ci /* shift 16 bits at a time to fill 64 bits */ 550662306a36Sopenharmony_ci ldo->phy_type_high |= ((u64)buf << (i * 16)); 550762306a36Sopenharmony_ci } 550862306a36Sopenharmony_ci 550962306a36Sopenharmony_ci return status; 551062306a36Sopenharmony_ci} 551162306a36Sopenharmony_ci 551262306a36Sopenharmony_ci/** 551362306a36Sopenharmony_ci * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled 551462306a36Sopenharmony_ci * @caps: get PHY capability data 551562306a36Sopenharmony_ci */ 551662306a36Sopenharmony_cibool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps) 551762306a36Sopenharmony_ci{ 551862306a36Sopenharmony_ci if (caps->caps & ICE_AQC_PHY_AN_MODE || 551962306a36Sopenharmony_ci caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 | 552062306a36Sopenharmony_ci ICE_AQC_PHY_AN_EN_CLAUSE73 | 552162306a36Sopenharmony_ci ICE_AQC_PHY_AN_EN_CLAUSE37)) 552262306a36Sopenharmony_ci return true; 552362306a36Sopenharmony_ci 552462306a36Sopenharmony_ci return false; 552562306a36Sopenharmony_ci} 552662306a36Sopenharmony_ci 552762306a36Sopenharmony_ci/** 552862306a36Sopenharmony_ci * ice_aq_set_lldp_mib - Set the LLDP MIB 552962306a36Sopenharmony_ci * @hw: pointer to the HW struct 553062306a36Sopenharmony_ci * @mib_type: Local, Remote or both Local and Remote MIBs 553162306a36Sopenharmony_ci * @buf: pointer to the caller-supplied buffer to store the MIB block 553262306a36Sopenharmony_ci * @buf_size: size of the buffer (in bytes) 553362306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 553462306a36Sopenharmony_ci * 553562306a36Sopenharmony_ci * Set the LLDP MIB. (0x0A08) 553662306a36Sopenharmony_ci */ 553762306a36Sopenharmony_ciint 553862306a36Sopenharmony_ciice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size, 553962306a36Sopenharmony_ci struct ice_sq_cd *cd) 554062306a36Sopenharmony_ci{ 554162306a36Sopenharmony_ci struct ice_aqc_lldp_set_local_mib *cmd; 554262306a36Sopenharmony_ci struct ice_aq_desc desc; 554362306a36Sopenharmony_ci 554462306a36Sopenharmony_ci cmd = &desc.params.lldp_set_mib; 554562306a36Sopenharmony_ci 554662306a36Sopenharmony_ci if (buf_size == 0 || !buf) 554762306a36Sopenharmony_ci return -EINVAL; 554862306a36Sopenharmony_ci 554962306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib); 555062306a36Sopenharmony_ci 555162306a36Sopenharmony_ci desc.flags |= cpu_to_le16((u16)ICE_AQ_FLAG_RD); 555262306a36Sopenharmony_ci desc.datalen = cpu_to_le16(buf_size); 555362306a36Sopenharmony_ci 555462306a36Sopenharmony_ci cmd->type = mib_type; 555562306a36Sopenharmony_ci cmd->length = cpu_to_le16(buf_size); 555662306a36Sopenharmony_ci 555762306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 555862306a36Sopenharmony_ci} 555962306a36Sopenharmony_ci 556062306a36Sopenharmony_ci/** 556162306a36Sopenharmony_ci * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl 556262306a36Sopenharmony_ci * @hw: pointer to HW struct 556362306a36Sopenharmony_ci */ 556462306a36Sopenharmony_cibool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw) 556562306a36Sopenharmony_ci{ 556662306a36Sopenharmony_ci if (hw->mac_type != ICE_MAC_E810) 556762306a36Sopenharmony_ci return false; 556862306a36Sopenharmony_ci 556962306a36Sopenharmony_ci return ice_is_fw_api_min_ver(hw, ICE_FW_API_LLDP_FLTR_MAJ, 557062306a36Sopenharmony_ci ICE_FW_API_LLDP_FLTR_MIN, 557162306a36Sopenharmony_ci ICE_FW_API_LLDP_FLTR_PATCH); 557262306a36Sopenharmony_ci} 557362306a36Sopenharmony_ci 557462306a36Sopenharmony_ci/** 557562306a36Sopenharmony_ci * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter 557662306a36Sopenharmony_ci * @hw: pointer to HW struct 557762306a36Sopenharmony_ci * @vsi_num: absolute HW index for VSI 557862306a36Sopenharmony_ci * @add: boolean for if adding or removing a filter 557962306a36Sopenharmony_ci */ 558062306a36Sopenharmony_ciint 558162306a36Sopenharmony_ciice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add) 558262306a36Sopenharmony_ci{ 558362306a36Sopenharmony_ci struct ice_aqc_lldp_filter_ctrl *cmd; 558462306a36Sopenharmony_ci struct ice_aq_desc desc; 558562306a36Sopenharmony_ci 558662306a36Sopenharmony_ci cmd = &desc.params.lldp_filter_ctrl; 558762306a36Sopenharmony_ci 558862306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl); 558962306a36Sopenharmony_ci 559062306a36Sopenharmony_ci if (add) 559162306a36Sopenharmony_ci cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD; 559262306a36Sopenharmony_ci else 559362306a36Sopenharmony_ci cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE; 559462306a36Sopenharmony_ci 559562306a36Sopenharmony_ci cmd->vsi_num = cpu_to_le16(vsi_num); 559662306a36Sopenharmony_ci 559762306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 559862306a36Sopenharmony_ci} 559962306a36Sopenharmony_ci 560062306a36Sopenharmony_ci/** 560162306a36Sopenharmony_ci * ice_lldp_execute_pending_mib - execute LLDP pending MIB request 560262306a36Sopenharmony_ci * @hw: pointer to HW struct 560362306a36Sopenharmony_ci */ 560462306a36Sopenharmony_ciint ice_lldp_execute_pending_mib(struct ice_hw *hw) 560562306a36Sopenharmony_ci{ 560662306a36Sopenharmony_ci struct ice_aq_desc desc; 560762306a36Sopenharmony_ci 560862306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_execute_pending_mib); 560962306a36Sopenharmony_ci 561062306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 561162306a36Sopenharmony_ci} 561262306a36Sopenharmony_ci 561362306a36Sopenharmony_ci/** 561462306a36Sopenharmony_ci * ice_fw_supports_report_dflt_cfg 561562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 561662306a36Sopenharmony_ci * 561762306a36Sopenharmony_ci * Checks if the firmware supports report default configuration 561862306a36Sopenharmony_ci */ 561962306a36Sopenharmony_cibool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw) 562062306a36Sopenharmony_ci{ 562162306a36Sopenharmony_ci return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ, 562262306a36Sopenharmony_ci ICE_FW_API_REPORT_DFLT_CFG_MIN, 562362306a36Sopenharmony_ci ICE_FW_API_REPORT_DFLT_CFG_PATCH); 562462306a36Sopenharmony_ci} 562562306a36Sopenharmony_ci 562662306a36Sopenharmony_ci/* each of the indexes into the following array match the speed of a return 562762306a36Sopenharmony_ci * value from the list of AQ returned speeds like the range: 562862306a36Sopenharmony_ci * ICE_AQ_LINK_SPEED_10MB .. ICE_AQ_LINK_SPEED_100GB excluding 562962306a36Sopenharmony_ci * ICE_AQ_LINK_SPEED_UNKNOWN which is BIT(15) and maps to BIT(14) in this 563062306a36Sopenharmony_ci * array. The array is defined as 15 elements long because the link_speed 563162306a36Sopenharmony_ci * returned by the firmware is a 16 bit * value, but is indexed 563262306a36Sopenharmony_ci * by [fls(speed) - 1] 563362306a36Sopenharmony_ci */ 563462306a36Sopenharmony_cistatic const u32 ice_aq_to_link_speed[] = { 563562306a36Sopenharmony_ci SPEED_10, /* BIT(0) */ 563662306a36Sopenharmony_ci SPEED_100, 563762306a36Sopenharmony_ci SPEED_1000, 563862306a36Sopenharmony_ci SPEED_2500, 563962306a36Sopenharmony_ci SPEED_5000, 564062306a36Sopenharmony_ci SPEED_10000, 564162306a36Sopenharmony_ci SPEED_20000, 564262306a36Sopenharmony_ci SPEED_25000, 564362306a36Sopenharmony_ci SPEED_40000, 564462306a36Sopenharmony_ci SPEED_50000, 564562306a36Sopenharmony_ci SPEED_100000, /* BIT(10) */ 564662306a36Sopenharmony_ci}; 564762306a36Sopenharmony_ci 564862306a36Sopenharmony_ci/** 564962306a36Sopenharmony_ci * ice_get_link_speed - get integer speed from table 565062306a36Sopenharmony_ci * @index: array index from fls(aq speed) - 1 565162306a36Sopenharmony_ci * 565262306a36Sopenharmony_ci * Returns: u32 value containing integer speed 565362306a36Sopenharmony_ci */ 565462306a36Sopenharmony_ciu32 ice_get_link_speed(u16 index) 565562306a36Sopenharmony_ci{ 565662306a36Sopenharmony_ci if (index >= ARRAY_SIZE(ice_aq_to_link_speed)) 565762306a36Sopenharmony_ci return 0; 565862306a36Sopenharmony_ci 565962306a36Sopenharmony_ci return ice_aq_to_link_speed[index]; 566062306a36Sopenharmony_ci} 5661