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 285f31e4b6fSAnirudh Venkataramanan status = ice_init_all_ctrlq(hw); 286f31e4b6fSAnirudh Venkataramanan if (status) 287f31e4b6fSAnirudh Venkataramanan goto err_unroll_cqinit; 288f31e4b6fSAnirudh Venkataramanan 289f31e4b6fSAnirudh Venkataramanan status = ice_clear_pf_cfg(hw); 290f31e4b6fSAnirudh Venkataramanan if (status) 291f31e4b6fSAnirudh Venkataramanan goto err_unroll_cqinit; 292f31e4b6fSAnirudh Venkataramanan 293f31e4b6fSAnirudh Venkataramanan ice_clear_pxe_mode(hw); 294f31e4b6fSAnirudh Venkataramanan 295f31e4b6fSAnirudh Venkataramanan status = ice_init_nvm(hw); 296f31e4b6fSAnirudh Venkataramanan if (status) 297f31e4b6fSAnirudh Venkataramanan goto err_unroll_cqinit; 298f31e4b6fSAnirudh Venkataramanan 2999c20346bSAnirudh Venkataramanan status = ice_get_caps(hw); 3009c20346bSAnirudh Venkataramanan if (status) 3019c20346bSAnirudh Venkataramanan goto err_unroll_cqinit; 3029c20346bSAnirudh Venkataramanan 3039c20346bSAnirudh Venkataramanan hw->port_info = devm_kzalloc(ice_hw_to_dev(hw), 3049c20346bSAnirudh Venkataramanan sizeof(*hw->port_info), GFP_KERNEL); 3059c20346bSAnirudh Venkataramanan if (!hw->port_info) { 3069c20346bSAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 3079c20346bSAnirudh Venkataramanan goto err_unroll_cqinit; 3089c20346bSAnirudh Venkataramanan } 3099c20346bSAnirudh Venkataramanan 3109c20346bSAnirudh Venkataramanan /* set the back pointer to hw */ 3119c20346bSAnirudh Venkataramanan hw->port_info->hw = hw; 3129c20346bSAnirudh Venkataramanan 3139c20346bSAnirudh Venkataramanan /* Initialize port_info struct with switch configuration data */ 3149c20346bSAnirudh Venkataramanan status = ice_get_initial_sw_cfg(hw); 3159c20346bSAnirudh Venkataramanan if (status) 3169c20346bSAnirudh Venkataramanan goto err_unroll_alloc; 3179c20346bSAnirudh Venkataramanan 3189c20346bSAnirudh Venkataramanan /* Query the allocated resources for tx scheduler */ 3199c20346bSAnirudh Venkataramanan status = ice_sched_query_res_alloc(hw); 3209c20346bSAnirudh Venkataramanan if (status) { 3219c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_SCHED, 3229c20346bSAnirudh Venkataramanan "Failed to get scheduler allocated resources\n"); 3239c20346bSAnirudh Venkataramanan goto err_unroll_alloc; 3249c20346bSAnirudh Venkataramanan } 3259c20346bSAnirudh Venkataramanan 326dc49c772SAnirudh Venkataramanan /* Initialize port_info struct with scheduler data */ 327dc49c772SAnirudh Venkataramanan status = ice_sched_init_port(hw->port_info); 328dc49c772SAnirudh Venkataramanan if (status) 329dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 330dc49c772SAnirudh Venkataramanan 331dc49c772SAnirudh Venkataramanan pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL); 332dc49c772SAnirudh Venkataramanan if (!pcaps) { 333dc49c772SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 334dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 335dc49c772SAnirudh Venkataramanan } 336dc49c772SAnirudh Venkataramanan 337dc49c772SAnirudh Venkataramanan /* Initialize port_info struct with PHY capabilities */ 338dc49c772SAnirudh Venkataramanan status = ice_aq_get_phy_caps(hw->port_info, false, 339dc49c772SAnirudh Venkataramanan ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL); 340dc49c772SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), pcaps); 341dc49c772SAnirudh Venkataramanan if (status) 342dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 343dc49c772SAnirudh Venkataramanan 344dc49c772SAnirudh Venkataramanan /* Initialize port_info struct with link information */ 345dc49c772SAnirudh Venkataramanan status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL); 346dc49c772SAnirudh Venkataramanan if (status) 347dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 348dc49c772SAnirudh Venkataramanan 349dc49c772SAnirudh Venkataramanan /* Get port MAC information */ 350dc49c772SAnirudh Venkataramanan mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp); 351dc49c772SAnirudh Venkataramanan mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL); 352dc49c772SAnirudh Venkataramanan 353dc49c772SAnirudh Venkataramanan if (!mac_buf) 354dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 355dc49c772SAnirudh Venkataramanan 356dc49c772SAnirudh Venkataramanan status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL); 357dc49c772SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), mac_buf); 358dc49c772SAnirudh Venkataramanan 359dc49c772SAnirudh Venkataramanan if (status) 360dc49c772SAnirudh Venkataramanan goto err_unroll_sched; 361dc49c772SAnirudh Venkataramanan 362f31e4b6fSAnirudh Venkataramanan return 0; 363f31e4b6fSAnirudh Venkataramanan 364dc49c772SAnirudh Venkataramanan err_unroll_sched: 365dc49c772SAnirudh Venkataramanan ice_sched_cleanup_all(hw); 3669c20346bSAnirudh Venkataramanan err_unroll_alloc: 3679c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), hw->port_info); 368f31e4b6fSAnirudh Venkataramanan err_unroll_cqinit: 369f31e4b6fSAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 370f31e4b6fSAnirudh Venkataramanan return status; 371f31e4b6fSAnirudh Venkataramanan } 372f31e4b6fSAnirudh Venkataramanan 373f31e4b6fSAnirudh Venkataramanan /** 374f31e4b6fSAnirudh Venkataramanan * ice_deinit_hw - unroll initialization operations done by ice_init_hw 375f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 376f31e4b6fSAnirudh Venkataramanan */ 377f31e4b6fSAnirudh Venkataramanan void ice_deinit_hw(struct ice_hw *hw) 378f31e4b6fSAnirudh Venkataramanan { 3799c20346bSAnirudh Venkataramanan ice_sched_cleanup_all(hw); 380f31e4b6fSAnirudh Venkataramanan ice_shutdown_all_ctrlq(hw); 381dc49c772SAnirudh Venkataramanan 3829c20346bSAnirudh Venkataramanan if (hw->port_info) { 3839c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), hw->port_info); 3849c20346bSAnirudh Venkataramanan hw->port_info = NULL; 3859c20346bSAnirudh Venkataramanan } 386f31e4b6fSAnirudh Venkataramanan } 387f31e4b6fSAnirudh Venkataramanan 388f31e4b6fSAnirudh Venkataramanan /** 389f31e4b6fSAnirudh Venkataramanan * ice_check_reset - Check to see if a global reset is complete 390f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 391f31e4b6fSAnirudh Venkataramanan */ 392f31e4b6fSAnirudh Venkataramanan enum ice_status ice_check_reset(struct ice_hw *hw) 393f31e4b6fSAnirudh Venkataramanan { 394f31e4b6fSAnirudh Venkataramanan u32 cnt, reg = 0, grst_delay; 395f31e4b6fSAnirudh Venkataramanan 396f31e4b6fSAnirudh Venkataramanan /* Poll for Device Active state in case a recent CORER, GLOBR, 397f31e4b6fSAnirudh Venkataramanan * or EMPR has occurred. The grst delay value is in 100ms units. 398f31e4b6fSAnirudh Venkataramanan * Add 1sec for outstanding AQ commands that can take a long time. 399f31e4b6fSAnirudh Venkataramanan */ 400f31e4b6fSAnirudh Venkataramanan grst_delay = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >> 401f31e4b6fSAnirudh Venkataramanan GLGEN_RSTCTL_GRSTDEL_S) + 10; 402f31e4b6fSAnirudh Venkataramanan 403f31e4b6fSAnirudh Venkataramanan for (cnt = 0; cnt < grst_delay; cnt++) { 404f31e4b6fSAnirudh Venkataramanan mdelay(100); 405f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, GLGEN_RSTAT); 406f31e4b6fSAnirudh Venkataramanan if (!(reg & GLGEN_RSTAT_DEVSTATE_M)) 407f31e4b6fSAnirudh Venkataramanan break; 408f31e4b6fSAnirudh Venkataramanan } 409f31e4b6fSAnirudh Venkataramanan 410f31e4b6fSAnirudh Venkataramanan if (cnt == grst_delay) { 411f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 412f31e4b6fSAnirudh Venkataramanan "Global reset polling failed to complete.\n"); 413f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 414f31e4b6fSAnirudh Venkataramanan } 415f31e4b6fSAnirudh Venkataramanan 416f31e4b6fSAnirudh Venkataramanan #define ICE_RESET_DONE_MASK (GLNVM_ULD_CORER_DONE_M | \ 417f31e4b6fSAnirudh Venkataramanan GLNVM_ULD_GLOBR_DONE_M) 418f31e4b6fSAnirudh Venkataramanan 419f31e4b6fSAnirudh Venkataramanan /* Device is Active; check Global Reset processes are done */ 420f31e4b6fSAnirudh Venkataramanan for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 421f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK; 422f31e4b6fSAnirudh Venkataramanan if (reg == ICE_RESET_DONE_MASK) { 423f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 424f31e4b6fSAnirudh Venkataramanan "Global reset processes done. %d\n", cnt); 425f31e4b6fSAnirudh Venkataramanan break; 426f31e4b6fSAnirudh Venkataramanan } 427f31e4b6fSAnirudh Venkataramanan mdelay(10); 428f31e4b6fSAnirudh Venkataramanan } 429f31e4b6fSAnirudh Venkataramanan 430f31e4b6fSAnirudh Venkataramanan if (cnt == ICE_PF_RESET_WAIT_COUNT) { 431f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 432f31e4b6fSAnirudh Venkataramanan "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n", 433f31e4b6fSAnirudh Venkataramanan reg); 434f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 435f31e4b6fSAnirudh Venkataramanan } 436f31e4b6fSAnirudh Venkataramanan 437f31e4b6fSAnirudh Venkataramanan return 0; 438f31e4b6fSAnirudh Venkataramanan } 439f31e4b6fSAnirudh Venkataramanan 440f31e4b6fSAnirudh Venkataramanan /** 441f31e4b6fSAnirudh Venkataramanan * ice_pf_reset - Reset the PF 442f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 443f31e4b6fSAnirudh Venkataramanan * 444f31e4b6fSAnirudh Venkataramanan * If a global reset has been triggered, this function checks 445f31e4b6fSAnirudh Venkataramanan * for its completion and then issues the PF reset 446f31e4b6fSAnirudh Venkataramanan */ 447f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_pf_reset(struct ice_hw *hw) 448f31e4b6fSAnirudh Venkataramanan { 449f31e4b6fSAnirudh Venkataramanan u32 cnt, reg; 450f31e4b6fSAnirudh Venkataramanan 451f31e4b6fSAnirudh Venkataramanan /* If at function entry a global reset was already in progress, i.e. 452f31e4b6fSAnirudh Venkataramanan * state is not 'device active' or any of the reset done bits are not 453f31e4b6fSAnirudh Venkataramanan * set in GLNVM_ULD, there is no need for a PF Reset; poll until the 454f31e4b6fSAnirudh Venkataramanan * global reset is done. 455f31e4b6fSAnirudh Venkataramanan */ 456f31e4b6fSAnirudh Venkataramanan if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) || 457f31e4b6fSAnirudh Venkataramanan (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) { 458f31e4b6fSAnirudh Venkataramanan /* poll on global reset currently in progress until done */ 459f31e4b6fSAnirudh Venkataramanan if (ice_check_reset(hw)) 460f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 461f31e4b6fSAnirudh Venkataramanan 462f31e4b6fSAnirudh Venkataramanan return 0; 463f31e4b6fSAnirudh Venkataramanan } 464f31e4b6fSAnirudh Venkataramanan 465f31e4b6fSAnirudh Venkataramanan /* Reset the PF */ 466f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, PFGEN_CTRL); 467f31e4b6fSAnirudh Venkataramanan 468f31e4b6fSAnirudh Venkataramanan wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M)); 469f31e4b6fSAnirudh Venkataramanan 470f31e4b6fSAnirudh Venkataramanan for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 471f31e4b6fSAnirudh Venkataramanan reg = rd32(hw, PFGEN_CTRL); 472f31e4b6fSAnirudh Venkataramanan if (!(reg & PFGEN_CTRL_PFSWR_M)) 473f31e4b6fSAnirudh Venkataramanan break; 474f31e4b6fSAnirudh Venkataramanan 475f31e4b6fSAnirudh Venkataramanan mdelay(1); 476f31e4b6fSAnirudh Venkataramanan } 477f31e4b6fSAnirudh Venkataramanan 478f31e4b6fSAnirudh Venkataramanan if (cnt == ICE_PF_RESET_WAIT_COUNT) { 479f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 480f31e4b6fSAnirudh Venkataramanan "PF reset polling failed to complete.\n"); 481f31e4b6fSAnirudh Venkataramanan return ICE_ERR_RESET_FAILED; 482f31e4b6fSAnirudh Venkataramanan } 483f31e4b6fSAnirudh Venkataramanan 484f31e4b6fSAnirudh Venkataramanan return 0; 485f31e4b6fSAnirudh Venkataramanan } 486f31e4b6fSAnirudh Venkataramanan 487f31e4b6fSAnirudh Venkataramanan /** 488f31e4b6fSAnirudh Venkataramanan * ice_reset - Perform different types of reset 489f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hardware structure 490f31e4b6fSAnirudh Venkataramanan * @req: reset request 491f31e4b6fSAnirudh Venkataramanan * 492f31e4b6fSAnirudh Venkataramanan * This function triggers a reset as specified by the req parameter. 493f31e4b6fSAnirudh Venkataramanan * 494f31e4b6fSAnirudh Venkataramanan * Note: 495f31e4b6fSAnirudh Venkataramanan * If anything other than a PF reset is triggered, PXE mode is restored. 496f31e4b6fSAnirudh Venkataramanan * This has to be cleared using ice_clear_pxe_mode again, once the AQ 497f31e4b6fSAnirudh Venkataramanan * interface has been restored in the rebuild flow. 498f31e4b6fSAnirudh Venkataramanan */ 499f31e4b6fSAnirudh Venkataramanan enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req) 500f31e4b6fSAnirudh Venkataramanan { 501f31e4b6fSAnirudh Venkataramanan u32 val = 0; 502f31e4b6fSAnirudh Venkataramanan 503f31e4b6fSAnirudh Venkataramanan switch (req) { 504f31e4b6fSAnirudh Venkataramanan case ICE_RESET_PFR: 505f31e4b6fSAnirudh Venkataramanan return ice_pf_reset(hw); 506f31e4b6fSAnirudh Venkataramanan case ICE_RESET_CORER: 507f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n"); 508f31e4b6fSAnirudh Venkataramanan val = GLGEN_RTRIG_CORER_M; 509f31e4b6fSAnirudh Venkataramanan break; 510f31e4b6fSAnirudh Venkataramanan case ICE_RESET_GLOBR: 511f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n"); 512f31e4b6fSAnirudh Venkataramanan val = GLGEN_RTRIG_GLOBR_M; 513f31e4b6fSAnirudh Venkataramanan break; 514f31e4b6fSAnirudh Venkataramanan } 515f31e4b6fSAnirudh Venkataramanan 516f31e4b6fSAnirudh Venkataramanan val |= rd32(hw, GLGEN_RTRIG); 517f31e4b6fSAnirudh Venkataramanan wr32(hw, GLGEN_RTRIG, val); 518f31e4b6fSAnirudh Venkataramanan ice_flush(hw); 519f31e4b6fSAnirudh Venkataramanan 520f31e4b6fSAnirudh Venkataramanan /* wait for the FW to be ready */ 521f31e4b6fSAnirudh Venkataramanan return ice_check_reset(hw); 522f31e4b6fSAnirudh Venkataramanan } 523f31e4b6fSAnirudh Venkataramanan 5247ec59eeaSAnirudh Venkataramanan /** 5257ec59eeaSAnirudh Venkataramanan * ice_debug_cq 5267ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hardware structure 5277ec59eeaSAnirudh Venkataramanan * @mask: debug mask 5287ec59eeaSAnirudh Venkataramanan * @desc: pointer to control queue descriptor 5297ec59eeaSAnirudh Venkataramanan * @buf: pointer to command buffer 5307ec59eeaSAnirudh Venkataramanan * @buf_len: max length of buf 5317ec59eeaSAnirudh Venkataramanan * 5327ec59eeaSAnirudh Venkataramanan * Dumps debug log about control command with descriptor contents. 5337ec59eeaSAnirudh Venkataramanan */ 5347ec59eeaSAnirudh Venkataramanan void ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc, 5357ec59eeaSAnirudh Venkataramanan void *buf, u16 buf_len) 5367ec59eeaSAnirudh Venkataramanan { 5377ec59eeaSAnirudh Venkataramanan struct ice_aq_desc *cq_desc = (struct ice_aq_desc *)desc; 5387ec59eeaSAnirudh Venkataramanan u16 len; 5397ec59eeaSAnirudh Venkataramanan 5407ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 5417ec59eeaSAnirudh Venkataramanan if (!(mask & hw->debug_mask)) 5427ec59eeaSAnirudh Venkataramanan return; 5437ec59eeaSAnirudh Venkataramanan #endif 5447ec59eeaSAnirudh Venkataramanan 5457ec59eeaSAnirudh Venkataramanan if (!desc) 5467ec59eeaSAnirudh Venkataramanan return; 5477ec59eeaSAnirudh Venkataramanan 5487ec59eeaSAnirudh Venkataramanan len = le16_to_cpu(cq_desc->datalen); 5497ec59eeaSAnirudh Venkataramanan 5507ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, 5517ec59eeaSAnirudh Venkataramanan "CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n", 5527ec59eeaSAnirudh Venkataramanan le16_to_cpu(cq_desc->opcode), 5537ec59eeaSAnirudh Venkataramanan le16_to_cpu(cq_desc->flags), 5547ec59eeaSAnirudh Venkataramanan le16_to_cpu(cq_desc->datalen), le16_to_cpu(cq_desc->retval)); 5557ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n", 5567ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->cookie_high), 5577ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->cookie_low)); 5587ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n", 5597ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.param0), 5607ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.param1)); 5617ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n", 5627ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.addr_high), 5637ec59eeaSAnirudh Venkataramanan le32_to_cpu(cq_desc->params.generic.addr_low)); 5647ec59eeaSAnirudh Venkataramanan if (buf && cq_desc->datalen != 0) { 5657ec59eeaSAnirudh Venkataramanan ice_debug(hw, mask, "Buffer:\n"); 5667ec59eeaSAnirudh Venkataramanan if (buf_len < len) 5677ec59eeaSAnirudh Venkataramanan len = buf_len; 5687ec59eeaSAnirudh Venkataramanan 5697ec59eeaSAnirudh Venkataramanan ice_debug_array(hw, mask, 16, 1, (u8 *)buf, len); 5707ec59eeaSAnirudh Venkataramanan } 5717ec59eeaSAnirudh Venkataramanan } 5727ec59eeaSAnirudh Venkataramanan 5737ec59eeaSAnirudh Venkataramanan /* FW Admin Queue command wrappers */ 5747ec59eeaSAnirudh Venkataramanan 5757ec59eeaSAnirudh Venkataramanan /** 5767ec59eeaSAnirudh Venkataramanan * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue 5777ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hw struct 5787ec59eeaSAnirudh Venkataramanan * @desc: descriptor describing the command 5797ec59eeaSAnirudh Venkataramanan * @buf: buffer to use for indirect commands (NULL for direct commands) 5807ec59eeaSAnirudh Venkataramanan * @buf_size: size of buffer for indirect commands (0 for direct commands) 5817ec59eeaSAnirudh Venkataramanan * @cd: pointer to command details structure 5827ec59eeaSAnirudh Venkataramanan * 5837ec59eeaSAnirudh Venkataramanan * Helper function to send FW Admin Queue commands to the FW Admin Queue. 5847ec59eeaSAnirudh Venkataramanan */ 5857ec59eeaSAnirudh Venkataramanan enum ice_status 5867ec59eeaSAnirudh Venkataramanan ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf, 5877ec59eeaSAnirudh Venkataramanan u16 buf_size, struct ice_sq_cd *cd) 5887ec59eeaSAnirudh Venkataramanan { 5897ec59eeaSAnirudh Venkataramanan return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd); 5907ec59eeaSAnirudh Venkataramanan } 5917ec59eeaSAnirudh Venkataramanan 5927ec59eeaSAnirudh Venkataramanan /** 5937ec59eeaSAnirudh Venkataramanan * ice_aq_get_fw_ver 5947ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hw struct 5957ec59eeaSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 5967ec59eeaSAnirudh Venkataramanan * 5977ec59eeaSAnirudh Venkataramanan * Get the firmware version (0x0001) from the admin queue commands 5987ec59eeaSAnirudh Venkataramanan */ 5997ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd) 6007ec59eeaSAnirudh Venkataramanan { 6017ec59eeaSAnirudh Venkataramanan struct ice_aqc_get_ver *resp; 6027ec59eeaSAnirudh Venkataramanan struct ice_aq_desc desc; 6037ec59eeaSAnirudh Venkataramanan enum ice_status status; 6047ec59eeaSAnirudh Venkataramanan 6057ec59eeaSAnirudh Venkataramanan resp = &desc.params.get_ver; 6067ec59eeaSAnirudh Venkataramanan 6077ec59eeaSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver); 6087ec59eeaSAnirudh Venkataramanan 6097ec59eeaSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 6107ec59eeaSAnirudh Venkataramanan 6117ec59eeaSAnirudh Venkataramanan if (!status) { 6127ec59eeaSAnirudh Venkataramanan hw->fw_branch = resp->fw_branch; 6137ec59eeaSAnirudh Venkataramanan hw->fw_maj_ver = resp->fw_major; 6147ec59eeaSAnirudh Venkataramanan hw->fw_min_ver = resp->fw_minor; 6157ec59eeaSAnirudh Venkataramanan hw->fw_patch = resp->fw_patch; 6167ec59eeaSAnirudh Venkataramanan hw->fw_build = le32_to_cpu(resp->fw_build); 6177ec59eeaSAnirudh Venkataramanan hw->api_branch = resp->api_branch; 6187ec59eeaSAnirudh Venkataramanan hw->api_maj_ver = resp->api_major; 6197ec59eeaSAnirudh Venkataramanan hw->api_min_ver = resp->api_minor; 6207ec59eeaSAnirudh Venkataramanan hw->api_patch = resp->api_patch; 6217ec59eeaSAnirudh Venkataramanan } 6227ec59eeaSAnirudh Venkataramanan 6237ec59eeaSAnirudh Venkataramanan return status; 6247ec59eeaSAnirudh Venkataramanan } 6257ec59eeaSAnirudh Venkataramanan 6267ec59eeaSAnirudh Venkataramanan /** 6277ec59eeaSAnirudh Venkataramanan * ice_aq_q_shutdown 6287ec59eeaSAnirudh Venkataramanan * @hw: pointer to the hw struct 6297ec59eeaSAnirudh Venkataramanan * @unloading: is the driver unloading itself 6307ec59eeaSAnirudh Venkataramanan * 6317ec59eeaSAnirudh Venkataramanan * Tell the Firmware that we're shutting down the AdminQ and whether 6327ec59eeaSAnirudh Venkataramanan * or not the driver is unloading as well (0x0003). 6337ec59eeaSAnirudh Venkataramanan */ 6347ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading) 6357ec59eeaSAnirudh Venkataramanan { 6367ec59eeaSAnirudh Venkataramanan struct ice_aqc_q_shutdown *cmd; 6377ec59eeaSAnirudh Venkataramanan struct ice_aq_desc desc; 6387ec59eeaSAnirudh Venkataramanan 6397ec59eeaSAnirudh Venkataramanan cmd = &desc.params.q_shutdown; 6407ec59eeaSAnirudh Venkataramanan 6417ec59eeaSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown); 6427ec59eeaSAnirudh Venkataramanan 6437ec59eeaSAnirudh Venkataramanan if (unloading) 6447ec59eeaSAnirudh Venkataramanan cmd->driver_unloading = cpu_to_le32(ICE_AQC_DRIVER_UNLOADING); 6457ec59eeaSAnirudh Venkataramanan 6467ec59eeaSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 6477ec59eeaSAnirudh Venkataramanan } 648f31e4b6fSAnirudh Venkataramanan 649f31e4b6fSAnirudh Venkataramanan /** 650f31e4b6fSAnirudh Venkataramanan * ice_aq_req_res 651f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 652f31e4b6fSAnirudh Venkataramanan * @res: resource id 653f31e4b6fSAnirudh Venkataramanan * @access: access type 654f31e4b6fSAnirudh Venkataramanan * @sdp_number: resource number 655f31e4b6fSAnirudh Venkataramanan * @timeout: the maximum time in ms that the driver may hold the resource 656f31e4b6fSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 657f31e4b6fSAnirudh Venkataramanan * 658f31e4b6fSAnirudh Venkataramanan * requests common resource using the admin queue commands (0x0008) 659f31e4b6fSAnirudh Venkataramanan */ 660f31e4b6fSAnirudh Venkataramanan static enum ice_status 661f31e4b6fSAnirudh Venkataramanan ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res, 662f31e4b6fSAnirudh Venkataramanan enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout, 663f31e4b6fSAnirudh Venkataramanan struct ice_sq_cd *cd) 664f31e4b6fSAnirudh Venkataramanan { 665f31e4b6fSAnirudh Venkataramanan struct ice_aqc_req_res *cmd_resp; 666f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 667f31e4b6fSAnirudh Venkataramanan enum ice_status status; 668f31e4b6fSAnirudh Venkataramanan 669f31e4b6fSAnirudh Venkataramanan cmd_resp = &desc.params.res_owner; 670f31e4b6fSAnirudh Venkataramanan 671f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res); 672f31e4b6fSAnirudh Venkataramanan 673f31e4b6fSAnirudh Venkataramanan cmd_resp->res_id = cpu_to_le16(res); 674f31e4b6fSAnirudh Venkataramanan cmd_resp->access_type = cpu_to_le16(access); 675f31e4b6fSAnirudh Venkataramanan cmd_resp->res_number = cpu_to_le32(sdp_number); 676f31e4b6fSAnirudh Venkataramanan 677f31e4b6fSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 678f31e4b6fSAnirudh Venkataramanan /* The completion specifies the maximum time in ms that the driver 679f31e4b6fSAnirudh Venkataramanan * may hold the resource in the Timeout field. 680f31e4b6fSAnirudh Venkataramanan * If the resource is held by someone else, the command completes with 681f31e4b6fSAnirudh Venkataramanan * busy return value and the timeout field indicates the maximum time 682f31e4b6fSAnirudh Venkataramanan * the current owner of the resource has to free it. 683f31e4b6fSAnirudh Venkataramanan */ 684f31e4b6fSAnirudh Venkataramanan if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) 685f31e4b6fSAnirudh Venkataramanan *timeout = le32_to_cpu(cmd_resp->timeout); 686f31e4b6fSAnirudh Venkataramanan 687f31e4b6fSAnirudh Venkataramanan return status; 688f31e4b6fSAnirudh Venkataramanan } 689f31e4b6fSAnirudh Venkataramanan 690f31e4b6fSAnirudh Venkataramanan /** 691f31e4b6fSAnirudh Venkataramanan * ice_aq_release_res 692f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 693f31e4b6fSAnirudh Venkataramanan * @res: resource id 694f31e4b6fSAnirudh Venkataramanan * @sdp_number: resource number 695f31e4b6fSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 696f31e4b6fSAnirudh Venkataramanan * 697f31e4b6fSAnirudh Venkataramanan * release common resource using the admin queue commands (0x0009) 698f31e4b6fSAnirudh Venkataramanan */ 699f31e4b6fSAnirudh Venkataramanan static enum ice_status 700f31e4b6fSAnirudh Venkataramanan ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number, 701f31e4b6fSAnirudh Venkataramanan struct ice_sq_cd *cd) 702f31e4b6fSAnirudh Venkataramanan { 703f31e4b6fSAnirudh Venkataramanan struct ice_aqc_req_res *cmd; 704f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 705f31e4b6fSAnirudh Venkataramanan 706f31e4b6fSAnirudh Venkataramanan cmd = &desc.params.res_owner; 707f31e4b6fSAnirudh Venkataramanan 708f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res); 709f31e4b6fSAnirudh Venkataramanan 710f31e4b6fSAnirudh Venkataramanan cmd->res_id = cpu_to_le16(res); 711f31e4b6fSAnirudh Venkataramanan cmd->res_number = cpu_to_le32(sdp_number); 712f31e4b6fSAnirudh Venkataramanan 713f31e4b6fSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 714f31e4b6fSAnirudh Venkataramanan } 715f31e4b6fSAnirudh Venkataramanan 716f31e4b6fSAnirudh Venkataramanan /** 717f31e4b6fSAnirudh Venkataramanan * ice_acquire_res 718f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 719f31e4b6fSAnirudh Venkataramanan * @res: resource id 720f31e4b6fSAnirudh Venkataramanan * @access: access type (read or write) 721f31e4b6fSAnirudh Venkataramanan * 722f31e4b6fSAnirudh Venkataramanan * This function will attempt to acquire the ownership of a resource. 723f31e4b6fSAnirudh Venkataramanan */ 724f31e4b6fSAnirudh Venkataramanan enum ice_status 725f31e4b6fSAnirudh Venkataramanan ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, 726f31e4b6fSAnirudh Venkataramanan enum ice_aq_res_access_type access) 727f31e4b6fSAnirudh Venkataramanan { 728f31e4b6fSAnirudh Venkataramanan #define ICE_RES_POLLING_DELAY_MS 10 729f31e4b6fSAnirudh Venkataramanan u32 delay = ICE_RES_POLLING_DELAY_MS; 730f31e4b6fSAnirudh Venkataramanan enum ice_status status; 731f31e4b6fSAnirudh Venkataramanan u32 time_left = 0; 732f31e4b6fSAnirudh Venkataramanan u32 timeout; 733f31e4b6fSAnirudh Venkataramanan 734f31e4b6fSAnirudh Venkataramanan status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 735f31e4b6fSAnirudh Venkataramanan 736f31e4b6fSAnirudh Venkataramanan /* An admin queue return code of ICE_AQ_RC_EEXIST means that another 737f31e4b6fSAnirudh Venkataramanan * driver has previously acquired the resource and performed any 738f31e4b6fSAnirudh Venkataramanan * necessary updates; in this case the caller does not obtain the 739f31e4b6fSAnirudh Venkataramanan * resource and has no further work to do. 740f31e4b6fSAnirudh Venkataramanan */ 741f31e4b6fSAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) { 742f31e4b6fSAnirudh Venkataramanan status = ICE_ERR_AQ_NO_WORK; 743f31e4b6fSAnirudh Venkataramanan goto ice_acquire_res_exit; 744f31e4b6fSAnirudh Venkataramanan } 745f31e4b6fSAnirudh Venkataramanan 746f31e4b6fSAnirudh Venkataramanan if (status) 747f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, 748f31e4b6fSAnirudh Venkataramanan "resource %d acquire type %d failed.\n", res, access); 749f31e4b6fSAnirudh Venkataramanan 750f31e4b6fSAnirudh Venkataramanan /* If necessary, poll until the current lock owner timeouts */ 751f31e4b6fSAnirudh Venkataramanan timeout = time_left; 752f31e4b6fSAnirudh Venkataramanan while (status && timeout && time_left) { 753f31e4b6fSAnirudh Venkataramanan mdelay(delay); 754f31e4b6fSAnirudh Venkataramanan timeout = (timeout > delay) ? timeout - delay : 0; 755f31e4b6fSAnirudh Venkataramanan status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 756f31e4b6fSAnirudh Venkataramanan 757f31e4b6fSAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) { 758f31e4b6fSAnirudh Venkataramanan /* lock free, but no work to do */ 759f31e4b6fSAnirudh Venkataramanan status = ICE_ERR_AQ_NO_WORK; 760f31e4b6fSAnirudh Venkataramanan break; 761f31e4b6fSAnirudh Venkataramanan } 762f31e4b6fSAnirudh Venkataramanan 763f31e4b6fSAnirudh Venkataramanan if (!status) 764f31e4b6fSAnirudh Venkataramanan /* lock acquired */ 765f31e4b6fSAnirudh Venkataramanan break; 766f31e4b6fSAnirudh Venkataramanan } 767f31e4b6fSAnirudh Venkataramanan if (status && status != ICE_ERR_AQ_NO_WORK) 768f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n"); 769f31e4b6fSAnirudh Venkataramanan 770f31e4b6fSAnirudh Venkataramanan ice_acquire_res_exit: 771f31e4b6fSAnirudh Venkataramanan if (status == ICE_ERR_AQ_NO_WORK) { 772f31e4b6fSAnirudh Venkataramanan if (access == ICE_RES_WRITE) 773f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, 774f31e4b6fSAnirudh Venkataramanan "resource indicates no work to do.\n"); 775f31e4b6fSAnirudh Venkataramanan else 776f31e4b6fSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_RES, 777f31e4b6fSAnirudh Venkataramanan "Warning: ICE_ERR_AQ_NO_WORK not expected\n"); 778f31e4b6fSAnirudh Venkataramanan } 779f31e4b6fSAnirudh Venkataramanan return status; 780f31e4b6fSAnirudh Venkataramanan } 781f31e4b6fSAnirudh Venkataramanan 782f31e4b6fSAnirudh Venkataramanan /** 783f31e4b6fSAnirudh Venkataramanan * ice_release_res 784f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the HW structure 785f31e4b6fSAnirudh Venkataramanan * @res: resource id 786f31e4b6fSAnirudh Venkataramanan * 787f31e4b6fSAnirudh Venkataramanan * This function will release a resource using the proper Admin Command. 788f31e4b6fSAnirudh Venkataramanan */ 789f31e4b6fSAnirudh Venkataramanan void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res) 790f31e4b6fSAnirudh Venkataramanan { 791f31e4b6fSAnirudh Venkataramanan enum ice_status status; 792f31e4b6fSAnirudh Venkataramanan u32 total_delay = 0; 793f31e4b6fSAnirudh Venkataramanan 794f31e4b6fSAnirudh Venkataramanan status = ice_aq_release_res(hw, res, 0, NULL); 795f31e4b6fSAnirudh Venkataramanan 796f31e4b6fSAnirudh Venkataramanan /* there are some rare cases when trying to release the resource 797f31e4b6fSAnirudh Venkataramanan * results in an admin Q timeout, so handle them correctly 798f31e4b6fSAnirudh Venkataramanan */ 799f31e4b6fSAnirudh Venkataramanan while ((status == ICE_ERR_AQ_TIMEOUT) && 800f31e4b6fSAnirudh Venkataramanan (total_delay < hw->adminq.sq_cmd_timeout)) { 801f31e4b6fSAnirudh Venkataramanan mdelay(1); 802f31e4b6fSAnirudh Venkataramanan status = ice_aq_release_res(hw, res, 0, NULL); 803f31e4b6fSAnirudh Venkataramanan total_delay++; 804f31e4b6fSAnirudh Venkataramanan } 805f31e4b6fSAnirudh Venkataramanan } 806f31e4b6fSAnirudh Venkataramanan 807f31e4b6fSAnirudh Venkataramanan /** 8089c20346bSAnirudh Venkataramanan * ice_parse_caps - parse function/device capabilities 8099c20346bSAnirudh Venkataramanan * @hw: pointer to the hw struct 8109c20346bSAnirudh Venkataramanan * @buf: pointer to a buffer containing function/device capability records 8119c20346bSAnirudh Venkataramanan * @cap_count: number of capability records in the list 8129c20346bSAnirudh Venkataramanan * @opc: type of capabilities list to parse 8139c20346bSAnirudh Venkataramanan * 8149c20346bSAnirudh Venkataramanan * Helper function to parse function(0x000a)/device(0x000b) capabilities list. 8159c20346bSAnirudh Venkataramanan */ 8169c20346bSAnirudh Venkataramanan static void 8179c20346bSAnirudh Venkataramanan ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count, 8189c20346bSAnirudh Venkataramanan enum ice_adminq_opc opc) 8199c20346bSAnirudh Venkataramanan { 8209c20346bSAnirudh Venkataramanan struct ice_aqc_list_caps_elem *cap_resp; 8219c20346bSAnirudh Venkataramanan struct ice_hw_func_caps *func_p = NULL; 8229c20346bSAnirudh Venkataramanan struct ice_hw_dev_caps *dev_p = NULL; 8239c20346bSAnirudh Venkataramanan struct ice_hw_common_caps *caps; 8249c20346bSAnirudh Venkataramanan u32 i; 8259c20346bSAnirudh Venkataramanan 8269c20346bSAnirudh Venkataramanan if (!buf) 8279c20346bSAnirudh Venkataramanan return; 8289c20346bSAnirudh Venkataramanan 8299c20346bSAnirudh Venkataramanan cap_resp = (struct ice_aqc_list_caps_elem *)buf; 8309c20346bSAnirudh Venkataramanan 8319c20346bSAnirudh Venkataramanan if (opc == ice_aqc_opc_list_dev_caps) { 8329c20346bSAnirudh Venkataramanan dev_p = &hw->dev_caps; 8339c20346bSAnirudh Venkataramanan caps = &dev_p->common_cap; 8349c20346bSAnirudh Venkataramanan } else if (opc == ice_aqc_opc_list_func_caps) { 8359c20346bSAnirudh Venkataramanan func_p = &hw->func_caps; 8369c20346bSAnirudh Venkataramanan caps = &func_p->common_cap; 8379c20346bSAnirudh Venkataramanan } else { 8389c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, "wrong opcode\n"); 8399c20346bSAnirudh Venkataramanan return; 8409c20346bSAnirudh Venkataramanan } 8419c20346bSAnirudh Venkataramanan 8429c20346bSAnirudh Venkataramanan for (i = 0; caps && i < cap_count; i++, cap_resp++) { 8439c20346bSAnirudh Venkataramanan u32 logical_id = le32_to_cpu(cap_resp->logical_id); 8449c20346bSAnirudh Venkataramanan u32 phys_id = le32_to_cpu(cap_resp->phys_id); 8459c20346bSAnirudh Venkataramanan u32 number = le32_to_cpu(cap_resp->number); 8469c20346bSAnirudh Venkataramanan u16 cap = le16_to_cpu(cap_resp->cap); 8479c20346bSAnirudh Venkataramanan 8489c20346bSAnirudh Venkataramanan switch (cap) { 8499c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_VSI: 8509c20346bSAnirudh Venkataramanan if (dev_p) { 8519c20346bSAnirudh Venkataramanan dev_p->num_vsi_allocd_to_host = number; 8529c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8539c20346bSAnirudh Venkataramanan "HW caps: Dev.VSI cnt = %d\n", 8549c20346bSAnirudh Venkataramanan dev_p->num_vsi_allocd_to_host); 8559c20346bSAnirudh Venkataramanan } else if (func_p) { 8569c20346bSAnirudh Venkataramanan func_p->guaranteed_num_vsi = number; 8579c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8589c20346bSAnirudh Venkataramanan "HW caps: Func.VSI cnt = %d\n", 8599c20346bSAnirudh Venkataramanan func_p->guaranteed_num_vsi); 8609c20346bSAnirudh Venkataramanan } 8619c20346bSAnirudh Venkataramanan break; 8629c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_RSS: 8639c20346bSAnirudh Venkataramanan caps->rss_table_size = number; 8649c20346bSAnirudh Venkataramanan caps->rss_table_entry_width = logical_id; 8659c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8669c20346bSAnirudh Venkataramanan "HW caps: RSS table size = %d\n", 8679c20346bSAnirudh Venkataramanan caps->rss_table_size); 8689c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8699c20346bSAnirudh Venkataramanan "HW caps: RSS table width = %d\n", 8709c20346bSAnirudh Venkataramanan caps->rss_table_entry_width); 8719c20346bSAnirudh Venkataramanan break; 8729c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_RXQS: 8739c20346bSAnirudh Venkataramanan caps->num_rxq = number; 8749c20346bSAnirudh Venkataramanan caps->rxq_first_id = phys_id; 8759c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8769c20346bSAnirudh Venkataramanan "HW caps: Num Rx Qs = %d\n", caps->num_rxq); 8779c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8789c20346bSAnirudh Venkataramanan "HW caps: Rx first queue ID = %d\n", 8799c20346bSAnirudh Venkataramanan caps->rxq_first_id); 8809c20346bSAnirudh Venkataramanan break; 8819c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_TXQS: 8829c20346bSAnirudh Venkataramanan caps->num_txq = number; 8839c20346bSAnirudh Venkataramanan caps->txq_first_id = phys_id; 8849c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8859c20346bSAnirudh Venkataramanan "HW caps: Num Tx Qs = %d\n", caps->num_txq); 8869c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8879c20346bSAnirudh Venkataramanan "HW caps: Tx first queue ID = %d\n", 8889c20346bSAnirudh Venkataramanan caps->txq_first_id); 8899c20346bSAnirudh Venkataramanan break; 8909c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_MSIX: 8919c20346bSAnirudh Venkataramanan caps->num_msix_vectors = number; 8929c20346bSAnirudh Venkataramanan caps->msix_vector_first_id = phys_id; 8939c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8949c20346bSAnirudh Venkataramanan "HW caps: MSIX vector count = %d\n", 8959c20346bSAnirudh Venkataramanan caps->num_msix_vectors); 8969c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 8979c20346bSAnirudh Venkataramanan "HW caps: MSIX first vector index = %d\n", 8989c20346bSAnirudh Venkataramanan caps->msix_vector_first_id); 8999c20346bSAnirudh Venkataramanan break; 9009c20346bSAnirudh Venkataramanan case ICE_AQC_CAPS_MAX_MTU: 9019c20346bSAnirudh Venkataramanan caps->max_mtu = number; 9029c20346bSAnirudh Venkataramanan if (dev_p) 9039c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9049c20346bSAnirudh Venkataramanan "HW caps: Dev.MaxMTU = %d\n", 9059c20346bSAnirudh Venkataramanan caps->max_mtu); 9069c20346bSAnirudh Venkataramanan else if (func_p) 9079c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9089c20346bSAnirudh Venkataramanan "HW caps: func.MaxMTU = %d\n", 9099c20346bSAnirudh Venkataramanan caps->max_mtu); 9109c20346bSAnirudh Venkataramanan break; 9119c20346bSAnirudh Venkataramanan default: 9129c20346bSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_INIT, 9139c20346bSAnirudh Venkataramanan "HW caps: Unknown capability[%d]: 0x%x\n", i, 9149c20346bSAnirudh Venkataramanan cap); 9159c20346bSAnirudh Venkataramanan break; 9169c20346bSAnirudh Venkataramanan } 9179c20346bSAnirudh Venkataramanan } 9189c20346bSAnirudh Venkataramanan } 9199c20346bSAnirudh Venkataramanan 9209c20346bSAnirudh Venkataramanan /** 9219c20346bSAnirudh Venkataramanan * ice_aq_discover_caps - query function/device capabilities 9229c20346bSAnirudh Venkataramanan * @hw: pointer to the hw struct 9239c20346bSAnirudh Venkataramanan * @buf: a virtual buffer to hold the capabilities 9249c20346bSAnirudh Venkataramanan * @buf_size: Size of the virtual buffer 9259c20346bSAnirudh Venkataramanan * @data_size: Size of the returned data, or buf size needed if AQ err==ENOMEM 9269c20346bSAnirudh Venkataramanan * @opc: capabilities type to discover - pass in the command opcode 9279c20346bSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 9289c20346bSAnirudh Venkataramanan * 9299c20346bSAnirudh Venkataramanan * Get the function(0x000a)/device(0x000b) capabilities description from 9309c20346bSAnirudh Venkataramanan * the firmware. 9319c20346bSAnirudh Venkataramanan */ 9329c20346bSAnirudh Venkataramanan static enum ice_status 9339c20346bSAnirudh Venkataramanan ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u16 *data_size, 9349c20346bSAnirudh Venkataramanan enum ice_adminq_opc opc, struct ice_sq_cd *cd) 9359c20346bSAnirudh Venkataramanan { 9369c20346bSAnirudh Venkataramanan struct ice_aqc_list_caps *cmd; 9379c20346bSAnirudh Venkataramanan struct ice_aq_desc desc; 9389c20346bSAnirudh Venkataramanan enum ice_status status; 9399c20346bSAnirudh Venkataramanan 9409c20346bSAnirudh Venkataramanan cmd = &desc.params.get_cap; 9419c20346bSAnirudh Venkataramanan 9429c20346bSAnirudh Venkataramanan if (opc != ice_aqc_opc_list_func_caps && 9439c20346bSAnirudh Venkataramanan opc != ice_aqc_opc_list_dev_caps) 9449c20346bSAnirudh Venkataramanan return ICE_ERR_PARAM; 9459c20346bSAnirudh Venkataramanan 9469c20346bSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, opc); 9479c20346bSAnirudh Venkataramanan 9489c20346bSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 9499c20346bSAnirudh Venkataramanan if (!status) 9509c20346bSAnirudh Venkataramanan ice_parse_caps(hw, buf, le32_to_cpu(cmd->count), opc); 9519c20346bSAnirudh Venkataramanan *data_size = le16_to_cpu(desc.datalen); 9529c20346bSAnirudh Venkataramanan 9539c20346bSAnirudh Venkataramanan return status; 9549c20346bSAnirudh Venkataramanan } 9559c20346bSAnirudh Venkataramanan 9569c20346bSAnirudh Venkataramanan /** 9579c20346bSAnirudh Venkataramanan * ice_get_caps - get info about the HW 9589c20346bSAnirudh Venkataramanan * @hw: pointer to the hardware structure 9599c20346bSAnirudh Venkataramanan */ 9609c20346bSAnirudh Venkataramanan enum ice_status ice_get_caps(struct ice_hw *hw) 9619c20346bSAnirudh Venkataramanan { 9629c20346bSAnirudh Venkataramanan enum ice_status status; 9639c20346bSAnirudh Venkataramanan u16 data_size = 0; 9649c20346bSAnirudh Venkataramanan u16 cbuf_len; 9659c20346bSAnirudh Venkataramanan u8 retries; 9669c20346bSAnirudh Venkataramanan 9679c20346bSAnirudh Venkataramanan /* The driver doesn't know how many capabilities the device will return 9689c20346bSAnirudh Venkataramanan * so the buffer size required isn't known ahead of time. The driver 9699c20346bSAnirudh Venkataramanan * starts with cbuf_len and if this turns out to be insufficient, the 9709c20346bSAnirudh Venkataramanan * device returns ICE_AQ_RC_ENOMEM and also the buffer size it needs. 9719c20346bSAnirudh Venkataramanan * The driver then allocates the buffer of this size and retries the 9729c20346bSAnirudh Venkataramanan * operation. So it follows that the retry count is 2. 9739c20346bSAnirudh Venkataramanan */ 9749c20346bSAnirudh Venkataramanan #define ICE_GET_CAP_BUF_COUNT 40 9759c20346bSAnirudh Venkataramanan #define ICE_GET_CAP_RETRY_COUNT 2 9769c20346bSAnirudh Venkataramanan 9779c20346bSAnirudh Venkataramanan cbuf_len = ICE_GET_CAP_BUF_COUNT * 9789c20346bSAnirudh Venkataramanan sizeof(struct ice_aqc_list_caps_elem); 9799c20346bSAnirudh Venkataramanan 9809c20346bSAnirudh Venkataramanan retries = ICE_GET_CAP_RETRY_COUNT; 9819c20346bSAnirudh Venkataramanan 9829c20346bSAnirudh Venkataramanan do { 9839c20346bSAnirudh Venkataramanan void *cbuf; 9849c20346bSAnirudh Venkataramanan 9859c20346bSAnirudh Venkataramanan cbuf = devm_kzalloc(ice_hw_to_dev(hw), cbuf_len, GFP_KERNEL); 9869c20346bSAnirudh Venkataramanan if (!cbuf) 9879c20346bSAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 9889c20346bSAnirudh Venkataramanan 9899c20346bSAnirudh Venkataramanan status = ice_aq_discover_caps(hw, cbuf, cbuf_len, &data_size, 9909c20346bSAnirudh Venkataramanan ice_aqc_opc_list_func_caps, NULL); 9919c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), cbuf); 9929c20346bSAnirudh Venkataramanan 9939c20346bSAnirudh Venkataramanan if (!status || hw->adminq.sq_last_status != ICE_AQ_RC_ENOMEM) 9949c20346bSAnirudh Venkataramanan break; 9959c20346bSAnirudh Venkataramanan 9969c20346bSAnirudh Venkataramanan /* If ENOMEM is returned, try again with bigger buffer */ 9979c20346bSAnirudh Venkataramanan cbuf_len = data_size; 9989c20346bSAnirudh Venkataramanan } while (--retries); 9999c20346bSAnirudh Venkataramanan 10009c20346bSAnirudh Venkataramanan return status; 10019c20346bSAnirudh Venkataramanan } 10029c20346bSAnirudh Venkataramanan 10039c20346bSAnirudh Venkataramanan /** 1004f31e4b6fSAnirudh Venkataramanan * ice_aq_clear_pxe_mode 1005f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 1006f31e4b6fSAnirudh Venkataramanan * 1007f31e4b6fSAnirudh Venkataramanan * Tell the firmware that the driver is taking over from PXE (0x0110). 1008f31e4b6fSAnirudh Venkataramanan */ 1009f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw) 1010f31e4b6fSAnirudh Venkataramanan { 1011f31e4b6fSAnirudh Venkataramanan struct ice_aq_desc desc; 1012f31e4b6fSAnirudh Venkataramanan 1013f31e4b6fSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode); 1014f31e4b6fSAnirudh Venkataramanan desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT; 1015f31e4b6fSAnirudh Venkataramanan 1016f31e4b6fSAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 1017f31e4b6fSAnirudh Venkataramanan } 1018f31e4b6fSAnirudh Venkataramanan 1019f31e4b6fSAnirudh Venkataramanan /** 1020f31e4b6fSAnirudh Venkataramanan * ice_clear_pxe_mode - clear pxe operations mode 1021f31e4b6fSAnirudh Venkataramanan * @hw: pointer to the hw struct 1022f31e4b6fSAnirudh Venkataramanan * 1023f31e4b6fSAnirudh Venkataramanan * Make sure all PXE mode settings are cleared, including things 1024f31e4b6fSAnirudh Venkataramanan * like descriptor fetch/write-back mode. 1025f31e4b6fSAnirudh Venkataramanan */ 1026f31e4b6fSAnirudh Venkataramanan void ice_clear_pxe_mode(struct ice_hw *hw) 1027f31e4b6fSAnirudh Venkataramanan { 1028f31e4b6fSAnirudh Venkataramanan if (ice_check_sq_alive(hw, &hw->adminq)) 1029f31e4b6fSAnirudh Venkataramanan ice_aq_clear_pxe_mode(hw); 1030f31e4b6fSAnirudh Venkataramanan } 1031