17ec59eeaSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 27ec59eeaSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 37ec59eeaSAnirudh Venkataramanan 47ec59eeaSAnirudh Venkataramanan #include "ice_common.h" 59c20346bSAnirudh Venkataramanan #include "ice_sched.h" 67ec59eeaSAnirudh Venkataramanan #include "ice_adminq_cmd.h" 77ec59eeaSAnirudh Venkataramanan 8f31e4b6fSAnirudh Venkataramanan #define ICE_PF_RESET_WAIT_COUNT 200 9f31e4b6fSAnirudh Venkataramanan 10f31e4b6fSAnirudh Venkataramanan /** 11f31e4b6fSAnirudh Venkataramanan * ice_set_mac_type - Sets MAC type 12f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 13f31e4b6fSAnirudh Venkataramanan * 14f31e4b6fSAnirudh Venkataramanan * This function sets the MAC type of the adapter based on the 15f31e4b6fSAnirudh Venkataramanan * vendor ID and device ID stored in the hw structure. 16f31e4b6fSAnirudh Venkataramanan */ 17f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_set_mac_type(struct ice_hw *hw) 18f31e4b6fSAnirudh Venkataramanan { 19f31e4b6fSAnirudh Venkataramanan if (hw->vendor_id != PCI_VENDOR_ID_INTEL) 20f31e4b6fSAnirudh Venkataramanan return ICE_ERR_DEVICE_NOT_SUPPORTED; 21f31e4b6fSAnirudh Venkataramanan 22f31e4b6fSAnirudh Venkataramanan hw->mac_type = ICE_MAC_GENERIC; 23f31e4b6fSAnirudh Venkataramanan return 0; 24f31e4b6fSAnirudh Venkataramanan } 25f31e4b6fSAnirudh Venkataramanan 26f31e4b6fSAnirudh Venkataramanan /** 27f31e4b6fSAnirudh Venkataramanan * ice_clear_pf_cfg - Clear PF configuration 28f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 29f31e4b6fSAnirudh Venkataramanan */ 30f31e4b6fSAnirudh Venkataramanan enum ice_status ice_clear_pf_cfg(struct ice_hw *hw) 31f31e4b6fSAnirudh Venkataramanan { 32f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 33f31e4b6fSAnirudh Venkataramanan 34f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg); 35f31e4b6fSAnirudh Venkataramanan 36f31e4b6fSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 37f31e4b6fSAnirudh Venkataramanan } 38f31e4b6fSAnirudh Venkataramanan 39f31e4b6fSAnirudh Venkataramanan /** 40dc49c772SAnirudh Venkataramanan * ice_aq_manage_mac_read - manage MAC address read command 41dc49c772SAnirudh Venkataramanan * @hw: pointer to the hw struct 42dc49c772SAnirudh Venkataramanan * @buf: a virtual buffer to hold the manage MAC read response 43dc49c772SAnirudh Venkataramanan * @buf_size: Size of the virtual buffer 44dc49c772SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 45dc49c772SAnirudh Venkataramanan * 46dc49c772SAnirudh Venkataramanan * This function is used to return per PF station MAC address (0x0107). 47dc49c772SAnirudh Venkataramanan * NOTE: Upon successful completion of this command, MAC address information 48dc49c772SAnirudh Venkataramanan * is returned in user specified buffer. Please interpret user specified 49dc49c772SAnirudh Venkataramanan * buffer as "manage_mac_read" response. 50dc49c772SAnirudh Venkataramanan * Response such as various MAC addresses are stored in HW struct (port.mac) 51dc49c772SAnirudh Venkataramanan * ice_aq_discover_caps is expected to be called before this function is called. 52dc49c772SAnirudh Venkataramanan */ 53dc49c772SAnirudh Venkataramanan static enum ice_status 54dc49c772SAnirudh Venkataramanan ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size, 55dc49c772SAnirudh Venkataramanan struct ice_sq_cd *cd) 56dc49c772SAnirudh Venkataramanan { 57dc49c772SAnirudh Venkataramanan struct ice_aqc_manage_mac_read_resp *resp; 58dc49c772SAnirudh Venkataramanan struct ice_aqc_manage_mac_read *cmd; 59dc49c772SAnirudh Venkataramanan struct ice_aq_desc desc; 60dc49c772SAnirudh Venkataramanan enum ice_status status; 61dc49c772SAnirudh Venkataramanan u16 flags; 62dc49c772SAnirudh Venkataramanan 63dc49c772SAnirudh Venkataramanan cmd = &desc.params.mac_read; 64dc49c772SAnirudh Venkataramanan 65dc49c772SAnirudh Venkataramanan if (buf_size < sizeof(*resp)) 66dc49c772SAnirudh Venkataramanan return ICE_ERR_BUF_TOO_SHORT; 67dc49c772SAnirudh Venkataramanan 68dc49c772SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read); 69dc49c772SAnirudh Venkataramanan 70dc49c772SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 71dc49c772SAnirudh Venkataramanan if (status) 72dc49c772SAnirudh Venkataramanan return status; 73dc49c772SAnirudh Venkataramanan 74dc49c772SAnirudh Venkataramanan resp = (struct ice_aqc_manage_mac_read_resp *)buf; 75dc49c772SAnirudh Venkataramanan flags = le16_to_cpu(cmd->flags) & ICE_AQC_MAN_MAC_READ_M; 76dc49c772SAnirudh Venkataramanan 77dc49c772SAnirudh Venkataramanan if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) { 78dc49c772SAnirudh Venkataramanan ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n"); 79dc49c772SAnirudh Venkataramanan return ICE_ERR_CFG; 80dc49c772SAnirudh Venkataramanan } 81dc49c772SAnirudh Venkataramanan 82dc49c772SAnirudh Venkataramanan ether_addr_copy(hw->port_info->mac.lan_addr, resp->mac_addr); 83dc49c772SAnirudh Venkataramanan ether_addr_copy(hw->port_info->mac.perm_addr, resp->mac_addr); 84dc49c772SAnirudh Venkataramanan return 0; 85dc49c772SAnirudh Venkataramanan } 86dc49c772SAnirudh Venkataramanan 87dc49c772SAnirudh Venkataramanan /** 88dc49c772SAnirudh Venkataramanan * ice_aq_get_phy_caps - returns PHY capabilities 89dc49c772SAnirudh Venkataramanan * @pi: port information structure 90dc49c772SAnirudh Venkataramanan * @qual_mods: report qualified modules 91dc49c772SAnirudh Venkataramanan * @report_mode: report mode capabilities 92dc49c772SAnirudh Venkataramanan * @pcaps: structure for PHY capabilities to be filled 93dc49c772SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 94dc49c772SAnirudh Venkataramanan * 95dc49c772SAnirudh Venkataramanan * Returns the various PHY capabilities supported on the Port (0x0600) 96dc49c772SAnirudh Venkataramanan */ 97dc49c772SAnirudh Venkataramanan static enum ice_status 98dc49c772SAnirudh Venkataramanan ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, 99dc49c772SAnirudh Venkataramanan struct ice_aqc_get_phy_caps_data *pcaps, 100dc49c772SAnirudh Venkataramanan struct ice_sq_cd *cd) 101dc49c772SAnirudh Venkataramanan { 102dc49c772SAnirudh Venkataramanan struct ice_aqc_get_phy_caps *cmd; 103dc49c772SAnirudh Venkataramanan u16 pcaps_size = sizeof(*pcaps); 104dc49c772SAnirudh Venkataramanan struct ice_aq_desc desc; 105dc49c772SAnirudh Venkataramanan enum ice_status status; 106dc49c772SAnirudh Venkataramanan 107dc49c772SAnirudh Venkataramanan cmd = &desc.params.get_phy; 108dc49c772SAnirudh Venkataramanan 109dc49c772SAnirudh Venkataramanan if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi) 110dc49c772SAnirudh Venkataramanan return ICE_ERR_PARAM; 111dc49c772SAnirudh Venkataramanan 112dc49c772SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps); 113dc49c772SAnirudh Venkataramanan 114dc49c772SAnirudh Venkataramanan if (qual_mods) 115dc49c772SAnirudh Venkataramanan cmd->param0 |= cpu_to_le16(ICE_AQC_GET_PHY_RQM); 116dc49c772SAnirudh Venkataramanan 117dc49c772SAnirudh Venkataramanan cmd->param0 |= cpu_to_le16(report_mode); 118dc49c772SAnirudh Venkataramanan status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd); 119dc49c772SAnirudh Venkataramanan 120dc49c772SAnirudh Venkataramanan if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) 121dc49c772SAnirudh Venkataramanan pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low); 122dc49c772SAnirudh Venkataramanan 123dc49c772SAnirudh Venkataramanan return status; 124dc49c772SAnirudh Venkataramanan } 125dc49c772SAnirudh Venkataramanan 126dc49c772SAnirudh Venkataramanan /** 127dc49c772SAnirudh Venkataramanan * ice_get_media_type - Gets media type 128dc49c772SAnirudh Venkataramanan * @pi: port information structure 129dc49c772SAnirudh Venkataramanan */ 130dc49c772SAnirudh Venkataramanan static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) 131dc49c772SAnirudh Venkataramanan { 132dc49c772SAnirudh Venkataramanan struct ice_link_status *hw_link_info; 133dc49c772SAnirudh Venkataramanan 134dc49c772SAnirudh Venkataramanan if (!pi) 135dc49c772SAnirudh Venkataramanan return ICE_MEDIA_UNKNOWN; 136dc49c772SAnirudh Venkataramanan 137dc49c772SAnirudh Venkataramanan hw_link_info = &pi->phy.link_info; 138dc49c772SAnirudh Venkataramanan 139dc49c772SAnirudh Venkataramanan if (hw_link_info->phy_type_low) { 140dc49c772SAnirudh Venkataramanan switch (hw_link_info->phy_type_low) { 141dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_1000BASE_SX: 142dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_1000BASE_LX: 143dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_10GBASE_SR: 144dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_10GBASE_LR: 145dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 146dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_SR: 147dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_LR: 148dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 149dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_40GBASE_SR4: 150dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_40GBASE_LR4: 151dc49c772SAnirudh Venkataramanan return ICE_MEDIA_FIBER; 152dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100BASE_TX: 153dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_1000BASE_T: 154dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_2500BASE_T: 155dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_5GBASE_T: 156dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_10GBASE_T: 157dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_T: 158dc49c772SAnirudh Venkataramanan return ICE_MEDIA_BASET; 159dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_10G_SFI_DA: 160dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_CR: 161dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 162dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_CR1: 163dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_40GBASE_CR4: 164dc49c772SAnirudh Venkataramanan return ICE_MEDIA_DA; 165dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_1000BASE_KX: 166dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_2500BASE_KX: 167dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_2500BASE_X: 168dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_5GBASE_KR: 169dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 170dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_KR: 171dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_KR1: 172dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 173dc49c772SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_40GBASE_KR4: 174dc49c772SAnirudh Venkataramanan return ICE_MEDIA_BACKPLANE; 175dc49c772SAnirudh Venkataramanan } 176dc49c772SAnirudh Venkataramanan } 177dc49c772SAnirudh Venkataramanan 178dc49c772SAnirudh Venkataramanan return ICE_MEDIA_UNKNOWN; 179dc49c772SAnirudh Venkataramanan } 180dc49c772SAnirudh Venkataramanan 181dc49c772SAnirudh Venkataramanan /** 182dc49c772SAnirudh Venkataramanan * ice_aq_get_link_info 183dc49c772SAnirudh Venkataramanan * @pi: port information structure 184dc49c772SAnirudh Venkataramanan * @ena_lse: enable/disable LinkStatusEvent reporting 185dc49c772SAnirudh Venkataramanan * @link: pointer to link status structure - optional 186dc49c772SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 187dc49c772SAnirudh Venkataramanan * 188dc49c772SAnirudh Venkataramanan * Get Link Status (0x607). Returns the link status of the adapter. 189dc49c772SAnirudh Venkataramanan */ 190dc49c772SAnirudh Venkataramanan enum ice_status 191dc49c772SAnirudh Venkataramanan ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, 192dc49c772SAnirudh Venkataramanan struct ice_link_status *link, struct ice_sq_cd *cd) 193dc49c772SAnirudh Venkataramanan { 194dc49c772SAnirudh Venkataramanan struct ice_link_status *hw_link_info_old, *hw_link_info; 195dc49c772SAnirudh Venkataramanan struct ice_aqc_get_link_status_data link_data = { 0 }; 196dc49c772SAnirudh Venkataramanan struct ice_aqc_get_link_status *resp; 197dc49c772SAnirudh Venkataramanan enum ice_media_type *hw_media_type; 198dc49c772SAnirudh Venkataramanan struct ice_fc_info *hw_fc_info; 199dc49c772SAnirudh Venkataramanan bool tx_pause, rx_pause; 200dc49c772SAnirudh Venkataramanan struct ice_aq_desc desc; 201dc49c772SAnirudh Venkataramanan enum ice_status status; 202dc49c772SAnirudh Venkataramanan u16 cmd_flags; 203dc49c772SAnirudh Venkataramanan 204dc49c772SAnirudh Venkataramanan if (!pi) 205dc49c772SAnirudh Venkataramanan return ICE_ERR_PARAM; 206dc49c772SAnirudh Venkataramanan hw_link_info_old = &pi->phy.link_info_old; 207dc49c772SAnirudh Venkataramanan hw_media_type = &pi->phy.media_type; 208dc49c772SAnirudh Venkataramanan hw_link_info = &pi->phy.link_info; 209dc49c772SAnirudh Venkataramanan hw_fc_info = &pi->fc; 210dc49c772SAnirudh Venkataramanan 211dc49c772SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status); 212dc49c772SAnirudh Venkataramanan cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS; 213dc49c772SAnirudh Venkataramanan resp = &desc.params.get_link_status; 214dc49c772SAnirudh Venkataramanan resp->cmd_flags = cpu_to_le16(cmd_flags); 215dc49c772SAnirudh Venkataramanan resp->lport_num = pi->lport; 216dc49c772SAnirudh Venkataramanan 217dc49c772SAnirudh Venkataramanan status = ice_aq_send_cmd(pi->hw, &desc, &link_data, sizeof(link_data), 218dc49c772SAnirudh Venkataramanan cd); 219dc49c772SAnirudh Venkataramanan 220dc49c772SAnirudh Venkataramanan if (status) 221dc49c772SAnirudh Venkataramanan return status; 222dc49c772SAnirudh Venkataramanan 223dc49c772SAnirudh Venkataramanan /* save off old link status information */ 224dc49c772SAnirudh Venkataramanan *hw_link_info_old = *hw_link_info; 225dc49c772SAnirudh Venkataramanan 226dc49c772SAnirudh Venkataramanan /* update current link status information */ 227dc49c772SAnirudh Venkataramanan hw_link_info->link_speed = le16_to_cpu(link_data.link_speed); 228dc49c772SAnirudh Venkataramanan hw_link_info->phy_type_low = le64_to_cpu(link_data.phy_type_low); 229dc49c772SAnirudh Venkataramanan *hw_media_type = ice_get_media_type(pi); 230dc49c772SAnirudh Venkataramanan hw_link_info->link_info = link_data.link_info; 231dc49c772SAnirudh Venkataramanan hw_link_info->an_info = link_data.an_info; 232dc49c772SAnirudh Venkataramanan hw_link_info->ext_info = link_data.ext_info; 233dc49c772SAnirudh Venkataramanan hw_link_info->max_frame_size = le16_to_cpu(link_data.max_frame_size); 234dc49c772SAnirudh Venkataramanan hw_link_info->pacing = link_data.cfg & ICE_AQ_CFG_PACING_M; 235dc49c772SAnirudh Venkataramanan 236dc49c772SAnirudh Venkataramanan /* update fc info */ 237dc49c772SAnirudh Venkataramanan tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX); 238dc49c772SAnirudh Venkataramanan rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX); 239dc49c772SAnirudh Venkataramanan if (tx_pause && rx_pause) 240dc49c772SAnirudh Venkataramanan hw_fc_info->current_mode = ICE_FC_FULL; 241dc49c772SAnirudh Venkataramanan else if (tx_pause) 242dc49c772SAnirudh Venkataramanan hw_fc_info->current_mode = ICE_FC_TX_PAUSE; 243dc49c772SAnirudh Venkataramanan else if (rx_pause) 244dc49c772SAnirudh Venkataramanan hw_fc_info->current_mode = ICE_FC_RX_PAUSE; 245dc49c772SAnirudh Venkataramanan else 246dc49c772SAnirudh Venkataramanan hw_fc_info->current_mode = ICE_FC_NONE; 247dc49c772SAnirudh Venkataramanan 248dc49c772SAnirudh Venkataramanan hw_link_info->lse_ena = 249dc49c772SAnirudh Venkataramanan !!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED)); 250dc49c772SAnirudh Venkataramanan 251dc49c772SAnirudh Venkataramanan /* save link status information */ 252dc49c772SAnirudh Venkataramanan if (link) 253dc49c772SAnirudh Venkataramanan *link = *hw_link_info; 254dc49c772SAnirudh Venkataramanan 255dc49c772SAnirudh Venkataramanan /* flag cleared so calling functions don't call AQ again */ 256dc49c772SAnirudh Venkataramanan pi->phy.get_link_info = false; 257dc49c772SAnirudh Venkataramanan 258dc49c772SAnirudh Venkataramanan return status; 259dc49c772SAnirudh Venkataramanan } 260dc49c772SAnirudh Venkataramanan 261dc49c772SAnirudh Venkataramanan /** 262f31e4b6fSAnirudh Venkataramanan * ice_init_hw - main hardware initialization routine 263f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 264f31e4b6fSAnirudh Venkataramanan */ 265f31e4b6fSAnirudh Venkataramanan enum ice_status ice_init_hw(struct ice_hw *hw) 266f31e4b6fSAnirudh Venkataramanan { 267dc49c772SAnirudh Venkataramanan struct ice_aqc_get_phy_caps_data *pcaps; 268f31e4b6fSAnirudh Venkataramanan enum ice_status status; 269dc49c772SAnirudh Venkataramanan u16 mac_buf_len; 270dc49c772SAnirudh Venkataramanan void *mac_buf; 271f31e4b6fSAnirudh Venkataramanan 272f31e4b6fSAnirudh Venkataramanan /* Set MAC type based on DeviceID */ 273f31e4b6fSAnirudh Venkataramanan status = ice_set_mac_type(hw); 274f31e4b6fSAnirudh Venkataramanan if (status) 275f31e4b6fSAnirudh Venkataramanan return status; 276f31e4b6fSAnirudh Venkataramanan 277f31e4b6fSAnirudh Venkataramanan hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) & 278f31e4b6fSAnirudh Venkataramanan PF_FUNC_RID_FUNC_NUM_M) >> 279f31e4b6fSAnirudh Venkataramanan PF_FUNC_RID_FUNC_NUM_S; 280f31e4b6fSAnirudh Venkataramanan 281f31e4b6fSAnirudh Venkataramanan status = ice_reset(hw, ICE_RESET_PFR); 282f31e4b6fSAnirudh Venkataramanan if (status) 283f31e4b6fSAnirudh Venkataramanan return status; 284f31e4b6fSAnirudh Venkataramanan 285940b61afSAnirudh Venkataramanan /* set these values to minimum allowed */ 286940b61afSAnirudh Venkataramanan hw->itr_gran_200 = ICE_ITR_GRAN_MIN_200; 287940b61afSAnirudh Venkataramanan hw->itr_gran_100 = ICE_ITR_GRAN_MIN_100; 288940b61afSAnirudh Venkataramanan hw->itr_gran_50 = ICE_ITR_GRAN_MIN_50; 289940b61afSAnirudh Venkataramanan hw->itr_gran_25 = ICE_ITR_GRAN_MIN_25; 290940b61afSAnirudh Venkataramanan 291f31e4b6fSAnirudh Venkataramanan status = ice_init_all_ctrlq(hw); 292f31e4b6fSAnirudh Venkataramanan if (status) 293f31e4b6fSAnirudh Venkataramanan goto err_unroll_cqinit; 294f31e4b6fSAnirudh Venkataramanan 295f31e4b6fSAnirudh Venkataramanan status = ice_clear_pf_cfg(hw); 296f31e4b6fSAnirudh Venkataramanan if (status) 297f31e4b6fSAnirudh Venkataramanan goto err_unroll_cqinit; 298f31e4b6fSAnirudh Venkataramanan 299f31e4b6fSAnirudh Venkataramanan ice_clear_pxe_mode(hw); 300f31e4b6fSAnirudh Venkataramanan 301f31e4b6fSAnirudh Venkataramanan status = ice_init_nvm(hw); 302f31e4b6fSAnirudh Venkataramanan if (status) 303f31e4b6fSAnirudh Venkataramanan goto err_unroll_cqinit; 304f31e4b6fSAnirudh Venkataramanan 3059c20346bSAnirudh Venkataramanan status = ice_get_caps(hw); 3069c20346bSAnirudh Venkataramanan if (status) 3079c20346bSAnirudh Venkataramanan goto err_unroll_cqinit; 3089c20346bSAnirudh Venkataramanan 3099c20346bSAnirudh Venkataramanan hw->port_info = devm_kzalloc(ice_hw_to_dev(hw), 3109c20346bSAnirudh Venkataramanan sizeof(*hw->port_info), GFP_KERNEL); 3119c20346bSAnirudh Venkataramanan if (!hw->port_info) { 3129c20346bSAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 3139c20346bSAnirudh Venkataramanan goto err_unroll_cqinit; 3149c20346bSAnirudh Venkataramanan } 3159c20346bSAnirudh Venkataramanan 3169c20346bSAnirudh Venkataramanan /* set the back pointer to hw */ 3179c20346bSAnirudh Venkataramanan hw->port_info->hw = hw; 3189c20346bSAnirudh Venkataramanan 3199c20346bSAnirudh Venkataramanan /* Initialize port_info struct with switch configuration data */ 3209c20346bSAnirudh Venkataramanan status = ice_get_initial_sw_cfg(hw); 3219c20346bSAnirudh Venkataramanan if (status) 3229c20346bSAnirudh Venkataramanan goto err_unroll_alloc; 3239c20346bSAnirudh Venkataramanan 3249c20346bSAnirudh Venkataramanan /* Query the allocated resources for tx scheduler */ 3259c20346bSAnirudh Venkataramanan status = ice_sched_query_res_alloc(hw); 3269c20346bSAnirudh Venkataramanan if (status) { 3279c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_SCHED, 3289c20346bSAnirudh Venkataramanan "Failed to get scheduler allocated resources\n"); 3299c20346bSAnirudh Venkataramanan goto err_unroll_alloc; 3309c20346bSAnirudh Venkataramanan } 3319c20346bSAnirudh Venkataramanan 332dc49c772SAnirudh Venkataramanan /* Initialize port_info struct with scheduler data */ 333dc49c772SAnirudh Venkataramanan status = ice_sched_init_port(hw->port_info); 334dc49c772SAnirudh Venkataramanan if (status) 335dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 336dc49c772SAnirudh Venkataramanan 337dc49c772SAnirudh Venkataramanan pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL); 338dc49c772SAnirudh Venkataramanan if (!pcaps) { 339dc49c772SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 340dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 341dc49c772SAnirudh Venkataramanan } 342dc49c772SAnirudh Venkataramanan 343dc49c772SAnirudh Venkataramanan /* Initialize port_info struct with PHY capabilities */ 344dc49c772SAnirudh Venkataramanan status = ice_aq_get_phy_caps(hw->port_info, false, 345dc49c772SAnirudh Venkataramanan ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL); 346dc49c772SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), pcaps); 347dc49c772SAnirudh Venkataramanan if (status) 348dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 349dc49c772SAnirudh Venkataramanan 350dc49c772SAnirudh Venkataramanan /* Initialize port_info struct with link information */ 351dc49c772SAnirudh Venkataramanan status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL); 352dc49c772SAnirudh Venkataramanan if (status) 353dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 354dc49c772SAnirudh Venkataramanan 355dc49c772SAnirudh Venkataramanan /* Get port MAC information */ 356dc49c772SAnirudh Venkataramanan mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp); 357dc49c772SAnirudh Venkataramanan mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL); 358dc49c772SAnirudh Venkataramanan 359dc49c772SAnirudh Venkataramanan if (!mac_buf) 360dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 361dc49c772SAnirudh Venkataramanan 362dc49c772SAnirudh Venkataramanan status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL); 363dc49c772SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), mac_buf); 364dc49c772SAnirudh Venkataramanan 365dc49c772SAnirudh Venkataramanan if (status) 366dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 367dc49c772SAnirudh Venkataramanan 368f31e4b6fSAnirudh Venkataramanan return 0; 369f31e4b6fSAnirudh Venkataramanan 370dc49c772SAnirudh Venkataramanan err_unroll_sched: 371dc49c772SAnirudh Venkataramanan ice_sched_cleanup_all(hw); 3729c20346bSAnirudh Venkataramanan err_unroll_alloc: 3739c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), hw->port_info); 374f31e4b6fSAnirudh Venkataramanan err_unroll_cqinit: 375f31e4b6fSAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 376f31e4b6fSAnirudh Venkataramanan return status; 377f31e4b6fSAnirudh Venkataramanan } 378f31e4b6fSAnirudh Venkataramanan 379f31e4b6fSAnirudh Venkataramanan /** 380f31e4b6fSAnirudh Venkataramanan * ice_deinit_hw - unroll initialization operations done by ice_init_hw 381f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 382f31e4b6fSAnirudh Venkataramanan */ 383f31e4b6fSAnirudh Venkataramanan void ice_deinit_hw(struct ice_hw *hw) 384f31e4b6fSAnirudh Venkataramanan { 3859c20346bSAnirudh Venkataramanan ice_sched_cleanup_all(hw); 386f31e4b6fSAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 387dc49c772SAnirudh Venkataramanan 3889c20346bSAnirudh Venkataramanan if (hw->port_info) { 3899c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), hw->port_info); 3909c20346bSAnirudh Venkataramanan hw->port_info = NULL; 3919c20346bSAnirudh Venkataramanan } 392f31e4b6fSAnirudh Venkataramanan } 393f31e4b6fSAnirudh Venkataramanan 394f31e4b6fSAnirudh Venkataramanan /** 395f31e4b6fSAnirudh Venkataramanan * ice_check_reset - Check to see if a global reset is complete 396f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 397f31e4b6fSAnirudh Venkataramanan */ 398f31e4b6fSAnirudh Venkataramanan enum ice_status ice_check_reset(struct ice_hw *hw) 399f31e4b6fSAnirudh Venkataramanan { 400f31e4b6fSAnirudh Venkataramanan u32 cnt, reg = 0, grst_delay; 401f31e4b6fSAnirudh Venkataramanan 402f31e4b6fSAnirudh Venkataramanan /* Poll for Device Active state in case a recent CORER, GLOBR, 403f31e4b6fSAnirudh Venkataramanan * or EMPR has occurred. The grst delay value is in 100ms units. 404f31e4b6fSAnirudh Venkataramanan * Add 1sec for outstanding AQ commands that can take a long time. 405f31e4b6fSAnirudh Venkataramanan */ 406f31e4b6fSAnirudh Venkataramanan grst_delay = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >> 407f31e4b6fSAnirudh Venkataramanan GLGEN_RSTCTL_GRSTDEL_S) + 10; 408f31e4b6fSAnirudh Venkataramanan 409f31e4b6fSAnirudh Venkataramanan for (cnt = 0; cnt < grst_delay; cnt++) { 410f31e4b6fSAnirudh Venkataramanan mdelay(100); 411f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, GLGEN_RSTAT); 412f31e4b6fSAnirudh Venkataramanan if (!(reg & GLGEN_RSTAT_DEVSTATE_M)) 413f31e4b6fSAnirudh Venkataramanan break; 414f31e4b6fSAnirudh Venkataramanan } 415f31e4b6fSAnirudh Venkataramanan 416f31e4b6fSAnirudh Venkataramanan if (cnt == grst_delay) { 417f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 418f31e4b6fSAnirudh Venkataramanan "Global reset polling failed to complete.\n"); 419f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 420f31e4b6fSAnirudh Venkataramanan } 421f31e4b6fSAnirudh Venkataramanan 422f31e4b6fSAnirudh Venkataramanan #define ICE_RESET_DONE_MASK (GLNVM_ULD_CORER_DONE_M | \ 423f31e4b6fSAnirudh Venkataramanan GLNVM_ULD_GLOBR_DONE_M) 424f31e4b6fSAnirudh Venkataramanan 425f31e4b6fSAnirudh Venkataramanan /* Device is Active; check Global Reset processes are done */ 426f31e4b6fSAnirudh Venkataramanan for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 427f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK; 428f31e4b6fSAnirudh Venkataramanan if (reg == ICE_RESET_DONE_MASK) { 429f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 430f31e4b6fSAnirudh Venkataramanan "Global reset processes done. %d\n", cnt); 431f31e4b6fSAnirudh Venkataramanan break; 432f31e4b6fSAnirudh Venkataramanan } 433f31e4b6fSAnirudh Venkataramanan mdelay(10); 434f31e4b6fSAnirudh Venkataramanan } 435f31e4b6fSAnirudh Venkataramanan 436f31e4b6fSAnirudh Venkataramanan if (cnt == ICE_PF_RESET_WAIT_COUNT) { 437f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 438f31e4b6fSAnirudh Venkataramanan "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n", 439f31e4b6fSAnirudh Venkataramanan reg); 440f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 441f31e4b6fSAnirudh Venkataramanan } 442f31e4b6fSAnirudh Venkataramanan 443f31e4b6fSAnirudh Venkataramanan return 0; 444f31e4b6fSAnirudh Venkataramanan } 445f31e4b6fSAnirudh Venkataramanan 446f31e4b6fSAnirudh Venkataramanan /** 447f31e4b6fSAnirudh Venkataramanan * ice_pf_reset - Reset the PF 448f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 449f31e4b6fSAnirudh Venkataramanan * 450f31e4b6fSAnirudh Venkataramanan * If a global reset has been triggered, this function checks 451f31e4b6fSAnirudh Venkataramanan * for its completion and then issues the PF reset 452f31e4b6fSAnirudh Venkataramanan */ 453f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_pf_reset(struct ice_hw *hw) 454f31e4b6fSAnirudh Venkataramanan { 455f31e4b6fSAnirudh Venkataramanan u32 cnt, reg; 456f31e4b6fSAnirudh Venkataramanan 457f31e4b6fSAnirudh Venkataramanan /* If at function entry a global reset was already in progress, i.e. 458f31e4b6fSAnirudh Venkataramanan * state is not 'device active' or any of the reset done bits are not 459f31e4b6fSAnirudh Venkataramanan * set in GLNVM_ULD, there is no need for a PF Reset; poll until the 460f31e4b6fSAnirudh Venkataramanan * global reset is done. 461f31e4b6fSAnirudh Venkataramanan */ 462f31e4b6fSAnirudh Venkataramanan if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) || 463f31e4b6fSAnirudh Venkataramanan (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) { 464f31e4b6fSAnirudh Venkataramanan /* poll on global reset currently in progress until done */ 465f31e4b6fSAnirudh Venkataramanan if (ice_check_reset(hw)) 466f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 467f31e4b6fSAnirudh Venkataramanan 468f31e4b6fSAnirudh Venkataramanan return 0; 469f31e4b6fSAnirudh Venkataramanan } 470f31e4b6fSAnirudh Venkataramanan 471f31e4b6fSAnirudh Venkataramanan /* Reset the PF */ 472f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, PFGEN_CTRL); 473f31e4b6fSAnirudh Venkataramanan 474f31e4b6fSAnirudh Venkataramanan wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M)); 475f31e4b6fSAnirudh Venkataramanan 476f31e4b6fSAnirudh Venkataramanan for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 477f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, PFGEN_CTRL); 478f31e4b6fSAnirudh Venkataramanan if (!(reg & PFGEN_CTRL_PFSWR_M)) 479f31e4b6fSAnirudh Venkataramanan break; 480f31e4b6fSAnirudh Venkataramanan 481f31e4b6fSAnirudh Venkataramanan mdelay(1); 482f31e4b6fSAnirudh Venkataramanan } 483f31e4b6fSAnirudh Venkataramanan 484f31e4b6fSAnirudh Venkataramanan if (cnt == ICE_PF_RESET_WAIT_COUNT) { 485f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 486f31e4b6fSAnirudh Venkataramanan "PF reset polling failed to complete.\n"); 487f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 488f31e4b6fSAnirudh Venkataramanan } 489f31e4b6fSAnirudh Venkataramanan 490f31e4b6fSAnirudh Venkataramanan return 0; 491f31e4b6fSAnirudh Venkataramanan } 492f31e4b6fSAnirudh Venkataramanan 493f31e4b6fSAnirudh Venkataramanan /** 494f31e4b6fSAnirudh Venkataramanan * ice_reset - Perform different types of reset 495f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 496f31e4b6fSAnirudh Venkataramanan * @req: reset request 497f31e4b6fSAnirudh Venkataramanan * 498f31e4b6fSAnirudh Venkataramanan * This function triggers a reset as specified by the req parameter. 499f31e4b6fSAnirudh Venkataramanan * 500f31e4b6fSAnirudh Venkataramanan * Note: 501f31e4b6fSAnirudh Venkataramanan * If anything other than a PF reset is triggered, PXE mode is restored. 502f31e4b6fSAnirudh Venkataramanan * This has to be cleared using ice_clear_pxe_mode again, once the AQ 503f31e4b6fSAnirudh Venkataramanan * interface has been restored in the rebuild flow. 504f31e4b6fSAnirudh Venkataramanan */ 505f31e4b6fSAnirudh Venkataramanan enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req) 506f31e4b6fSAnirudh Venkataramanan { 507f31e4b6fSAnirudh Venkataramanan u32 val = 0; 508f31e4b6fSAnirudh Venkataramanan 509f31e4b6fSAnirudh Venkataramanan switch (req) { 510f31e4b6fSAnirudh Venkataramanan case ICE_RESET_PFR: 511f31e4b6fSAnirudh Venkataramanan return ice_pf_reset(hw); 512f31e4b6fSAnirudh Venkataramanan case ICE_RESET_CORER: 513f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n"); 514f31e4b6fSAnirudh Venkataramanan val = GLGEN_RTRIG_CORER_M; 515f31e4b6fSAnirudh Venkataramanan break; 516f31e4b6fSAnirudh Venkataramanan case ICE_RESET_GLOBR: 517f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n"); 518f31e4b6fSAnirudh Venkataramanan val = GLGEN_RTRIG_GLOBR_M; 519f31e4b6fSAnirudh Venkataramanan break; 520f31e4b6fSAnirudh Venkataramanan } 521f31e4b6fSAnirudh Venkataramanan 522f31e4b6fSAnirudh Venkataramanan val |= rd32(hw, GLGEN_RTRIG); 523f31e4b6fSAnirudh Venkataramanan wr32(hw, GLGEN_RTRIG, val); 524f31e4b6fSAnirudh Venkataramanan ice_flush(hw); 525f31e4b6fSAnirudh Venkataramanan 526f31e4b6fSAnirudh Venkataramanan /* wait for the FW to be ready */ 527f31e4b6fSAnirudh Venkataramanan return ice_check_reset(hw); 528f31e4b6fSAnirudh Venkataramanan } 529f31e4b6fSAnirudh Venkataramanan 5307ec59eeaSAnirudh Venkataramanan /** 5317ec59eeaSAnirudh Venkataramanan * ice_debug_cq 5327ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hardware structure 5337ec59eeaSAnirudh Venkataramanan * @mask: debug mask 5347ec59eeaSAnirudh Venkataramanan * @desc: pointer to control queue descriptor 5357ec59eeaSAnirudh Venkataramanan * @buf: pointer to command buffer 5367ec59eeaSAnirudh Venkataramanan * @buf_len: max length of buf 5377ec59eeaSAnirudh Venkataramanan * 5387ec59eeaSAnirudh Venkataramanan * Dumps debug log about control command with descriptor contents. 5397ec59eeaSAnirudh Venkataramanan */ 5407ec59eeaSAnirudh Venkataramanan void ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc, 5417ec59eeaSAnirudh Venkataramanan void *buf, u16 buf_len) 5427ec59eeaSAnirudh Venkataramanan { 5437ec59eeaSAnirudh Venkataramanan struct ice_aq_desc *cq_desc = (struct ice_aq_desc *)desc; 5447ec59eeaSAnirudh Venkataramanan u16 len; 5457ec59eeaSAnirudh Venkataramanan 5467ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 5477ec59eeaSAnirudh Venkataramanan if (!(mask & hw->debug_mask)) 5487ec59eeaSAnirudh Venkataramanan return; 5497ec59eeaSAnirudh Venkataramanan #endif 5507ec59eeaSAnirudh Venkataramanan 5517ec59eeaSAnirudh Venkataramanan if (!desc) 5527ec59eeaSAnirudh Venkataramanan return; 5537ec59eeaSAnirudh Venkataramanan 5547ec59eeaSAnirudh Venkataramanan len = le16_to_cpu(cq_desc->datalen); 5557ec59eeaSAnirudh Venkataramanan 5567ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, 5577ec59eeaSAnirudh Venkataramanan "CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n", 5587ec59eeaSAnirudh Venkataramanan le16_to_cpu(cq_desc->opcode), 5597ec59eeaSAnirudh Venkataramanan le16_to_cpu(cq_desc->flags), 5607ec59eeaSAnirudh Venkataramanan le16_to_cpu(cq_desc->datalen), le16_to_cpu(cq_desc->retval)); 5617ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n", 5627ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->cookie_high), 5637ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->cookie_low)); 5647ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n", 5657ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.param0), 5667ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.param1)); 5677ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n", 5687ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.addr_high), 5697ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.addr_low)); 5707ec59eeaSAnirudh Venkataramanan if (buf && cq_desc->datalen != 0) { 5717ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "Buffer:\n"); 5727ec59eeaSAnirudh Venkataramanan if (buf_len < len) 5737ec59eeaSAnirudh Venkataramanan len = buf_len; 5747ec59eeaSAnirudh Venkataramanan 5757ec59eeaSAnirudh Venkataramanan ice_debug_array(hw, mask, 16, 1, (u8 *)buf, len); 5767ec59eeaSAnirudh Venkataramanan } 5777ec59eeaSAnirudh Venkataramanan } 5787ec59eeaSAnirudh Venkataramanan 5797ec59eeaSAnirudh Venkataramanan /* FW Admin Queue command wrappers */ 5807ec59eeaSAnirudh Venkataramanan 5817ec59eeaSAnirudh Venkataramanan /** 5827ec59eeaSAnirudh Venkataramanan * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue 5837ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hw struct 5847ec59eeaSAnirudh Venkataramanan * @desc: descriptor describing the command 5857ec59eeaSAnirudh Venkataramanan * @buf: buffer to use for indirect commands (NULL for direct commands) 5867ec59eeaSAnirudh Venkataramanan * @buf_size: size of buffer for indirect commands (0 for direct commands) 5877ec59eeaSAnirudh Venkataramanan * @cd: pointer to command details structure 5887ec59eeaSAnirudh Venkataramanan * 5897ec59eeaSAnirudh Venkataramanan * Helper function to send FW Admin Queue commands to the FW Admin Queue. 5907ec59eeaSAnirudh Venkataramanan */ 5917ec59eeaSAnirudh Venkataramanan enum ice_status 5927ec59eeaSAnirudh Venkataramanan ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf, 5937ec59eeaSAnirudh Venkataramanan u16 buf_size, struct ice_sq_cd *cd) 5947ec59eeaSAnirudh Venkataramanan { 5957ec59eeaSAnirudh Venkataramanan return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd); 5967ec59eeaSAnirudh Venkataramanan } 5977ec59eeaSAnirudh Venkataramanan 5987ec59eeaSAnirudh Venkataramanan /** 5997ec59eeaSAnirudh Venkataramanan * ice_aq_get_fw_ver 6007ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hw struct 6017ec59eeaSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 6027ec59eeaSAnirudh Venkataramanan * 6037ec59eeaSAnirudh Venkataramanan * Get the firmware version (0x0001) from the admin queue commands 6047ec59eeaSAnirudh Venkataramanan */ 6057ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd) 6067ec59eeaSAnirudh Venkataramanan { 6077ec59eeaSAnirudh Venkataramanan struct ice_aqc_get_ver *resp; 6087ec59eeaSAnirudh Venkataramanan struct ice_aq_desc desc; 6097ec59eeaSAnirudh Venkataramanan enum ice_status status; 6107ec59eeaSAnirudh Venkataramanan 6117ec59eeaSAnirudh Venkataramanan resp = &desc.params.get_ver; 6127ec59eeaSAnirudh Venkataramanan 6137ec59eeaSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver); 6147ec59eeaSAnirudh Venkataramanan 6157ec59eeaSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 6167ec59eeaSAnirudh Venkataramanan 6177ec59eeaSAnirudh Venkataramanan if (!status) { 6187ec59eeaSAnirudh Venkataramanan hw->fw_branch = resp->fw_branch; 6197ec59eeaSAnirudh Venkataramanan hw->fw_maj_ver = resp->fw_major; 6207ec59eeaSAnirudh Venkataramanan hw->fw_min_ver = resp->fw_minor; 6217ec59eeaSAnirudh Venkataramanan hw->fw_patch = resp->fw_patch; 6227ec59eeaSAnirudh Venkataramanan hw->fw_build = le32_to_cpu(resp->fw_build); 6237ec59eeaSAnirudh Venkataramanan hw->api_branch = resp->api_branch; 6247ec59eeaSAnirudh Venkataramanan hw->api_maj_ver = resp->api_major; 6257ec59eeaSAnirudh Venkataramanan hw->api_min_ver = resp->api_minor; 6267ec59eeaSAnirudh Venkataramanan hw->api_patch = resp->api_patch; 6277ec59eeaSAnirudh Venkataramanan } 6287ec59eeaSAnirudh Venkataramanan 6297ec59eeaSAnirudh Venkataramanan return status; 6307ec59eeaSAnirudh Venkataramanan } 6317ec59eeaSAnirudh Venkataramanan 6327ec59eeaSAnirudh Venkataramanan /** 6337ec59eeaSAnirudh Venkataramanan * ice_aq_q_shutdown 6347ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hw struct 6357ec59eeaSAnirudh Venkataramanan * @unloading: is the driver unloading itself 6367ec59eeaSAnirudh Venkataramanan * 6377ec59eeaSAnirudh Venkataramanan * Tell the Firmware that we're shutting down the AdminQ and whether 6387ec59eeaSAnirudh Venkataramanan * or not the driver is unloading as well (0x0003). 6397ec59eeaSAnirudh Venkataramanan */ 6407ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading) 6417ec59eeaSAnirudh Venkataramanan { 6427ec59eeaSAnirudh Venkataramanan struct ice_aqc_q_shutdown *cmd; 6437ec59eeaSAnirudh Venkataramanan struct ice_aq_desc desc; 6447ec59eeaSAnirudh Venkataramanan 6457ec59eeaSAnirudh Venkataramanan cmd = &desc.params.q_shutdown; 6467ec59eeaSAnirudh Venkataramanan 6477ec59eeaSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown); 6487ec59eeaSAnirudh Venkataramanan 6497ec59eeaSAnirudh Venkataramanan if (unloading) 6507ec59eeaSAnirudh Venkataramanan cmd->driver_unloading = cpu_to_le32(ICE_AQC_DRIVER_UNLOADING); 6517ec59eeaSAnirudh Venkataramanan 6527ec59eeaSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 6537ec59eeaSAnirudh Venkataramanan } 654f31e4b6fSAnirudh Venkataramanan 655f31e4b6fSAnirudh Venkataramanan /** 656f31e4b6fSAnirudh Venkataramanan * ice_aq_req_res 657f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 658f31e4b6fSAnirudh Venkataramanan * @res: resource id 659f31e4b6fSAnirudh Venkataramanan * @access: access type 660f31e4b6fSAnirudh Venkataramanan * @sdp_number: resource number 661f31e4b6fSAnirudh Venkataramanan * @timeout: the maximum time in ms that the driver may hold the resource 662f31e4b6fSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 663f31e4b6fSAnirudh Venkataramanan * 664f31e4b6fSAnirudh Venkataramanan * requests common resource using the admin queue commands (0x0008) 665f31e4b6fSAnirudh Venkataramanan */ 666f31e4b6fSAnirudh Venkataramanan static enum ice_status 667f31e4b6fSAnirudh Venkataramanan ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res, 668f31e4b6fSAnirudh Venkataramanan enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout, 669f31e4b6fSAnirudh Venkataramanan struct ice_sq_cd *cd) 670f31e4b6fSAnirudh Venkataramanan { 671f31e4b6fSAnirudh Venkataramanan struct ice_aqc_req_res *cmd_resp; 672f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 673f31e4b6fSAnirudh Venkataramanan enum ice_status status; 674f31e4b6fSAnirudh Venkataramanan 675f31e4b6fSAnirudh Venkataramanan cmd_resp = &desc.params.res_owner; 676f31e4b6fSAnirudh Venkataramanan 677f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res); 678f31e4b6fSAnirudh Venkataramanan 679f31e4b6fSAnirudh Venkataramanan cmd_resp->res_id = cpu_to_le16(res); 680f31e4b6fSAnirudh Venkataramanan cmd_resp->access_type = cpu_to_le16(access); 681f31e4b6fSAnirudh Venkataramanan cmd_resp->res_number = cpu_to_le32(sdp_number); 682f31e4b6fSAnirudh Venkataramanan 683f31e4b6fSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 684f31e4b6fSAnirudh Venkataramanan /* The completion specifies the maximum time in ms that the driver 685f31e4b6fSAnirudh Venkataramanan * may hold the resource in the Timeout field. 686f31e4b6fSAnirudh Venkataramanan * If the resource is held by someone else, the command completes with 687f31e4b6fSAnirudh Venkataramanan * busy return value and the timeout field indicates the maximum time 688f31e4b6fSAnirudh Venkataramanan * the current owner of the resource has to free it. 689f31e4b6fSAnirudh Venkataramanan */ 690f31e4b6fSAnirudh Venkataramanan if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) 691f31e4b6fSAnirudh Venkataramanan *timeout = le32_to_cpu(cmd_resp->timeout); 692f31e4b6fSAnirudh Venkataramanan 693f31e4b6fSAnirudh Venkataramanan return status; 694f31e4b6fSAnirudh Venkataramanan } 695f31e4b6fSAnirudh Venkataramanan 696f31e4b6fSAnirudh Venkataramanan /** 697f31e4b6fSAnirudh Venkataramanan * ice_aq_release_res 698f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 699f31e4b6fSAnirudh Venkataramanan * @res: resource id 700f31e4b6fSAnirudh Venkataramanan * @sdp_number: resource number 701f31e4b6fSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 702f31e4b6fSAnirudh Venkataramanan * 703f31e4b6fSAnirudh Venkataramanan * release common resource using the admin queue commands (0x0009) 704f31e4b6fSAnirudh Venkataramanan */ 705f31e4b6fSAnirudh Venkataramanan static enum ice_status 706f31e4b6fSAnirudh Venkataramanan ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number, 707f31e4b6fSAnirudh Venkataramanan struct ice_sq_cd *cd) 708f31e4b6fSAnirudh Venkataramanan { 709f31e4b6fSAnirudh Venkataramanan struct ice_aqc_req_res *cmd; 710f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 711f31e4b6fSAnirudh Venkataramanan 712f31e4b6fSAnirudh Venkataramanan cmd = &desc.params.res_owner; 713f31e4b6fSAnirudh Venkataramanan 714f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res); 715f31e4b6fSAnirudh Venkataramanan 716f31e4b6fSAnirudh Venkataramanan cmd->res_id = cpu_to_le16(res); 717f31e4b6fSAnirudh Venkataramanan cmd->res_number = cpu_to_le32(sdp_number); 718f31e4b6fSAnirudh Venkataramanan 719f31e4b6fSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 720f31e4b6fSAnirudh Venkataramanan } 721f31e4b6fSAnirudh Venkataramanan 722f31e4b6fSAnirudh Venkataramanan /** 723f31e4b6fSAnirudh Venkataramanan * ice_acquire_res 724f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 725f31e4b6fSAnirudh Venkataramanan * @res: resource id 726f31e4b6fSAnirudh Venkataramanan * @access: access type (read or write) 727f31e4b6fSAnirudh Venkataramanan * 728f31e4b6fSAnirudh Venkataramanan * This function will attempt to acquire the ownership of a resource. 729f31e4b6fSAnirudh Venkataramanan */ 730f31e4b6fSAnirudh Venkataramanan enum ice_status 731f31e4b6fSAnirudh Venkataramanan ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, 732f31e4b6fSAnirudh Venkataramanan enum ice_aq_res_access_type access) 733f31e4b6fSAnirudh Venkataramanan { 734f31e4b6fSAnirudh Venkataramanan #define ICE_RES_POLLING_DELAY_MS 10 735f31e4b6fSAnirudh Venkataramanan u32 delay = ICE_RES_POLLING_DELAY_MS; 736f31e4b6fSAnirudh Venkataramanan enum ice_status status; 737f31e4b6fSAnirudh Venkataramanan u32 time_left = 0; 738f31e4b6fSAnirudh Venkataramanan u32 timeout; 739f31e4b6fSAnirudh Venkataramanan 740f31e4b6fSAnirudh Venkataramanan status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 741f31e4b6fSAnirudh Venkataramanan 742f31e4b6fSAnirudh Venkataramanan /* An admin queue return code of ICE_AQ_RC_EEXIST means that another 743f31e4b6fSAnirudh Venkataramanan * driver has previously acquired the resource and performed any 744f31e4b6fSAnirudh Venkataramanan * necessary updates; in this case the caller does not obtain the 745f31e4b6fSAnirudh Venkataramanan * resource and has no further work to do. 746f31e4b6fSAnirudh Venkataramanan */ 747f31e4b6fSAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) { 748f31e4b6fSAnirudh Venkataramanan status = ICE_ERR_AQ_NO_WORK; 749f31e4b6fSAnirudh Venkataramanan goto ice_acquire_res_exit; 750f31e4b6fSAnirudh Venkataramanan } 751f31e4b6fSAnirudh Venkataramanan 752f31e4b6fSAnirudh Venkataramanan if (status) 753f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, 754f31e4b6fSAnirudh Venkataramanan "resource %d acquire type %d failed.\n", res, access); 755f31e4b6fSAnirudh Venkataramanan 756f31e4b6fSAnirudh Venkataramanan /* If necessary, poll until the current lock owner timeouts */ 757f31e4b6fSAnirudh Venkataramanan timeout = time_left; 758f31e4b6fSAnirudh Venkataramanan while (status && timeout && time_left) { 759f31e4b6fSAnirudh Venkataramanan mdelay(delay); 760f31e4b6fSAnirudh Venkataramanan timeout = (timeout > delay) ? timeout - delay : 0; 761f31e4b6fSAnirudh Venkataramanan status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 762f31e4b6fSAnirudh Venkataramanan 763f31e4b6fSAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) { 764f31e4b6fSAnirudh Venkataramanan /* lock free, but no work to do */ 765f31e4b6fSAnirudh Venkataramanan status = ICE_ERR_AQ_NO_WORK; 766f31e4b6fSAnirudh Venkataramanan break; 767f31e4b6fSAnirudh Venkataramanan } 768f31e4b6fSAnirudh Venkataramanan 769f31e4b6fSAnirudh Venkataramanan if (!status) 770f31e4b6fSAnirudh Venkataramanan /* lock acquired */ 771f31e4b6fSAnirudh Venkataramanan break; 772f31e4b6fSAnirudh Venkataramanan } 773f31e4b6fSAnirudh Venkataramanan if (status && status != ICE_ERR_AQ_NO_WORK) 774f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n"); 775f31e4b6fSAnirudh Venkataramanan 776f31e4b6fSAnirudh Venkataramanan ice_acquire_res_exit: 777f31e4b6fSAnirudh Venkataramanan if (status == ICE_ERR_AQ_NO_WORK) { 778f31e4b6fSAnirudh Venkataramanan if (access == ICE_RES_WRITE) 779f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, 780f31e4b6fSAnirudh Venkataramanan "resource indicates no work to do.\n"); 781f31e4b6fSAnirudh Venkataramanan else 782f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, 783f31e4b6fSAnirudh Venkataramanan "Warning: ICE_ERR_AQ_NO_WORK not expected\n"); 784f31e4b6fSAnirudh Venkataramanan } 785f31e4b6fSAnirudh Venkataramanan return status; 786f31e4b6fSAnirudh Venkataramanan } 787f31e4b6fSAnirudh Venkataramanan 788f31e4b6fSAnirudh Venkataramanan /** 789f31e4b6fSAnirudh Venkataramanan * ice_release_res 790f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 791f31e4b6fSAnirudh Venkataramanan * @res: resource id 792f31e4b6fSAnirudh Venkataramanan * 793f31e4b6fSAnirudh Venkataramanan * This function will release a resource using the proper Admin Command. 794f31e4b6fSAnirudh Venkataramanan */ 795f31e4b6fSAnirudh Venkataramanan void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res) 796f31e4b6fSAnirudh Venkataramanan { 797f31e4b6fSAnirudh Venkataramanan enum ice_status status; 798f31e4b6fSAnirudh Venkataramanan u32 total_delay = 0; 799f31e4b6fSAnirudh Venkataramanan 800f31e4b6fSAnirudh Venkataramanan status = ice_aq_release_res(hw, res, 0, NULL); 801f31e4b6fSAnirudh Venkataramanan 802f31e4b6fSAnirudh Venkataramanan /* there are some rare cases when trying to release the resource 803f31e4b6fSAnirudh Venkataramanan * results in an admin Q timeout, so handle them correctly 804f31e4b6fSAnirudh Venkataramanan */ 805f31e4b6fSAnirudh Venkataramanan while ((status == ICE_ERR_AQ_TIMEOUT) && 806f31e4b6fSAnirudh Venkataramanan (total_delay < hw->adminq.sq_cmd_timeout)) { 807f31e4b6fSAnirudh Venkataramanan mdelay(1); 808f31e4b6fSAnirudh Venkataramanan status = ice_aq_release_res(hw, res, 0, NULL); 809f31e4b6fSAnirudh Venkataramanan total_delay++; 810f31e4b6fSAnirudh Venkataramanan } 811f31e4b6fSAnirudh Venkataramanan } 812f31e4b6fSAnirudh Venkataramanan 813f31e4b6fSAnirudh Venkataramanan /** 8149c20346bSAnirudh Venkataramanan * ice_parse_caps - parse function/device capabilities 8159c20346bSAnirudh Venkataramanan * @hw: pointer to the hw struct 8169c20346bSAnirudh Venkataramanan * @buf: pointer to a buffer containing function/device capability records 8179c20346bSAnirudh Venkataramanan * @cap_count: number of capability records in the list 8189c20346bSAnirudh Venkataramanan * @opc: type of capabilities list to parse 8199c20346bSAnirudh Venkataramanan * 8209c20346bSAnirudh Venkataramanan * Helper function to parse function(0x000a)/device(0x000b) capabilities list. 8219c20346bSAnirudh Venkataramanan */ 8229c20346bSAnirudh Venkataramanan static void 8239c20346bSAnirudh Venkataramanan ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count, 8249c20346bSAnirudh Venkataramanan enum ice_adminq_opc opc) 8259c20346bSAnirudh Venkataramanan { 8269c20346bSAnirudh Venkataramanan struct ice_aqc_list_caps_elem *cap_resp; 8279c20346bSAnirudh Venkataramanan struct ice_hw_func_caps *func_p = NULL; 8289c20346bSAnirudh Venkataramanan struct ice_hw_dev_caps *dev_p = NULL; 8299c20346bSAnirudh Venkataramanan struct ice_hw_common_caps *caps; 8309c20346bSAnirudh Venkataramanan u32 i; 8319c20346bSAnirudh Venkataramanan 8329c20346bSAnirudh Venkataramanan if (!buf) 8339c20346bSAnirudh Venkataramanan return; 8349c20346bSAnirudh Venkataramanan 8359c20346bSAnirudh Venkataramanan cap_resp = (struct ice_aqc_list_caps_elem *)buf; 8369c20346bSAnirudh Venkataramanan 8379c20346bSAnirudh Venkataramanan if (opc == ice_aqc_opc_list_dev_caps) { 8389c20346bSAnirudh Venkataramanan dev_p = &hw->dev_caps; 8399c20346bSAnirudh Venkataramanan caps = &dev_p->common_cap; 8409c20346bSAnirudh Venkataramanan } else if (opc == ice_aqc_opc_list_func_caps) { 8419c20346bSAnirudh Venkataramanan func_p = &hw->func_caps; 8429c20346bSAnirudh Venkataramanan caps = &func_p->common_cap; 8439c20346bSAnirudh Venkataramanan } else { 8449c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "wrong opcode\n"); 8459c20346bSAnirudh Venkataramanan return; 8469c20346bSAnirudh Venkataramanan } 8479c20346bSAnirudh Venkataramanan 8489c20346bSAnirudh Venkataramanan for (i = 0; caps && i < cap_count; i++, cap_resp++) { 8499c20346bSAnirudh Venkataramanan u32 logical_id = le32_to_cpu(cap_resp->logical_id); 8509c20346bSAnirudh Venkataramanan u32 phys_id = le32_to_cpu(cap_resp->phys_id); 8519c20346bSAnirudh Venkataramanan u32 number = le32_to_cpu(cap_resp->number); 8529c20346bSAnirudh Venkataramanan u16 cap = le16_to_cpu(cap_resp->cap); 8539c20346bSAnirudh Venkataramanan 8549c20346bSAnirudh Venkataramanan switch (cap) { 8559c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_VSI: 8569c20346bSAnirudh Venkataramanan if (dev_p) { 8579c20346bSAnirudh Venkataramanan dev_p->num_vsi_allocd_to_host = number; 8589c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8599c20346bSAnirudh Venkataramanan "HW caps: Dev.VSI cnt = %d\n", 8609c20346bSAnirudh Venkataramanan dev_p->num_vsi_allocd_to_host); 8619c20346bSAnirudh Venkataramanan } else if (func_p) { 8629c20346bSAnirudh Venkataramanan func_p->guaranteed_num_vsi = number; 8639c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8649c20346bSAnirudh Venkataramanan "HW caps: Func.VSI cnt = %d\n", 8659c20346bSAnirudh Venkataramanan func_p->guaranteed_num_vsi); 8669c20346bSAnirudh Venkataramanan } 8679c20346bSAnirudh Venkataramanan break; 8689c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_RSS: 8699c20346bSAnirudh Venkataramanan caps->rss_table_size = number; 8709c20346bSAnirudh Venkataramanan caps->rss_table_entry_width = logical_id; 8719c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8729c20346bSAnirudh Venkataramanan "HW caps: RSS table size = %d\n", 8739c20346bSAnirudh Venkataramanan caps->rss_table_size); 8749c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8759c20346bSAnirudh Venkataramanan "HW caps: RSS table width = %d\n", 8769c20346bSAnirudh Venkataramanan caps->rss_table_entry_width); 8779c20346bSAnirudh Venkataramanan break; 8789c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_RXQS: 8799c20346bSAnirudh Venkataramanan caps->num_rxq = number; 8809c20346bSAnirudh Venkataramanan caps->rxq_first_id = phys_id; 8819c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8829c20346bSAnirudh Venkataramanan "HW caps: Num Rx Qs = %d\n", caps->num_rxq); 8839c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8849c20346bSAnirudh Venkataramanan "HW caps: Rx first queue ID = %d\n", 8859c20346bSAnirudh Venkataramanan caps->rxq_first_id); 8869c20346bSAnirudh Venkataramanan break; 8879c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_TXQS: 8889c20346bSAnirudh Venkataramanan caps->num_txq = number; 8899c20346bSAnirudh Venkataramanan caps->txq_first_id = phys_id; 8909c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8919c20346bSAnirudh Venkataramanan "HW caps: Num Tx Qs = %d\n", caps->num_txq); 8929c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8939c20346bSAnirudh Venkataramanan "HW caps: Tx first queue ID = %d\n", 8949c20346bSAnirudh Venkataramanan caps->txq_first_id); 8959c20346bSAnirudh Venkataramanan break; 8969c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_MSIX: 8979c20346bSAnirudh Venkataramanan caps->num_msix_vectors = number; 8989c20346bSAnirudh Venkataramanan caps->msix_vector_first_id = phys_id; 8999c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9009c20346bSAnirudh Venkataramanan "HW caps: MSIX vector count = %d\n", 9019c20346bSAnirudh Venkataramanan caps->num_msix_vectors); 9029c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9039c20346bSAnirudh Venkataramanan "HW caps: MSIX first vector index = %d\n", 9049c20346bSAnirudh Venkataramanan caps->msix_vector_first_id); 9059c20346bSAnirudh Venkataramanan break; 9069c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_MAX_MTU: 9079c20346bSAnirudh Venkataramanan caps->max_mtu = number; 9089c20346bSAnirudh Venkataramanan if (dev_p) 9099c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9109c20346bSAnirudh Venkataramanan "HW caps: Dev.MaxMTU = %d\n", 9119c20346bSAnirudh Venkataramanan caps->max_mtu); 9129c20346bSAnirudh Venkataramanan else if (func_p) 9139c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9149c20346bSAnirudh Venkataramanan "HW caps: func.MaxMTU = %d\n", 9159c20346bSAnirudh Venkataramanan caps->max_mtu); 9169c20346bSAnirudh Venkataramanan break; 9179c20346bSAnirudh Venkataramanan default: 9189c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9199c20346bSAnirudh Venkataramanan "HW caps: Unknown capability[%d]: 0x%x\n", i, 9209c20346bSAnirudh Venkataramanan cap); 9219c20346bSAnirudh Venkataramanan break; 9229c20346bSAnirudh Venkataramanan } 9239c20346bSAnirudh Venkataramanan } 9249c20346bSAnirudh Venkataramanan } 9259c20346bSAnirudh Venkataramanan 9269c20346bSAnirudh Venkataramanan /** 9279c20346bSAnirudh Venkataramanan * ice_aq_discover_caps - query function/device capabilities 9289c20346bSAnirudh Venkataramanan * @hw: pointer to the hw struct 9299c20346bSAnirudh Venkataramanan * @buf: a virtual buffer to hold the capabilities 9309c20346bSAnirudh Venkataramanan * @buf_size: Size of the virtual buffer 9319c20346bSAnirudh Venkataramanan * @data_size: Size of the returned data, or buf size needed if AQ err==ENOMEM 9329c20346bSAnirudh Venkataramanan * @opc: capabilities type to discover - pass in the command opcode 9339c20346bSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 9349c20346bSAnirudh Venkataramanan * 9359c20346bSAnirudh Venkataramanan * Get the function(0x000a)/device(0x000b) capabilities description from 9369c20346bSAnirudh Venkataramanan * the firmware. 9379c20346bSAnirudh Venkataramanan */ 9389c20346bSAnirudh Venkataramanan static enum ice_status 9399c20346bSAnirudh Venkataramanan ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u16 *data_size, 9409c20346bSAnirudh Venkataramanan enum ice_adminq_opc opc, struct ice_sq_cd *cd) 9419c20346bSAnirudh Venkataramanan { 9429c20346bSAnirudh Venkataramanan struct ice_aqc_list_caps *cmd; 9439c20346bSAnirudh Venkataramanan struct ice_aq_desc desc; 9449c20346bSAnirudh Venkataramanan enum ice_status status; 9459c20346bSAnirudh Venkataramanan 9469c20346bSAnirudh Venkataramanan cmd = &desc.params.get_cap; 9479c20346bSAnirudh Venkataramanan 9489c20346bSAnirudh Venkataramanan if (opc != ice_aqc_opc_list_func_caps && 9499c20346bSAnirudh Venkataramanan opc != ice_aqc_opc_list_dev_caps) 9509c20346bSAnirudh Venkataramanan return ICE_ERR_PARAM; 9519c20346bSAnirudh Venkataramanan 9529c20346bSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, opc); 9539c20346bSAnirudh Venkataramanan 9549c20346bSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 9559c20346bSAnirudh Venkataramanan if (!status) 9569c20346bSAnirudh Venkataramanan ice_parse_caps(hw, buf, le32_to_cpu(cmd->count), opc); 9579c20346bSAnirudh Venkataramanan *data_size = le16_to_cpu(desc.datalen); 9589c20346bSAnirudh Venkataramanan 9599c20346bSAnirudh Venkataramanan return status; 9609c20346bSAnirudh Venkataramanan } 9619c20346bSAnirudh Venkataramanan 9629c20346bSAnirudh Venkataramanan /** 9639c20346bSAnirudh Venkataramanan * ice_get_caps - get info about the HW 9649c20346bSAnirudh Venkataramanan * @hw: pointer to the hardware structure 9659c20346bSAnirudh Venkataramanan */ 9669c20346bSAnirudh Venkataramanan enum ice_status ice_get_caps(struct ice_hw *hw) 9679c20346bSAnirudh Venkataramanan { 9689c20346bSAnirudh Venkataramanan enum ice_status status; 9699c20346bSAnirudh Venkataramanan u16 data_size = 0; 9709c20346bSAnirudh Venkataramanan u16 cbuf_len; 9719c20346bSAnirudh Venkataramanan u8 retries; 9729c20346bSAnirudh Venkataramanan 9739c20346bSAnirudh Venkataramanan /* The driver doesn't know how many capabilities the device will return 9749c20346bSAnirudh Venkataramanan * so the buffer size required isn't known ahead of time. The driver 9759c20346bSAnirudh Venkataramanan * starts with cbuf_len and if this turns out to be insufficient, the 9769c20346bSAnirudh Venkataramanan * device returns ICE_AQ_RC_ENOMEM and also the buffer size it needs. 9779c20346bSAnirudh Venkataramanan * The driver then allocates the buffer of this size and retries the 9789c20346bSAnirudh Venkataramanan * operation. So it follows that the retry count is 2. 9799c20346bSAnirudh Venkataramanan */ 9809c20346bSAnirudh Venkataramanan #define ICE_GET_CAP_BUF_COUNT 40 9819c20346bSAnirudh Venkataramanan #define ICE_GET_CAP_RETRY_COUNT 2 9829c20346bSAnirudh Venkataramanan 9839c20346bSAnirudh Venkataramanan cbuf_len = ICE_GET_CAP_BUF_COUNT * 9849c20346bSAnirudh Venkataramanan sizeof(struct ice_aqc_list_caps_elem); 9859c20346bSAnirudh Venkataramanan 9869c20346bSAnirudh Venkataramanan retries = ICE_GET_CAP_RETRY_COUNT; 9879c20346bSAnirudh Venkataramanan 9889c20346bSAnirudh Venkataramanan do { 9899c20346bSAnirudh Venkataramanan void *cbuf; 9909c20346bSAnirudh Venkataramanan 9919c20346bSAnirudh Venkataramanan cbuf = devm_kzalloc(ice_hw_to_dev(hw), cbuf_len, GFP_KERNEL); 9929c20346bSAnirudh Venkataramanan if (!cbuf) 9939c20346bSAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 9949c20346bSAnirudh Venkataramanan 9959c20346bSAnirudh Venkataramanan status = ice_aq_discover_caps(hw, cbuf, cbuf_len, &data_size, 9969c20346bSAnirudh Venkataramanan ice_aqc_opc_list_func_caps, NULL); 9979c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), cbuf); 9989c20346bSAnirudh Venkataramanan 9999c20346bSAnirudh Venkataramanan if (!status || hw->adminq.sq_last_status != ICE_AQ_RC_ENOMEM) 10009c20346bSAnirudh Venkataramanan break; 10019c20346bSAnirudh Venkataramanan 10029c20346bSAnirudh Venkataramanan /* If ENOMEM is returned, try again with bigger buffer */ 10039c20346bSAnirudh Venkataramanan cbuf_len = data_size; 10049c20346bSAnirudh Venkataramanan } while (--retries); 10059c20346bSAnirudh Venkataramanan 10069c20346bSAnirudh Venkataramanan return status; 10079c20346bSAnirudh Venkataramanan } 10089c20346bSAnirudh Venkataramanan 10099c20346bSAnirudh Venkataramanan /** 1010f31e4b6fSAnirudh Venkataramanan * ice_aq_clear_pxe_mode 1011f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 1012f31e4b6fSAnirudh Venkataramanan * 1013f31e4b6fSAnirudh Venkataramanan * Tell the firmware that the driver is taking over from PXE (0x0110). 1014f31e4b6fSAnirudh Venkataramanan */ 1015f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw) 1016f31e4b6fSAnirudh Venkataramanan { 1017f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 1018f31e4b6fSAnirudh Venkataramanan 1019f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode); 1020f31e4b6fSAnirudh Venkataramanan desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT; 1021f31e4b6fSAnirudh Venkataramanan 1022f31e4b6fSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 1023f31e4b6fSAnirudh Venkataramanan } 1024f31e4b6fSAnirudh Venkataramanan 1025f31e4b6fSAnirudh Venkataramanan /** 1026f31e4b6fSAnirudh Venkataramanan * ice_clear_pxe_mode - clear pxe operations mode 1027f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 1028f31e4b6fSAnirudh Venkataramanan * 1029f31e4b6fSAnirudh Venkataramanan * Make sure all PXE mode settings are cleared, including things 1030f31e4b6fSAnirudh Venkataramanan * like descriptor fetch/write-back mode. 1031f31e4b6fSAnirudh Venkataramanan */ 1032f31e4b6fSAnirudh Venkataramanan void ice_clear_pxe_mode(struct ice_hw *hw) 1033f31e4b6fSAnirudh Venkataramanan { 1034f31e4b6fSAnirudh Venkataramanan if (ice_check_sq_alive(hw, &hw->adminq)) 1035f31e4b6fSAnirudh Venkataramanan ice_aq_clear_pxe_mode(hw); 1036f31e4b6fSAnirudh Venkataramanan } 1037