1*71d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2*71d10453SEric Joyner /* Copyright (c) 2020, Intel Corporation 3*71d10453SEric Joyner * All rights reserved. 4*71d10453SEric Joyner * 5*71d10453SEric Joyner * Redistribution and use in source and binary forms, with or without 6*71d10453SEric Joyner * modification, are permitted provided that the following conditions are met: 7*71d10453SEric Joyner * 8*71d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 9*71d10453SEric Joyner * this list of conditions and the following disclaimer. 10*71d10453SEric Joyner * 11*71d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 12*71d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the 13*71d10453SEric Joyner * documentation and/or other materials provided with the distribution. 14*71d10453SEric Joyner * 15*71d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 16*71d10453SEric Joyner * contributors may be used to endorse or promote products derived from 17*71d10453SEric Joyner * this software without specific prior written permission. 18*71d10453SEric Joyner * 19*71d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20*71d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*71d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*71d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23*71d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*71d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*71d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*71d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*71d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*71d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*71d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 30*71d10453SEric Joyner */ 31*71d10453SEric Joyner /*$FreeBSD$*/ 32*71d10453SEric Joyner 33*71d10453SEric Joyner #include "ice_common.h" 34*71d10453SEric Joyner #include "ice_sched.h" 35*71d10453SEric Joyner #include "ice_adminq_cmd.h" 36*71d10453SEric Joyner 37*71d10453SEric Joyner #include "ice_flow.h" 38*71d10453SEric Joyner #include "ice_switch.h" 39*71d10453SEric Joyner 40*71d10453SEric Joyner #define ICE_PF_RESET_WAIT_COUNT 300 41*71d10453SEric Joyner 42*71d10453SEric Joyner /** 43*71d10453SEric Joyner * ice_set_mac_type - Sets MAC type 44*71d10453SEric Joyner * @hw: pointer to the HW structure 45*71d10453SEric Joyner * 46*71d10453SEric Joyner * This function sets the MAC type of the adapter based on the 47*71d10453SEric Joyner * vendor ID and device ID stored in the HW structure. 48*71d10453SEric Joyner */ 49*71d10453SEric Joyner enum ice_status ice_set_mac_type(struct ice_hw *hw) 50*71d10453SEric Joyner { 51*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 52*71d10453SEric Joyner 53*71d10453SEric Joyner if (hw->vendor_id != ICE_INTEL_VENDOR_ID) 54*71d10453SEric Joyner return ICE_ERR_DEVICE_NOT_SUPPORTED; 55*71d10453SEric Joyner 56*71d10453SEric Joyner switch (hw->device_id) { 57*71d10453SEric Joyner case ICE_DEV_ID_E810C_BACKPLANE: 58*71d10453SEric Joyner case ICE_DEV_ID_E810C_QSFP: 59*71d10453SEric Joyner case ICE_DEV_ID_E810C_SFP: 60*71d10453SEric Joyner case ICE_DEV_ID_E810_XXV_BACKPLANE: 61*71d10453SEric Joyner case ICE_DEV_ID_E810_XXV_QSFP: 62*71d10453SEric Joyner case ICE_DEV_ID_E810_XXV_SFP: 63*71d10453SEric Joyner hw->mac_type = ICE_MAC_E810; 64*71d10453SEric Joyner break; 65*71d10453SEric Joyner case ICE_DEV_ID_E822C_10G_BASE_T: 66*71d10453SEric Joyner case ICE_DEV_ID_E822C_BACKPLANE: 67*71d10453SEric Joyner case ICE_DEV_ID_E822C_QSFP: 68*71d10453SEric Joyner case ICE_DEV_ID_E822C_SFP: 69*71d10453SEric Joyner case ICE_DEV_ID_E822C_SGMII: 70*71d10453SEric Joyner case ICE_DEV_ID_E822L_10G_BASE_T: 71*71d10453SEric Joyner case ICE_DEV_ID_E822L_BACKPLANE: 72*71d10453SEric Joyner case ICE_DEV_ID_E822L_SFP: 73*71d10453SEric Joyner case ICE_DEV_ID_E822L_SGMII: 74*71d10453SEric Joyner case ICE_DEV_ID_E823L_10G_BASE_T: 75*71d10453SEric Joyner case ICE_DEV_ID_E823L_1GBE: 76*71d10453SEric Joyner case ICE_DEV_ID_E823L_BACKPLANE: 77*71d10453SEric Joyner case ICE_DEV_ID_E823L_QSFP: 78*71d10453SEric Joyner case ICE_DEV_ID_E823L_SFP: 79*71d10453SEric Joyner hw->mac_type = ICE_MAC_GENERIC; 80*71d10453SEric Joyner break; 81*71d10453SEric Joyner default: 82*71d10453SEric Joyner hw->mac_type = ICE_MAC_UNKNOWN; 83*71d10453SEric Joyner break; 84*71d10453SEric Joyner } 85*71d10453SEric Joyner 86*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type); 87*71d10453SEric Joyner return ICE_SUCCESS; 88*71d10453SEric Joyner } 89*71d10453SEric Joyner 90*71d10453SEric Joyner /** 91*71d10453SEric Joyner * ice_clear_pf_cfg - Clear PF configuration 92*71d10453SEric Joyner * @hw: pointer to the hardware structure 93*71d10453SEric Joyner * 94*71d10453SEric Joyner * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port 95*71d10453SEric Joyner * configuration, flow director filters, etc.). 96*71d10453SEric Joyner */ 97*71d10453SEric Joyner enum ice_status ice_clear_pf_cfg(struct ice_hw *hw) 98*71d10453SEric Joyner { 99*71d10453SEric Joyner struct ice_aq_desc desc; 100*71d10453SEric Joyner 101*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg); 102*71d10453SEric Joyner 103*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 104*71d10453SEric Joyner } 105*71d10453SEric Joyner 106*71d10453SEric Joyner /** 107*71d10453SEric Joyner * ice_aq_manage_mac_read - manage MAC address read command 108*71d10453SEric Joyner * @hw: pointer to the HW struct 109*71d10453SEric Joyner * @buf: a virtual buffer to hold the manage MAC read response 110*71d10453SEric Joyner * @buf_size: Size of the virtual buffer 111*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 112*71d10453SEric Joyner * 113*71d10453SEric Joyner * This function is used to return per PF station MAC address (0x0107). 114*71d10453SEric Joyner * NOTE: Upon successful completion of this command, MAC address information 115*71d10453SEric Joyner * is returned in user specified buffer. Please interpret user specified 116*71d10453SEric Joyner * buffer as "manage_mac_read" response. 117*71d10453SEric Joyner * Response such as various MAC addresses are stored in HW struct (port.mac) 118*71d10453SEric Joyner * ice_aq_discover_caps is expected to be called before this function is called. 119*71d10453SEric Joyner */ 120*71d10453SEric Joyner enum ice_status 121*71d10453SEric Joyner ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size, 122*71d10453SEric Joyner struct ice_sq_cd *cd) 123*71d10453SEric Joyner { 124*71d10453SEric Joyner struct ice_aqc_manage_mac_read_resp *resp; 125*71d10453SEric Joyner struct ice_aqc_manage_mac_read *cmd; 126*71d10453SEric Joyner struct ice_aq_desc desc; 127*71d10453SEric Joyner enum ice_status status; 128*71d10453SEric Joyner u16 flags; 129*71d10453SEric Joyner u8 i; 130*71d10453SEric Joyner 131*71d10453SEric Joyner cmd = &desc.params.mac_read; 132*71d10453SEric Joyner 133*71d10453SEric Joyner if (buf_size < sizeof(*resp)) 134*71d10453SEric Joyner return ICE_ERR_BUF_TOO_SHORT; 135*71d10453SEric Joyner 136*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read); 137*71d10453SEric Joyner 138*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 139*71d10453SEric Joyner if (status) 140*71d10453SEric Joyner return status; 141*71d10453SEric Joyner 142*71d10453SEric Joyner resp = (struct ice_aqc_manage_mac_read_resp *)buf; 143*71d10453SEric Joyner flags = LE16_TO_CPU(cmd->flags) & ICE_AQC_MAN_MAC_READ_M; 144*71d10453SEric Joyner 145*71d10453SEric Joyner if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) { 146*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n"); 147*71d10453SEric Joyner return ICE_ERR_CFG; 148*71d10453SEric Joyner } 149*71d10453SEric Joyner 150*71d10453SEric Joyner /* A single port can report up to two (LAN and WoL) addresses */ 151*71d10453SEric Joyner for (i = 0; i < cmd->num_addr; i++) 152*71d10453SEric Joyner if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) { 153*71d10453SEric Joyner ice_memcpy(hw->port_info->mac.lan_addr, 154*71d10453SEric Joyner resp[i].mac_addr, ETH_ALEN, 155*71d10453SEric Joyner ICE_DMA_TO_NONDMA); 156*71d10453SEric Joyner ice_memcpy(hw->port_info->mac.perm_addr, 157*71d10453SEric Joyner resp[i].mac_addr, 158*71d10453SEric Joyner ETH_ALEN, ICE_DMA_TO_NONDMA); 159*71d10453SEric Joyner break; 160*71d10453SEric Joyner } 161*71d10453SEric Joyner return ICE_SUCCESS; 162*71d10453SEric Joyner } 163*71d10453SEric Joyner 164*71d10453SEric Joyner /** 165*71d10453SEric Joyner * ice_aq_get_phy_caps - returns PHY capabilities 166*71d10453SEric Joyner * @pi: port information structure 167*71d10453SEric Joyner * @qual_mods: report qualified modules 168*71d10453SEric Joyner * @report_mode: report mode capabilities 169*71d10453SEric Joyner * @pcaps: structure for PHY capabilities to be filled 170*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 171*71d10453SEric Joyner * 172*71d10453SEric Joyner * Returns the various PHY capabilities supported on the Port (0x0600) 173*71d10453SEric Joyner */ 174*71d10453SEric Joyner enum ice_status 175*71d10453SEric Joyner ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, 176*71d10453SEric Joyner struct ice_aqc_get_phy_caps_data *pcaps, 177*71d10453SEric Joyner struct ice_sq_cd *cd) 178*71d10453SEric Joyner { 179*71d10453SEric Joyner struct ice_aqc_get_phy_caps *cmd; 180*71d10453SEric Joyner u16 pcaps_size = sizeof(*pcaps); 181*71d10453SEric Joyner struct ice_aq_desc desc; 182*71d10453SEric Joyner enum ice_status status; 183*71d10453SEric Joyner 184*71d10453SEric Joyner cmd = &desc.params.get_phy; 185*71d10453SEric Joyner 186*71d10453SEric Joyner if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi) 187*71d10453SEric Joyner return ICE_ERR_PARAM; 188*71d10453SEric Joyner 189*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps); 190*71d10453SEric Joyner 191*71d10453SEric Joyner if (qual_mods) 192*71d10453SEric Joyner cmd->param0 |= CPU_TO_LE16(ICE_AQC_GET_PHY_RQM); 193*71d10453SEric Joyner 194*71d10453SEric Joyner cmd->param0 |= CPU_TO_LE16(report_mode); 195*71d10453SEric Joyner status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd); 196*71d10453SEric Joyner 197*71d10453SEric Joyner if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP) { 198*71d10453SEric Joyner pi->phy.phy_type_low = LE64_TO_CPU(pcaps->phy_type_low); 199*71d10453SEric Joyner pi->phy.phy_type_high = LE64_TO_CPU(pcaps->phy_type_high); 200*71d10453SEric Joyner } 201*71d10453SEric Joyner 202*71d10453SEric Joyner return status; 203*71d10453SEric Joyner } 204*71d10453SEric Joyner 205*71d10453SEric Joyner /** 206*71d10453SEric Joyner * ice_aq_get_link_topo_handle - get link topology node return status 207*71d10453SEric Joyner * @pi: port information structure 208*71d10453SEric Joyner * @node_type: requested node type 209*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 210*71d10453SEric Joyner * 211*71d10453SEric Joyner * Get link topology node return status for specified node type (0x06E0) 212*71d10453SEric Joyner * 213*71d10453SEric Joyner * Node type cage can be used to determine if cage is present. If AQC 214*71d10453SEric Joyner * returns error (ENOENT), then no cage present. If no cage present, then 215*71d10453SEric Joyner * connection type is backplane or BASE-T. 216*71d10453SEric Joyner */ 217*71d10453SEric Joyner static enum ice_status 218*71d10453SEric Joyner ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type, 219*71d10453SEric Joyner struct ice_sq_cd *cd) 220*71d10453SEric Joyner { 221*71d10453SEric Joyner struct ice_aqc_get_link_topo *cmd; 222*71d10453SEric Joyner struct ice_aq_desc desc; 223*71d10453SEric Joyner 224*71d10453SEric Joyner cmd = &desc.params.get_link_topo; 225*71d10453SEric Joyner 226*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); 227*71d10453SEric Joyner 228*71d10453SEric Joyner cmd->addr.node_type_ctx = (ICE_AQC_LINK_TOPO_NODE_CTX_PORT << 229*71d10453SEric Joyner ICE_AQC_LINK_TOPO_NODE_CTX_S); 230*71d10453SEric Joyner 231*71d10453SEric Joyner /* set node type */ 232*71d10453SEric Joyner cmd->addr.node_type_ctx |= (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type); 233*71d10453SEric Joyner 234*71d10453SEric Joyner return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd); 235*71d10453SEric Joyner } 236*71d10453SEric Joyner 237*71d10453SEric Joyner /* 238*71d10453SEric Joyner * ice_is_media_cage_present 239*71d10453SEric Joyner * @pi: port information structure 240*71d10453SEric Joyner * 241*71d10453SEric Joyner * Returns true if media cage is present, else false. If no cage, then 242*71d10453SEric Joyner * media type is backplane or BASE-T. 243*71d10453SEric Joyner */ 244*71d10453SEric Joyner static bool ice_is_media_cage_present(struct ice_port_info *pi) 245*71d10453SEric Joyner { 246*71d10453SEric Joyner /* Node type cage can be used to determine if cage is present. If AQC 247*71d10453SEric Joyner * returns error (ENOENT), then no cage present. If no cage present then 248*71d10453SEric Joyner * connection type is backplane or BASE-T. 249*71d10453SEric Joyner */ 250*71d10453SEric Joyner return !ice_aq_get_link_topo_handle(pi, 251*71d10453SEric Joyner ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE, 252*71d10453SEric Joyner NULL); 253*71d10453SEric Joyner } 254*71d10453SEric Joyner 255*71d10453SEric Joyner /** 256*71d10453SEric Joyner * ice_get_media_type - Gets media type 257*71d10453SEric Joyner * @pi: port information structure 258*71d10453SEric Joyner */ 259*71d10453SEric Joyner static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) 260*71d10453SEric Joyner { 261*71d10453SEric Joyner struct ice_link_status *hw_link_info; 262*71d10453SEric Joyner 263*71d10453SEric Joyner if (!pi) 264*71d10453SEric Joyner return ICE_MEDIA_UNKNOWN; 265*71d10453SEric Joyner 266*71d10453SEric Joyner hw_link_info = &pi->phy.link_info; 267*71d10453SEric Joyner if (hw_link_info->phy_type_low && hw_link_info->phy_type_high) 268*71d10453SEric Joyner /* If more than one media type is selected, report unknown */ 269*71d10453SEric Joyner return ICE_MEDIA_UNKNOWN; 270*71d10453SEric Joyner 271*71d10453SEric Joyner if (hw_link_info->phy_type_low) { 272*71d10453SEric Joyner switch (hw_link_info->phy_type_low) { 273*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_SX: 274*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_LX: 275*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_SR: 276*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_LR: 277*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 278*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_SR: 279*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_LR: 280*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_SR4: 281*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_LR4: 282*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_SR2: 283*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_LR2: 284*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_SR: 285*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_FR: 286*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_LR: 287*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_SR4: 288*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_LR4: 289*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_SR2: 290*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_DR: 291*71d10453SEric Joyner return ICE_MEDIA_FIBER; 292*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100BASE_TX: 293*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_T: 294*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_2500BASE_T: 295*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_5GBASE_T: 296*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_T: 297*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_T: 298*71d10453SEric Joyner return ICE_MEDIA_BASET; 299*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10G_SFI_DA: 300*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_CR: 301*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 302*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_CR1: 303*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_CR4: 304*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_CR2: 305*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_CP: 306*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_CR4: 307*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 308*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_CP2: 309*71d10453SEric Joyner return ICE_MEDIA_DA; 310*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 311*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40G_XLAUI: 312*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_LAUI2: 313*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_AUI2: 314*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_AUI1: 315*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100G_AUI4: 316*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100G_CAUI4: 317*71d10453SEric Joyner if (ice_is_media_cage_present(pi)) 318*71d10453SEric Joyner return ICE_MEDIA_DA; 319*71d10453SEric Joyner /* fall-through */ 320*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_KX: 321*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_2500BASE_KX: 322*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_2500BASE_X: 323*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_5GBASE_KR: 324*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 325*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_KR: 326*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_KR1: 327*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 328*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_KR4: 329*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 330*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_KR2: 331*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_KR4: 332*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 333*71d10453SEric Joyner return ICE_MEDIA_BACKPLANE; 334*71d10453SEric Joyner } 335*71d10453SEric Joyner } else { 336*71d10453SEric Joyner switch (hw_link_info->phy_type_high) { 337*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100G_AUI2: 338*71d10453SEric Joyner if (ice_is_media_cage_present(pi)) 339*71d10453SEric Joyner return ICE_MEDIA_DA; 340*71d10453SEric Joyner /* fall-through */ 341*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 342*71d10453SEric Joyner return ICE_MEDIA_BACKPLANE; 343*71d10453SEric Joyner } 344*71d10453SEric Joyner } 345*71d10453SEric Joyner return ICE_MEDIA_UNKNOWN; 346*71d10453SEric Joyner } 347*71d10453SEric Joyner 348*71d10453SEric Joyner /** 349*71d10453SEric Joyner * ice_aq_get_link_info 350*71d10453SEric Joyner * @pi: port information structure 351*71d10453SEric Joyner * @ena_lse: enable/disable LinkStatusEvent reporting 352*71d10453SEric Joyner * @link: pointer to link status structure - optional 353*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 354*71d10453SEric Joyner * 355*71d10453SEric Joyner * Get Link Status (0x607). Returns the link status of the adapter. 356*71d10453SEric Joyner */ 357*71d10453SEric Joyner enum ice_status 358*71d10453SEric Joyner ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, 359*71d10453SEric Joyner struct ice_link_status *link, struct ice_sq_cd *cd) 360*71d10453SEric Joyner { 361*71d10453SEric Joyner struct ice_aqc_get_link_status_data link_data = { 0 }; 362*71d10453SEric Joyner struct ice_aqc_get_link_status *resp; 363*71d10453SEric Joyner struct ice_link_status *li_old, *li; 364*71d10453SEric Joyner enum ice_media_type *hw_media_type; 365*71d10453SEric Joyner struct ice_fc_info *hw_fc_info; 366*71d10453SEric Joyner bool tx_pause, rx_pause; 367*71d10453SEric Joyner struct ice_aq_desc desc; 368*71d10453SEric Joyner enum ice_status status; 369*71d10453SEric Joyner struct ice_hw *hw; 370*71d10453SEric Joyner u16 cmd_flags; 371*71d10453SEric Joyner 372*71d10453SEric Joyner if (!pi) 373*71d10453SEric Joyner return ICE_ERR_PARAM; 374*71d10453SEric Joyner hw = pi->hw; 375*71d10453SEric Joyner 376*71d10453SEric Joyner li_old = &pi->phy.link_info_old; 377*71d10453SEric Joyner hw_media_type = &pi->phy.media_type; 378*71d10453SEric Joyner li = &pi->phy.link_info; 379*71d10453SEric Joyner hw_fc_info = &pi->fc; 380*71d10453SEric Joyner 381*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status); 382*71d10453SEric Joyner cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS; 383*71d10453SEric Joyner resp = &desc.params.get_link_status; 384*71d10453SEric Joyner resp->cmd_flags = CPU_TO_LE16(cmd_flags); 385*71d10453SEric Joyner resp->lport_num = pi->lport; 386*71d10453SEric Joyner 387*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd); 388*71d10453SEric Joyner 389*71d10453SEric Joyner if (status != ICE_SUCCESS) 390*71d10453SEric Joyner return status; 391*71d10453SEric Joyner 392*71d10453SEric Joyner /* save off old link status information */ 393*71d10453SEric Joyner *li_old = *li; 394*71d10453SEric Joyner 395*71d10453SEric Joyner /* update current link status information */ 396*71d10453SEric Joyner li->link_speed = LE16_TO_CPU(link_data.link_speed); 397*71d10453SEric Joyner li->phy_type_low = LE64_TO_CPU(link_data.phy_type_low); 398*71d10453SEric Joyner li->phy_type_high = LE64_TO_CPU(link_data.phy_type_high); 399*71d10453SEric Joyner *hw_media_type = ice_get_media_type(pi); 400*71d10453SEric Joyner li->link_info = link_data.link_info; 401*71d10453SEric Joyner li->an_info = link_data.an_info; 402*71d10453SEric Joyner li->ext_info = link_data.ext_info; 403*71d10453SEric Joyner li->max_frame_size = LE16_TO_CPU(link_data.max_frame_size); 404*71d10453SEric Joyner li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK; 405*71d10453SEric Joyner li->topo_media_conflict = link_data.topo_media_conflict; 406*71d10453SEric Joyner li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M | 407*71d10453SEric Joyner ICE_AQ_CFG_PACING_TYPE_M); 408*71d10453SEric Joyner 409*71d10453SEric Joyner /* update fc info */ 410*71d10453SEric Joyner tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX); 411*71d10453SEric Joyner rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX); 412*71d10453SEric Joyner if (tx_pause && rx_pause) 413*71d10453SEric Joyner hw_fc_info->current_mode = ICE_FC_FULL; 414*71d10453SEric Joyner else if (tx_pause) 415*71d10453SEric Joyner hw_fc_info->current_mode = ICE_FC_TX_PAUSE; 416*71d10453SEric Joyner else if (rx_pause) 417*71d10453SEric Joyner hw_fc_info->current_mode = ICE_FC_RX_PAUSE; 418*71d10453SEric Joyner else 419*71d10453SEric Joyner hw_fc_info->current_mode = ICE_FC_NONE; 420*71d10453SEric Joyner 421*71d10453SEric Joyner li->lse_ena = !!(resp->cmd_flags & CPU_TO_LE16(ICE_AQ_LSE_IS_ENABLED)); 422*71d10453SEric Joyner 423*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "link_speed = 0x%x\n", li->link_speed); 424*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n", 425*71d10453SEric Joyner (unsigned long long)li->phy_type_low); 426*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n", 427*71d10453SEric Joyner (unsigned long long)li->phy_type_high); 428*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "media_type = 0x%x\n", *hw_media_type); 429*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "link_info = 0x%x\n", li->link_info); 430*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "an_info = 0x%x\n", li->an_info); 431*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "ext_info = 0x%x\n", li->ext_info); 432*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "lse_ena = 0x%x\n", li->lse_ena); 433*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "max_frame = 0x%x\n", li->max_frame_size); 434*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "pacing = 0x%x\n", li->pacing); 435*71d10453SEric Joyner 436*71d10453SEric Joyner /* save link status information */ 437*71d10453SEric Joyner if (link) 438*71d10453SEric Joyner *link = *li; 439*71d10453SEric Joyner 440*71d10453SEric Joyner /* flag cleared so calling functions don't call AQ again */ 441*71d10453SEric Joyner pi->phy.get_link_info = false; 442*71d10453SEric Joyner 443*71d10453SEric Joyner return ICE_SUCCESS; 444*71d10453SEric Joyner } 445*71d10453SEric Joyner 446*71d10453SEric Joyner /** 447*71d10453SEric Joyner * ice_aq_set_mac_cfg 448*71d10453SEric Joyner * @hw: pointer to the HW struct 449*71d10453SEric Joyner * @max_frame_size: Maximum Frame Size to be supported 450*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 451*71d10453SEric Joyner * 452*71d10453SEric Joyner * Set MAC configuration (0x0603) 453*71d10453SEric Joyner */ 454*71d10453SEric Joyner enum ice_status 455*71d10453SEric Joyner ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd) 456*71d10453SEric Joyner { 457*71d10453SEric Joyner u16 fc_threshold_val, tx_timer_val; 458*71d10453SEric Joyner struct ice_aqc_set_mac_cfg *cmd; 459*71d10453SEric Joyner struct ice_aq_desc desc; 460*71d10453SEric Joyner u32 reg_val; 461*71d10453SEric Joyner 462*71d10453SEric Joyner cmd = &desc.params.set_mac_cfg; 463*71d10453SEric Joyner 464*71d10453SEric Joyner if (max_frame_size == 0) 465*71d10453SEric Joyner return ICE_ERR_PARAM; 466*71d10453SEric Joyner 467*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg); 468*71d10453SEric Joyner 469*71d10453SEric Joyner cmd->max_frame_size = CPU_TO_LE16(max_frame_size); 470*71d10453SEric Joyner 471*71d10453SEric Joyner /* We read back the transmit timer and fc threshold value of 472*71d10453SEric Joyner * LFC. Thus, we will use index = 473*71d10453SEric Joyner * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX. 474*71d10453SEric Joyner * 475*71d10453SEric Joyner * Also, because we are opearating on transmit timer and fc 476*71d10453SEric Joyner * threshold of LFC, we don't turn on any bit in tx_tmr_priority 477*71d10453SEric Joyner */ 478*71d10453SEric Joyner #define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 479*71d10453SEric Joyner 480*71d10453SEric Joyner /* Retrieve the transmit timer */ 481*71d10453SEric Joyner reg_val = rd32(hw, 482*71d10453SEric Joyner PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC)); 483*71d10453SEric Joyner tx_timer_val = reg_val & 484*71d10453SEric Joyner PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M; 485*71d10453SEric Joyner cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val); 486*71d10453SEric Joyner 487*71d10453SEric Joyner /* Retrieve the fc threshold */ 488*71d10453SEric Joyner reg_val = rd32(hw, 489*71d10453SEric Joyner PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC)); 490*71d10453SEric Joyner fc_threshold_val = reg_val & MAKEMASK(0xFFFF, 0); 491*71d10453SEric Joyner cmd->fc_refresh_threshold = CPU_TO_LE16(fc_threshold_val); 492*71d10453SEric Joyner 493*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 494*71d10453SEric Joyner } 495*71d10453SEric Joyner 496*71d10453SEric Joyner /** 497*71d10453SEric Joyner * ice_init_fltr_mgmt_struct - initializes filter management list and locks 498*71d10453SEric Joyner * @hw: pointer to the HW struct 499*71d10453SEric Joyner */ 500*71d10453SEric Joyner static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw) 501*71d10453SEric Joyner { 502*71d10453SEric Joyner struct ice_switch_info *sw; 503*71d10453SEric Joyner 504*71d10453SEric Joyner hw->switch_info = (struct ice_switch_info *) 505*71d10453SEric Joyner ice_malloc(hw, sizeof(*hw->switch_info)); 506*71d10453SEric Joyner 507*71d10453SEric Joyner sw = hw->switch_info; 508*71d10453SEric Joyner 509*71d10453SEric Joyner if (!sw) 510*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 511*71d10453SEric Joyner 512*71d10453SEric Joyner INIT_LIST_HEAD(&sw->vsi_list_map_head); 513*71d10453SEric Joyner 514*71d10453SEric Joyner return ice_init_def_sw_recp(hw, &hw->switch_info->recp_list); 515*71d10453SEric Joyner } 516*71d10453SEric Joyner 517*71d10453SEric Joyner /** 518*71d10453SEric Joyner * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks 519*71d10453SEric Joyner * @hw: pointer to the HW struct 520*71d10453SEric Joyner */ 521*71d10453SEric Joyner static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw) 522*71d10453SEric Joyner { 523*71d10453SEric Joyner struct ice_switch_info *sw = hw->switch_info; 524*71d10453SEric Joyner struct ice_vsi_list_map_info *v_pos_map; 525*71d10453SEric Joyner struct ice_vsi_list_map_info *v_tmp_map; 526*71d10453SEric Joyner struct ice_sw_recipe *recps; 527*71d10453SEric Joyner u8 i; 528*71d10453SEric Joyner 529*71d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(v_pos_map, v_tmp_map, &sw->vsi_list_map_head, 530*71d10453SEric Joyner ice_vsi_list_map_info, list_entry) { 531*71d10453SEric Joyner LIST_DEL(&v_pos_map->list_entry); 532*71d10453SEric Joyner ice_free(hw, v_pos_map); 533*71d10453SEric Joyner } 534*71d10453SEric Joyner recps = hw->switch_info->recp_list; 535*71d10453SEric Joyner for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 536*71d10453SEric Joyner struct ice_recp_grp_entry *rg_entry, *tmprg_entry; 537*71d10453SEric Joyner 538*71d10453SEric Joyner recps[i].root_rid = i; 539*71d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(rg_entry, tmprg_entry, 540*71d10453SEric Joyner &recps[i].rg_list, ice_recp_grp_entry, 541*71d10453SEric Joyner l_entry) { 542*71d10453SEric Joyner LIST_DEL(&rg_entry->l_entry); 543*71d10453SEric Joyner ice_free(hw, rg_entry); 544*71d10453SEric Joyner } 545*71d10453SEric Joyner 546*71d10453SEric Joyner if (recps[i].adv_rule) { 547*71d10453SEric Joyner struct ice_adv_fltr_mgmt_list_entry *tmp_entry; 548*71d10453SEric Joyner struct ice_adv_fltr_mgmt_list_entry *lst_itr; 549*71d10453SEric Joyner 550*71d10453SEric Joyner ice_destroy_lock(&recps[i].filt_rule_lock); 551*71d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry, 552*71d10453SEric Joyner &recps[i].filt_rules, 553*71d10453SEric Joyner ice_adv_fltr_mgmt_list_entry, 554*71d10453SEric Joyner list_entry) { 555*71d10453SEric Joyner LIST_DEL(&lst_itr->list_entry); 556*71d10453SEric Joyner ice_free(hw, lst_itr->lkups); 557*71d10453SEric Joyner ice_free(hw, lst_itr); 558*71d10453SEric Joyner } 559*71d10453SEric Joyner } else { 560*71d10453SEric Joyner struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry; 561*71d10453SEric Joyner 562*71d10453SEric Joyner ice_destroy_lock(&recps[i].filt_rule_lock); 563*71d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry, 564*71d10453SEric Joyner &recps[i].filt_rules, 565*71d10453SEric Joyner ice_fltr_mgmt_list_entry, 566*71d10453SEric Joyner list_entry) { 567*71d10453SEric Joyner LIST_DEL(&lst_itr->list_entry); 568*71d10453SEric Joyner ice_free(hw, lst_itr); 569*71d10453SEric Joyner } 570*71d10453SEric Joyner } 571*71d10453SEric Joyner if (recps[i].root_buf) 572*71d10453SEric Joyner ice_free(hw, recps[i].root_buf); 573*71d10453SEric Joyner } 574*71d10453SEric Joyner ice_rm_all_sw_replay_rule_info(hw); 575*71d10453SEric Joyner ice_free(hw, sw->recp_list); 576*71d10453SEric Joyner ice_free(hw, sw); 577*71d10453SEric Joyner } 578*71d10453SEric Joyner 579*71d10453SEric Joyner /** 580*71d10453SEric Joyner * ice_get_itr_intrl_gran 581*71d10453SEric Joyner * @hw: pointer to the HW struct 582*71d10453SEric Joyner * 583*71d10453SEric Joyner * Determines the ITR/INTRL granularities based on the maximum aggregate 584*71d10453SEric Joyner * bandwidth according to the device's configuration during power-on. 585*71d10453SEric Joyner */ 586*71d10453SEric Joyner static void ice_get_itr_intrl_gran(struct ice_hw *hw) 587*71d10453SEric Joyner { 588*71d10453SEric Joyner u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) & 589*71d10453SEric Joyner GL_PWR_MODE_CTL_CAR_MAX_BW_M) >> 590*71d10453SEric Joyner GL_PWR_MODE_CTL_CAR_MAX_BW_S; 591*71d10453SEric Joyner 592*71d10453SEric Joyner switch (max_agg_bw) { 593*71d10453SEric Joyner case ICE_MAX_AGG_BW_200G: 594*71d10453SEric Joyner case ICE_MAX_AGG_BW_100G: 595*71d10453SEric Joyner case ICE_MAX_AGG_BW_50G: 596*71d10453SEric Joyner hw->itr_gran = ICE_ITR_GRAN_ABOVE_25; 597*71d10453SEric Joyner hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25; 598*71d10453SEric Joyner break; 599*71d10453SEric Joyner case ICE_MAX_AGG_BW_25G: 600*71d10453SEric Joyner hw->itr_gran = ICE_ITR_GRAN_MAX_25; 601*71d10453SEric Joyner hw->intrl_gran = ICE_INTRL_GRAN_MAX_25; 602*71d10453SEric Joyner break; 603*71d10453SEric Joyner } 604*71d10453SEric Joyner } 605*71d10453SEric Joyner 606*71d10453SEric Joyner /** 607*71d10453SEric Joyner * ice_print_rollback_msg - print FW rollback message 608*71d10453SEric Joyner * @hw: pointer to the hardware structure 609*71d10453SEric Joyner */ 610*71d10453SEric Joyner void ice_print_rollback_msg(struct ice_hw *hw) 611*71d10453SEric Joyner { 612*71d10453SEric Joyner char nvm_str[ICE_NVM_VER_LEN] = { 0 }; 613*71d10453SEric Joyner struct ice_nvm_info *nvm = &hw->nvm; 614*71d10453SEric Joyner struct ice_orom_info *orom; 615*71d10453SEric Joyner 616*71d10453SEric Joyner orom = &nvm->orom; 617*71d10453SEric Joyner 618*71d10453SEric Joyner SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d", 619*71d10453SEric Joyner nvm->major_ver, nvm->minor_ver, nvm->eetrack, orom->major, 620*71d10453SEric Joyner orom->build, orom->patch); 621*71d10453SEric Joyner ice_warn(hw, 622*71d10453SEric Joyner "Firmware rollback mode detected. Current version is NVM: %s, FW: %d.%d. Device may exhibit limited functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware rollback mode\n", 623*71d10453SEric Joyner nvm_str, hw->fw_maj_ver, hw->fw_min_ver); 624*71d10453SEric Joyner } 625*71d10453SEric Joyner 626*71d10453SEric Joyner /** 627*71d10453SEric Joyner * ice_init_hw - main hardware initialization routine 628*71d10453SEric Joyner * @hw: pointer to the hardware structure 629*71d10453SEric Joyner */ 630*71d10453SEric Joyner enum ice_status ice_init_hw(struct ice_hw *hw) 631*71d10453SEric Joyner { 632*71d10453SEric Joyner struct ice_aqc_get_phy_caps_data *pcaps; 633*71d10453SEric Joyner enum ice_status status; 634*71d10453SEric Joyner u16 mac_buf_len; 635*71d10453SEric Joyner void *mac_buf; 636*71d10453SEric Joyner 637*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 638*71d10453SEric Joyner 639*71d10453SEric Joyner /* Set MAC type based on DeviceID */ 640*71d10453SEric Joyner status = ice_set_mac_type(hw); 641*71d10453SEric Joyner if (status) 642*71d10453SEric Joyner return status; 643*71d10453SEric Joyner 644*71d10453SEric Joyner hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) & 645*71d10453SEric Joyner PF_FUNC_RID_FUNCTION_NUMBER_M) >> 646*71d10453SEric Joyner PF_FUNC_RID_FUNCTION_NUMBER_S; 647*71d10453SEric Joyner 648*71d10453SEric Joyner status = ice_reset(hw, ICE_RESET_PFR); 649*71d10453SEric Joyner if (status) 650*71d10453SEric Joyner return status; 651*71d10453SEric Joyner 652*71d10453SEric Joyner ice_get_itr_intrl_gran(hw); 653*71d10453SEric Joyner 654*71d10453SEric Joyner status = ice_create_all_ctrlq(hw); 655*71d10453SEric Joyner if (status) 656*71d10453SEric Joyner goto err_unroll_cqinit; 657*71d10453SEric Joyner 658*71d10453SEric Joyner status = ice_init_nvm(hw); 659*71d10453SEric Joyner if (status) 660*71d10453SEric Joyner goto err_unroll_cqinit; 661*71d10453SEric Joyner 662*71d10453SEric Joyner if (ice_get_fw_mode(hw) == ICE_FW_MODE_ROLLBACK) 663*71d10453SEric Joyner ice_print_rollback_msg(hw); 664*71d10453SEric Joyner 665*71d10453SEric Joyner status = ice_clear_pf_cfg(hw); 666*71d10453SEric Joyner if (status) 667*71d10453SEric Joyner goto err_unroll_cqinit; 668*71d10453SEric Joyner 669*71d10453SEric Joyner ice_clear_pxe_mode(hw); 670*71d10453SEric Joyner 671*71d10453SEric Joyner status = ice_get_caps(hw); 672*71d10453SEric Joyner if (status) 673*71d10453SEric Joyner goto err_unroll_cqinit; 674*71d10453SEric Joyner 675*71d10453SEric Joyner hw->port_info = (struct ice_port_info *) 676*71d10453SEric Joyner ice_malloc(hw, sizeof(*hw->port_info)); 677*71d10453SEric Joyner if (!hw->port_info) { 678*71d10453SEric Joyner status = ICE_ERR_NO_MEMORY; 679*71d10453SEric Joyner goto err_unroll_cqinit; 680*71d10453SEric Joyner } 681*71d10453SEric Joyner 682*71d10453SEric Joyner /* set the back pointer to HW */ 683*71d10453SEric Joyner hw->port_info->hw = hw; 684*71d10453SEric Joyner 685*71d10453SEric Joyner /* Initialize port_info struct with switch configuration data */ 686*71d10453SEric Joyner status = ice_get_initial_sw_cfg(hw); 687*71d10453SEric Joyner if (status) 688*71d10453SEric Joyner goto err_unroll_alloc; 689*71d10453SEric Joyner 690*71d10453SEric Joyner hw->evb_veb = true; 691*71d10453SEric Joyner /* Query the allocated resources for Tx scheduler */ 692*71d10453SEric Joyner status = ice_sched_query_res_alloc(hw); 693*71d10453SEric Joyner if (status) { 694*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, 695*71d10453SEric Joyner "Failed to get scheduler allocated resources\n"); 696*71d10453SEric Joyner goto err_unroll_alloc; 697*71d10453SEric Joyner } 698*71d10453SEric Joyner ice_sched_get_psm_clk_freq(hw); 699*71d10453SEric Joyner 700*71d10453SEric Joyner /* Initialize port_info struct with scheduler data */ 701*71d10453SEric Joyner status = ice_sched_init_port(hw->port_info); 702*71d10453SEric Joyner if (status) 703*71d10453SEric Joyner goto err_unroll_sched; 704*71d10453SEric Joyner 705*71d10453SEric Joyner pcaps = (struct ice_aqc_get_phy_caps_data *) 706*71d10453SEric Joyner ice_malloc(hw, sizeof(*pcaps)); 707*71d10453SEric Joyner if (!pcaps) { 708*71d10453SEric Joyner status = ICE_ERR_NO_MEMORY; 709*71d10453SEric Joyner goto err_unroll_sched; 710*71d10453SEric Joyner } 711*71d10453SEric Joyner 712*71d10453SEric Joyner /* Initialize port_info struct with PHY capabilities */ 713*71d10453SEric Joyner status = ice_aq_get_phy_caps(hw->port_info, false, 714*71d10453SEric Joyner ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL); 715*71d10453SEric Joyner ice_free(hw, pcaps); 716*71d10453SEric Joyner if (status) 717*71d10453SEric Joyner goto err_unroll_sched; 718*71d10453SEric Joyner 719*71d10453SEric Joyner /* Initialize port_info struct with link information */ 720*71d10453SEric Joyner status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL); 721*71d10453SEric Joyner if (status) 722*71d10453SEric Joyner goto err_unroll_sched; 723*71d10453SEric Joyner /* need a valid SW entry point to build a Tx tree */ 724*71d10453SEric Joyner if (!hw->sw_entry_point_layer) { 725*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n"); 726*71d10453SEric Joyner status = ICE_ERR_CFG; 727*71d10453SEric Joyner goto err_unroll_sched; 728*71d10453SEric Joyner } 729*71d10453SEric Joyner INIT_LIST_HEAD(&hw->agg_list); 730*71d10453SEric Joyner /* Initialize max burst size */ 731*71d10453SEric Joyner if (!hw->max_burst_size) 732*71d10453SEric Joyner ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE); 733*71d10453SEric Joyner 734*71d10453SEric Joyner status = ice_init_fltr_mgmt_struct(hw); 735*71d10453SEric Joyner if (status) 736*71d10453SEric Joyner goto err_unroll_sched; 737*71d10453SEric Joyner 738*71d10453SEric Joyner /* Get MAC information */ 739*71d10453SEric Joyner /* A single port can report up to two (LAN and WoL) addresses */ 740*71d10453SEric Joyner mac_buf = ice_calloc(hw, 2, 741*71d10453SEric Joyner sizeof(struct ice_aqc_manage_mac_read_resp)); 742*71d10453SEric Joyner mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp); 743*71d10453SEric Joyner 744*71d10453SEric Joyner if (!mac_buf) { 745*71d10453SEric Joyner status = ICE_ERR_NO_MEMORY; 746*71d10453SEric Joyner goto err_unroll_fltr_mgmt_struct; 747*71d10453SEric Joyner } 748*71d10453SEric Joyner 749*71d10453SEric Joyner status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL); 750*71d10453SEric Joyner ice_free(hw, mac_buf); 751*71d10453SEric Joyner 752*71d10453SEric Joyner if (status) 753*71d10453SEric Joyner goto err_unroll_fltr_mgmt_struct; 754*71d10453SEric Joyner status = ice_init_hw_tbls(hw); 755*71d10453SEric Joyner if (status) 756*71d10453SEric Joyner goto err_unroll_fltr_mgmt_struct; 757*71d10453SEric Joyner ice_init_lock(&hw->tnl_lock); 758*71d10453SEric Joyner return ICE_SUCCESS; 759*71d10453SEric Joyner 760*71d10453SEric Joyner err_unroll_fltr_mgmt_struct: 761*71d10453SEric Joyner ice_cleanup_fltr_mgmt_struct(hw); 762*71d10453SEric Joyner err_unroll_sched: 763*71d10453SEric Joyner ice_sched_cleanup_all(hw); 764*71d10453SEric Joyner err_unroll_alloc: 765*71d10453SEric Joyner ice_free(hw, hw->port_info); 766*71d10453SEric Joyner hw->port_info = NULL; 767*71d10453SEric Joyner err_unroll_cqinit: 768*71d10453SEric Joyner ice_destroy_all_ctrlq(hw); 769*71d10453SEric Joyner return status; 770*71d10453SEric Joyner } 771*71d10453SEric Joyner 772*71d10453SEric Joyner /** 773*71d10453SEric Joyner * ice_deinit_hw - unroll initialization operations done by ice_init_hw 774*71d10453SEric Joyner * @hw: pointer to the hardware structure 775*71d10453SEric Joyner * 776*71d10453SEric Joyner * This should be called only during nominal operation, not as a result of 777*71d10453SEric Joyner * ice_init_hw() failing since ice_init_hw() will take care of unrolling 778*71d10453SEric Joyner * applicable initializations if it fails for any reason. 779*71d10453SEric Joyner */ 780*71d10453SEric Joyner void ice_deinit_hw(struct ice_hw *hw) 781*71d10453SEric Joyner { 782*71d10453SEric Joyner ice_cleanup_fltr_mgmt_struct(hw); 783*71d10453SEric Joyner 784*71d10453SEric Joyner ice_sched_cleanup_all(hw); 785*71d10453SEric Joyner ice_sched_clear_agg(hw); 786*71d10453SEric Joyner ice_free_seg(hw); 787*71d10453SEric Joyner ice_free_hw_tbls(hw); 788*71d10453SEric Joyner ice_destroy_lock(&hw->tnl_lock); 789*71d10453SEric Joyner 790*71d10453SEric Joyner if (hw->port_info) { 791*71d10453SEric Joyner ice_free(hw, hw->port_info); 792*71d10453SEric Joyner hw->port_info = NULL; 793*71d10453SEric Joyner } 794*71d10453SEric Joyner 795*71d10453SEric Joyner ice_destroy_all_ctrlq(hw); 796*71d10453SEric Joyner 797*71d10453SEric Joyner /* Clear VSI contexts if not already cleared */ 798*71d10453SEric Joyner ice_clear_all_vsi_ctx(hw); 799*71d10453SEric Joyner } 800*71d10453SEric Joyner 801*71d10453SEric Joyner /** 802*71d10453SEric Joyner * ice_check_reset - Check to see if a global reset is complete 803*71d10453SEric Joyner * @hw: pointer to the hardware structure 804*71d10453SEric Joyner */ 805*71d10453SEric Joyner enum ice_status ice_check_reset(struct ice_hw *hw) 806*71d10453SEric Joyner { 807*71d10453SEric Joyner u32 cnt, reg = 0, grst_delay, uld_mask; 808*71d10453SEric Joyner 809*71d10453SEric Joyner /* Poll for Device Active state in case a recent CORER, GLOBR, 810*71d10453SEric Joyner * or EMPR has occurred. The grst delay value is in 100ms units. 811*71d10453SEric Joyner * Add 1sec for outstanding AQ commands that can take a long time. 812*71d10453SEric Joyner */ 813*71d10453SEric Joyner grst_delay = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >> 814*71d10453SEric Joyner GLGEN_RSTCTL_GRSTDEL_S) + 10; 815*71d10453SEric Joyner 816*71d10453SEric Joyner for (cnt = 0; cnt < grst_delay; cnt++) { 817*71d10453SEric Joyner ice_msec_delay(100, true); 818*71d10453SEric Joyner reg = rd32(hw, GLGEN_RSTAT); 819*71d10453SEric Joyner if (!(reg & GLGEN_RSTAT_DEVSTATE_M)) 820*71d10453SEric Joyner break; 821*71d10453SEric Joyner } 822*71d10453SEric Joyner 823*71d10453SEric Joyner if (cnt == grst_delay) { 824*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 825*71d10453SEric Joyner "Global reset polling failed to complete.\n"); 826*71d10453SEric Joyner return ICE_ERR_RESET_FAILED; 827*71d10453SEric Joyner } 828*71d10453SEric Joyner 829*71d10453SEric Joyner #define ICE_RESET_DONE_MASK (GLNVM_ULD_PCIER_DONE_M |\ 830*71d10453SEric Joyner GLNVM_ULD_PCIER_DONE_1_M |\ 831*71d10453SEric Joyner GLNVM_ULD_CORER_DONE_M |\ 832*71d10453SEric Joyner GLNVM_ULD_GLOBR_DONE_M |\ 833*71d10453SEric Joyner GLNVM_ULD_POR_DONE_M |\ 834*71d10453SEric Joyner GLNVM_ULD_POR_DONE_1_M |\ 835*71d10453SEric Joyner GLNVM_ULD_PCIER_DONE_2_M) 836*71d10453SEric Joyner 837*71d10453SEric Joyner uld_mask = ICE_RESET_DONE_MASK; 838*71d10453SEric Joyner 839*71d10453SEric Joyner /* Device is Active; check Global Reset processes are done */ 840*71d10453SEric Joyner for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 841*71d10453SEric Joyner reg = rd32(hw, GLNVM_ULD) & uld_mask; 842*71d10453SEric Joyner if (reg == uld_mask) { 843*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 844*71d10453SEric Joyner "Global reset processes done. %d\n", cnt); 845*71d10453SEric Joyner break; 846*71d10453SEric Joyner } 847*71d10453SEric Joyner ice_msec_delay(10, true); 848*71d10453SEric Joyner } 849*71d10453SEric Joyner 850*71d10453SEric Joyner if (cnt == ICE_PF_RESET_WAIT_COUNT) { 851*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 852*71d10453SEric Joyner "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n", 853*71d10453SEric Joyner reg); 854*71d10453SEric Joyner return ICE_ERR_RESET_FAILED; 855*71d10453SEric Joyner } 856*71d10453SEric Joyner 857*71d10453SEric Joyner return ICE_SUCCESS; 858*71d10453SEric Joyner } 859*71d10453SEric Joyner 860*71d10453SEric Joyner /** 861*71d10453SEric Joyner * ice_pf_reset - Reset the PF 862*71d10453SEric Joyner * @hw: pointer to the hardware structure 863*71d10453SEric Joyner * 864*71d10453SEric Joyner * If a global reset has been triggered, this function checks 865*71d10453SEric Joyner * for its completion and then issues the PF reset 866*71d10453SEric Joyner */ 867*71d10453SEric Joyner static enum ice_status ice_pf_reset(struct ice_hw *hw) 868*71d10453SEric Joyner { 869*71d10453SEric Joyner u32 cnt, reg; 870*71d10453SEric Joyner 871*71d10453SEric Joyner /* If at function entry a global reset was already in progress, i.e. 872*71d10453SEric Joyner * state is not 'device active' or any of the reset done bits are not 873*71d10453SEric Joyner * set in GLNVM_ULD, there is no need for a PF Reset; poll until the 874*71d10453SEric Joyner * global reset is done. 875*71d10453SEric Joyner */ 876*71d10453SEric Joyner if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) || 877*71d10453SEric Joyner (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) { 878*71d10453SEric Joyner /* poll on global reset currently in progress until done */ 879*71d10453SEric Joyner if (ice_check_reset(hw)) 880*71d10453SEric Joyner return ICE_ERR_RESET_FAILED; 881*71d10453SEric Joyner 882*71d10453SEric Joyner return ICE_SUCCESS; 883*71d10453SEric Joyner } 884*71d10453SEric Joyner 885*71d10453SEric Joyner /* Reset the PF */ 886*71d10453SEric Joyner reg = rd32(hw, PFGEN_CTRL); 887*71d10453SEric Joyner 888*71d10453SEric Joyner wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M)); 889*71d10453SEric Joyner 890*71d10453SEric Joyner for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) { 891*71d10453SEric Joyner reg = rd32(hw, PFGEN_CTRL); 892*71d10453SEric Joyner if (!(reg & PFGEN_CTRL_PFSWR_M)) 893*71d10453SEric Joyner break; 894*71d10453SEric Joyner 895*71d10453SEric Joyner ice_msec_delay(1, true); 896*71d10453SEric Joyner } 897*71d10453SEric Joyner 898*71d10453SEric Joyner if (cnt == ICE_PF_RESET_WAIT_COUNT) { 899*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 900*71d10453SEric Joyner "PF reset polling failed to complete.\n"); 901*71d10453SEric Joyner return ICE_ERR_RESET_FAILED; 902*71d10453SEric Joyner } 903*71d10453SEric Joyner 904*71d10453SEric Joyner return ICE_SUCCESS; 905*71d10453SEric Joyner } 906*71d10453SEric Joyner 907*71d10453SEric Joyner /** 908*71d10453SEric Joyner * ice_reset - Perform different types of reset 909*71d10453SEric Joyner * @hw: pointer to the hardware structure 910*71d10453SEric Joyner * @req: reset request 911*71d10453SEric Joyner * 912*71d10453SEric Joyner * This function triggers a reset as specified by the req parameter. 913*71d10453SEric Joyner * 914*71d10453SEric Joyner * Note: 915*71d10453SEric Joyner * If anything other than a PF reset is triggered, PXE mode is restored. 916*71d10453SEric Joyner * This has to be cleared using ice_clear_pxe_mode again, once the AQ 917*71d10453SEric Joyner * interface has been restored in the rebuild flow. 918*71d10453SEric Joyner */ 919*71d10453SEric Joyner enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req) 920*71d10453SEric Joyner { 921*71d10453SEric Joyner u32 val = 0; 922*71d10453SEric Joyner 923*71d10453SEric Joyner switch (req) { 924*71d10453SEric Joyner case ICE_RESET_PFR: 925*71d10453SEric Joyner return ice_pf_reset(hw); 926*71d10453SEric Joyner case ICE_RESET_CORER: 927*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n"); 928*71d10453SEric Joyner val = GLGEN_RTRIG_CORER_M; 929*71d10453SEric Joyner break; 930*71d10453SEric Joyner case ICE_RESET_GLOBR: 931*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n"); 932*71d10453SEric Joyner val = GLGEN_RTRIG_GLOBR_M; 933*71d10453SEric Joyner break; 934*71d10453SEric Joyner default: 935*71d10453SEric Joyner return ICE_ERR_PARAM; 936*71d10453SEric Joyner } 937*71d10453SEric Joyner 938*71d10453SEric Joyner val |= rd32(hw, GLGEN_RTRIG); 939*71d10453SEric Joyner wr32(hw, GLGEN_RTRIG, val); 940*71d10453SEric Joyner ice_flush(hw); 941*71d10453SEric Joyner 942*71d10453SEric Joyner /* wait for the FW to be ready */ 943*71d10453SEric Joyner return ice_check_reset(hw); 944*71d10453SEric Joyner } 945*71d10453SEric Joyner 946*71d10453SEric Joyner /** 947*71d10453SEric Joyner * ice_copy_rxq_ctx_to_hw 948*71d10453SEric Joyner * @hw: pointer to the hardware structure 949*71d10453SEric Joyner * @ice_rxq_ctx: pointer to the rxq context 950*71d10453SEric Joyner * @rxq_index: the index of the Rx queue 951*71d10453SEric Joyner * 952*71d10453SEric Joyner * Copies rxq context from dense structure to HW register space 953*71d10453SEric Joyner */ 954*71d10453SEric Joyner static enum ice_status 955*71d10453SEric Joyner ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index) 956*71d10453SEric Joyner { 957*71d10453SEric Joyner u8 i; 958*71d10453SEric Joyner 959*71d10453SEric Joyner if (!ice_rxq_ctx) 960*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 961*71d10453SEric Joyner 962*71d10453SEric Joyner if (rxq_index > QRX_CTRL_MAX_INDEX) 963*71d10453SEric Joyner return ICE_ERR_PARAM; 964*71d10453SEric Joyner 965*71d10453SEric Joyner /* Copy each dword separately to HW */ 966*71d10453SEric Joyner for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) { 967*71d10453SEric Joyner wr32(hw, QRX_CONTEXT(i, rxq_index), 968*71d10453SEric Joyner *((u32 *)(ice_rxq_ctx + (i * sizeof(u32))))); 969*71d10453SEric Joyner 970*71d10453SEric Joyner ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, 971*71d10453SEric Joyner *((u32 *)(ice_rxq_ctx + (i * sizeof(u32))))); 972*71d10453SEric Joyner } 973*71d10453SEric Joyner 974*71d10453SEric Joyner return ICE_SUCCESS; 975*71d10453SEric Joyner } 976*71d10453SEric Joyner 977*71d10453SEric Joyner /* LAN Rx Queue Context */ 978*71d10453SEric Joyner static const struct ice_ctx_ele ice_rlan_ctx_info[] = { 979*71d10453SEric Joyner /* Field Width LSB */ 980*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, head, 13, 0), 981*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, cpuid, 8, 13), 982*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, base, 57, 32), 983*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, qlen, 13, 89), 984*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, dbuf, 7, 102), 985*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, hbuf, 5, 109), 986*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, dtype, 2, 114), 987*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, dsize, 1, 116), 988*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, crcstrip, 1, 117), 989*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, l2tsel, 1, 119), 990*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, hsplit_0, 4, 120), 991*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, hsplit_1, 2, 124), 992*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, showiv, 1, 127), 993*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, rxmax, 14, 174), 994*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena, 1, 193), 995*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena, 1, 194), 996*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena, 1, 195), 997*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena, 1, 196), 998*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh, 3, 198), 999*71d10453SEric Joyner ICE_CTX_STORE(ice_rlan_ctx, prefena, 1, 201), 1000*71d10453SEric Joyner { 0 } 1001*71d10453SEric Joyner }; 1002*71d10453SEric Joyner 1003*71d10453SEric Joyner /** 1004*71d10453SEric Joyner * ice_write_rxq_ctx 1005*71d10453SEric Joyner * @hw: pointer to the hardware structure 1006*71d10453SEric Joyner * @rlan_ctx: pointer to the rxq context 1007*71d10453SEric Joyner * @rxq_index: the index of the Rx queue 1008*71d10453SEric Joyner * 1009*71d10453SEric Joyner * Converts rxq context from sparse to dense structure and then writes 1010*71d10453SEric Joyner * it to HW register space and enables the hardware to prefetch descriptors 1011*71d10453SEric Joyner * instead of only fetching them on demand 1012*71d10453SEric Joyner */ 1013*71d10453SEric Joyner enum ice_status 1014*71d10453SEric Joyner ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, 1015*71d10453SEric Joyner u32 rxq_index) 1016*71d10453SEric Joyner { 1017*71d10453SEric Joyner u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 }; 1018*71d10453SEric Joyner 1019*71d10453SEric Joyner if (!rlan_ctx) 1020*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 1021*71d10453SEric Joyner 1022*71d10453SEric Joyner rlan_ctx->prefena = 1; 1023*71d10453SEric Joyner 1024*71d10453SEric Joyner ice_set_ctx((u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info); 1025*71d10453SEric Joyner return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index); 1026*71d10453SEric Joyner } 1027*71d10453SEric Joyner 1028*71d10453SEric Joyner /** 1029*71d10453SEric Joyner * ice_clear_rxq_ctx 1030*71d10453SEric Joyner * @hw: pointer to the hardware structure 1031*71d10453SEric Joyner * @rxq_index: the index of the Rx queue to clear 1032*71d10453SEric Joyner * 1033*71d10453SEric Joyner * Clears rxq context in HW register space 1034*71d10453SEric Joyner */ 1035*71d10453SEric Joyner enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index) 1036*71d10453SEric Joyner { 1037*71d10453SEric Joyner u8 i; 1038*71d10453SEric Joyner 1039*71d10453SEric Joyner if (rxq_index > QRX_CTRL_MAX_INDEX) 1040*71d10453SEric Joyner return ICE_ERR_PARAM; 1041*71d10453SEric Joyner 1042*71d10453SEric Joyner /* Clear each dword register separately */ 1043*71d10453SEric Joyner for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) 1044*71d10453SEric Joyner wr32(hw, QRX_CONTEXT(i, rxq_index), 0); 1045*71d10453SEric Joyner 1046*71d10453SEric Joyner return ICE_SUCCESS; 1047*71d10453SEric Joyner } 1048*71d10453SEric Joyner 1049*71d10453SEric Joyner /* LAN Tx Queue Context */ 1050*71d10453SEric Joyner const struct ice_ctx_ele ice_tlan_ctx_info[] = { 1051*71d10453SEric Joyner /* Field Width LSB */ 1052*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, base, 57, 0), 1053*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, port_num, 3, 57), 1054*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, cgd_num, 5, 60), 1055*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, pf_num, 3, 65), 1056*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, vmvf_num, 10, 68), 1057*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, vmvf_type, 2, 78), 1058*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, src_vsi, 10, 80), 1059*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena, 1, 90), 1060*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag, 1, 91), 1061*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, alt_vlan, 1, 92), 1062*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, cpuid, 8, 93), 1063*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, wb_mode, 1, 101), 1064*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc, 1, 102), 1065*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, tphrd, 1, 103), 1066*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc, 1, 104), 1067*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, cmpq_id, 9, 105), 1068*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func, 14, 114), 1069*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode, 1, 128), 1070*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id, 6, 129), 1071*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, qlen, 13, 135), 1072*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx, 4, 148), 1073*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, tso_ena, 1, 152), 1074*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, tso_qnum, 11, 153), 1075*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, legacy_int, 1, 164), 1076*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, drop_ena, 1, 165), 1077*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx, 2, 166), 1078*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx, 3, 168), 1079*71d10453SEric Joyner ICE_CTX_STORE(ice_tlan_ctx, int_q_state, 122, 171), 1080*71d10453SEric Joyner { 0 } 1081*71d10453SEric Joyner }; 1082*71d10453SEric Joyner 1083*71d10453SEric Joyner /** 1084*71d10453SEric Joyner * ice_copy_tx_cmpltnq_ctx_to_hw 1085*71d10453SEric Joyner * @hw: pointer to the hardware structure 1086*71d10453SEric Joyner * @ice_tx_cmpltnq_ctx: pointer to the Tx completion queue context 1087*71d10453SEric Joyner * @tx_cmpltnq_index: the index of the completion queue 1088*71d10453SEric Joyner * 1089*71d10453SEric Joyner * Copies Tx completion queue context from dense structure to HW register space 1090*71d10453SEric Joyner */ 1091*71d10453SEric Joyner static enum ice_status 1092*71d10453SEric Joyner ice_copy_tx_cmpltnq_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_cmpltnq_ctx, 1093*71d10453SEric Joyner u32 tx_cmpltnq_index) 1094*71d10453SEric Joyner { 1095*71d10453SEric Joyner u8 i; 1096*71d10453SEric Joyner 1097*71d10453SEric Joyner if (!ice_tx_cmpltnq_ctx) 1098*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 1099*71d10453SEric Joyner 1100*71d10453SEric Joyner if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX) 1101*71d10453SEric Joyner return ICE_ERR_PARAM; 1102*71d10453SEric Joyner 1103*71d10453SEric Joyner /* Copy each dword separately to HW */ 1104*71d10453SEric Joyner for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++) { 1105*71d10453SEric Joyner wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index), 1106*71d10453SEric Joyner *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32))))); 1107*71d10453SEric Joyner 1108*71d10453SEric Joyner ice_debug(hw, ICE_DBG_QCTX, "cmpltnqdata[%d]: %08X\n", i, 1109*71d10453SEric Joyner *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32))))); 1110*71d10453SEric Joyner } 1111*71d10453SEric Joyner 1112*71d10453SEric Joyner return ICE_SUCCESS; 1113*71d10453SEric Joyner } 1114*71d10453SEric Joyner 1115*71d10453SEric Joyner /* LAN Tx Completion Queue Context */ 1116*71d10453SEric Joyner static const struct ice_ctx_ele ice_tx_cmpltnq_ctx_info[] = { 1117*71d10453SEric Joyner /* Field Width LSB */ 1118*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, base, 57, 0), 1119*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, q_len, 18, 64), 1120*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, generation, 1, 96), 1121*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, wrt_ptr, 22, 97), 1122*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, pf_num, 3, 128), 1123*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_num, 10, 131), 1124*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_type, 2, 141), 1125*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, tph_desc_wr, 1, 160), 1126*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cpuid, 8, 161), 1127*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cmpltn_cache, 512, 192), 1128*71d10453SEric Joyner { 0 } 1129*71d10453SEric Joyner }; 1130*71d10453SEric Joyner 1131*71d10453SEric Joyner /** 1132*71d10453SEric Joyner * ice_write_tx_cmpltnq_ctx 1133*71d10453SEric Joyner * @hw: pointer to the hardware structure 1134*71d10453SEric Joyner * @tx_cmpltnq_ctx: pointer to the completion queue context 1135*71d10453SEric Joyner * @tx_cmpltnq_index: the index of the completion queue 1136*71d10453SEric Joyner * 1137*71d10453SEric Joyner * Converts completion queue context from sparse to dense structure and then 1138*71d10453SEric Joyner * writes it to HW register space 1139*71d10453SEric Joyner */ 1140*71d10453SEric Joyner enum ice_status 1141*71d10453SEric Joyner ice_write_tx_cmpltnq_ctx(struct ice_hw *hw, 1142*71d10453SEric Joyner struct ice_tx_cmpltnq_ctx *tx_cmpltnq_ctx, 1143*71d10453SEric Joyner u32 tx_cmpltnq_index) 1144*71d10453SEric Joyner { 1145*71d10453SEric Joyner u8 ctx_buf[ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 }; 1146*71d10453SEric Joyner 1147*71d10453SEric Joyner ice_set_ctx((u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info); 1148*71d10453SEric Joyner return ice_copy_tx_cmpltnq_ctx_to_hw(hw, ctx_buf, tx_cmpltnq_index); 1149*71d10453SEric Joyner } 1150*71d10453SEric Joyner 1151*71d10453SEric Joyner /** 1152*71d10453SEric Joyner * ice_clear_tx_cmpltnq_ctx 1153*71d10453SEric Joyner * @hw: pointer to the hardware structure 1154*71d10453SEric Joyner * @tx_cmpltnq_index: the index of the completion queue to clear 1155*71d10453SEric Joyner * 1156*71d10453SEric Joyner * Clears Tx completion queue context in HW register space 1157*71d10453SEric Joyner */ 1158*71d10453SEric Joyner enum ice_status 1159*71d10453SEric Joyner ice_clear_tx_cmpltnq_ctx(struct ice_hw *hw, u32 tx_cmpltnq_index) 1160*71d10453SEric Joyner { 1161*71d10453SEric Joyner u8 i; 1162*71d10453SEric Joyner 1163*71d10453SEric Joyner if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX) 1164*71d10453SEric Joyner return ICE_ERR_PARAM; 1165*71d10453SEric Joyner 1166*71d10453SEric Joyner /* Clear each dword register separately */ 1167*71d10453SEric Joyner for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++) 1168*71d10453SEric Joyner wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index), 0); 1169*71d10453SEric Joyner 1170*71d10453SEric Joyner return ICE_SUCCESS; 1171*71d10453SEric Joyner } 1172*71d10453SEric Joyner 1173*71d10453SEric Joyner /** 1174*71d10453SEric Joyner * ice_copy_tx_drbell_q_ctx_to_hw 1175*71d10453SEric Joyner * @hw: pointer to the hardware structure 1176*71d10453SEric Joyner * @ice_tx_drbell_q_ctx: pointer to the doorbell queue context 1177*71d10453SEric Joyner * @tx_drbell_q_index: the index of the doorbell queue 1178*71d10453SEric Joyner * 1179*71d10453SEric Joyner * Copies doorbell queue context from dense structure to HW register space 1180*71d10453SEric Joyner */ 1181*71d10453SEric Joyner static enum ice_status 1182*71d10453SEric Joyner ice_copy_tx_drbell_q_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_drbell_q_ctx, 1183*71d10453SEric Joyner u32 tx_drbell_q_index) 1184*71d10453SEric Joyner { 1185*71d10453SEric Joyner u8 i; 1186*71d10453SEric Joyner 1187*71d10453SEric Joyner if (!ice_tx_drbell_q_ctx) 1188*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 1189*71d10453SEric Joyner 1190*71d10453SEric Joyner if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX) 1191*71d10453SEric Joyner return ICE_ERR_PARAM; 1192*71d10453SEric Joyner 1193*71d10453SEric Joyner /* Copy each dword separately to HW */ 1194*71d10453SEric Joyner for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++) { 1195*71d10453SEric Joyner wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index), 1196*71d10453SEric Joyner *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32))))); 1197*71d10453SEric Joyner 1198*71d10453SEric Joyner ice_debug(hw, ICE_DBG_QCTX, "tx_drbell_qdata[%d]: %08X\n", i, 1199*71d10453SEric Joyner *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32))))); 1200*71d10453SEric Joyner } 1201*71d10453SEric Joyner 1202*71d10453SEric Joyner return ICE_SUCCESS; 1203*71d10453SEric Joyner } 1204*71d10453SEric Joyner 1205*71d10453SEric Joyner /* LAN Tx Doorbell Queue Context info */ 1206*71d10453SEric Joyner static const struct ice_ctx_ele ice_tx_drbell_q_ctx_info[] = { 1207*71d10453SEric Joyner /* Field Width LSB */ 1208*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, base, 57, 0), 1209*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, ring_len, 13, 64), 1210*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, pf_num, 3, 80), 1211*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, vf_num, 8, 84), 1212*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, vmvf_type, 2, 94), 1213*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, cpuid, 8, 96), 1214*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_rd, 1, 104), 1215*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_wr, 1, 108), 1216*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, db_q_en, 1, 112), 1217*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_head, 13, 128), 1218*71d10453SEric Joyner ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_tail, 13, 144), 1219*71d10453SEric Joyner { 0 } 1220*71d10453SEric Joyner }; 1221*71d10453SEric Joyner 1222*71d10453SEric Joyner /** 1223*71d10453SEric Joyner * ice_write_tx_drbell_q_ctx 1224*71d10453SEric Joyner * @hw: pointer to the hardware structure 1225*71d10453SEric Joyner * @tx_drbell_q_ctx: pointer to the doorbell queue context 1226*71d10453SEric Joyner * @tx_drbell_q_index: the index of the doorbell queue 1227*71d10453SEric Joyner * 1228*71d10453SEric Joyner * Converts doorbell queue context from sparse to dense structure and then 1229*71d10453SEric Joyner * writes it to HW register space 1230*71d10453SEric Joyner */ 1231*71d10453SEric Joyner enum ice_status 1232*71d10453SEric Joyner ice_write_tx_drbell_q_ctx(struct ice_hw *hw, 1233*71d10453SEric Joyner struct ice_tx_drbell_q_ctx *tx_drbell_q_ctx, 1234*71d10453SEric Joyner u32 tx_drbell_q_index) 1235*71d10453SEric Joyner { 1236*71d10453SEric Joyner u8 ctx_buf[ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 }; 1237*71d10453SEric Joyner 1238*71d10453SEric Joyner ice_set_ctx((u8 *)tx_drbell_q_ctx, ctx_buf, ice_tx_drbell_q_ctx_info); 1239*71d10453SEric Joyner return ice_copy_tx_drbell_q_ctx_to_hw(hw, ctx_buf, tx_drbell_q_index); 1240*71d10453SEric Joyner } 1241*71d10453SEric Joyner 1242*71d10453SEric Joyner /** 1243*71d10453SEric Joyner * ice_clear_tx_drbell_q_ctx 1244*71d10453SEric Joyner * @hw: pointer to the hardware structure 1245*71d10453SEric Joyner * @tx_drbell_q_index: the index of the doorbell queue to clear 1246*71d10453SEric Joyner * 1247*71d10453SEric Joyner * Clears doorbell queue context in HW register space 1248*71d10453SEric Joyner */ 1249*71d10453SEric Joyner enum ice_status 1250*71d10453SEric Joyner ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index) 1251*71d10453SEric Joyner { 1252*71d10453SEric Joyner u8 i; 1253*71d10453SEric Joyner 1254*71d10453SEric Joyner if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX) 1255*71d10453SEric Joyner return ICE_ERR_PARAM; 1256*71d10453SEric Joyner 1257*71d10453SEric Joyner /* Clear each dword register separately */ 1258*71d10453SEric Joyner for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++) 1259*71d10453SEric Joyner wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index), 0); 1260*71d10453SEric Joyner 1261*71d10453SEric Joyner return ICE_SUCCESS; 1262*71d10453SEric Joyner } 1263*71d10453SEric Joyner 1264*71d10453SEric Joyner /* FW Admin Queue command wrappers */ 1265*71d10453SEric Joyner 1266*71d10453SEric Joyner /** 1267*71d10453SEric Joyner * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue 1268*71d10453SEric Joyner * @hw: pointer to the HW struct 1269*71d10453SEric Joyner * @desc: descriptor describing the command 1270*71d10453SEric Joyner * @buf: buffer to use for indirect commands (NULL for direct commands) 1271*71d10453SEric Joyner * @buf_size: size of buffer for indirect commands (0 for direct commands) 1272*71d10453SEric Joyner * @cd: pointer to command details structure 1273*71d10453SEric Joyner * 1274*71d10453SEric Joyner * Helper function to send FW Admin Queue commands to the FW Admin Queue. 1275*71d10453SEric Joyner */ 1276*71d10453SEric Joyner enum ice_status 1277*71d10453SEric Joyner ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf, 1278*71d10453SEric Joyner u16 buf_size, struct ice_sq_cd *cd) 1279*71d10453SEric Joyner { 1280*71d10453SEric Joyner return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd); 1281*71d10453SEric Joyner } 1282*71d10453SEric Joyner 1283*71d10453SEric Joyner /** 1284*71d10453SEric Joyner * ice_aq_get_fw_ver 1285*71d10453SEric Joyner * @hw: pointer to the HW struct 1286*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 1287*71d10453SEric Joyner * 1288*71d10453SEric Joyner * Get the firmware version (0x0001) from the admin queue commands 1289*71d10453SEric Joyner */ 1290*71d10453SEric Joyner enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd) 1291*71d10453SEric Joyner { 1292*71d10453SEric Joyner struct ice_aqc_get_ver *resp; 1293*71d10453SEric Joyner struct ice_aq_desc desc; 1294*71d10453SEric Joyner enum ice_status status; 1295*71d10453SEric Joyner 1296*71d10453SEric Joyner resp = &desc.params.get_ver; 1297*71d10453SEric Joyner 1298*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver); 1299*71d10453SEric Joyner 1300*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1301*71d10453SEric Joyner 1302*71d10453SEric Joyner if (!status) { 1303*71d10453SEric Joyner hw->fw_branch = resp->fw_branch; 1304*71d10453SEric Joyner hw->fw_maj_ver = resp->fw_major; 1305*71d10453SEric Joyner hw->fw_min_ver = resp->fw_minor; 1306*71d10453SEric Joyner hw->fw_patch = resp->fw_patch; 1307*71d10453SEric Joyner hw->fw_build = LE32_TO_CPU(resp->fw_build); 1308*71d10453SEric Joyner hw->api_branch = resp->api_branch; 1309*71d10453SEric Joyner hw->api_maj_ver = resp->api_major; 1310*71d10453SEric Joyner hw->api_min_ver = resp->api_minor; 1311*71d10453SEric Joyner hw->api_patch = resp->api_patch; 1312*71d10453SEric Joyner } 1313*71d10453SEric Joyner 1314*71d10453SEric Joyner return status; 1315*71d10453SEric Joyner } 1316*71d10453SEric Joyner 1317*71d10453SEric Joyner /** 1318*71d10453SEric Joyner * ice_aq_send_driver_ver 1319*71d10453SEric Joyner * @hw: pointer to the HW struct 1320*71d10453SEric Joyner * @dv: driver's major, minor version 1321*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 1322*71d10453SEric Joyner * 1323*71d10453SEric Joyner * Send the driver version (0x0002) to the firmware 1324*71d10453SEric Joyner */ 1325*71d10453SEric Joyner enum ice_status 1326*71d10453SEric Joyner ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv, 1327*71d10453SEric Joyner struct ice_sq_cd *cd) 1328*71d10453SEric Joyner { 1329*71d10453SEric Joyner struct ice_aqc_driver_ver *cmd; 1330*71d10453SEric Joyner struct ice_aq_desc desc; 1331*71d10453SEric Joyner u16 len; 1332*71d10453SEric Joyner 1333*71d10453SEric Joyner cmd = &desc.params.driver_ver; 1334*71d10453SEric Joyner 1335*71d10453SEric Joyner if (!dv) 1336*71d10453SEric Joyner return ICE_ERR_PARAM; 1337*71d10453SEric Joyner 1338*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver); 1339*71d10453SEric Joyner 1340*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1341*71d10453SEric Joyner cmd->major_ver = dv->major_ver; 1342*71d10453SEric Joyner cmd->minor_ver = dv->minor_ver; 1343*71d10453SEric Joyner cmd->build_ver = dv->build_ver; 1344*71d10453SEric Joyner cmd->subbuild_ver = dv->subbuild_ver; 1345*71d10453SEric Joyner 1346*71d10453SEric Joyner len = 0; 1347*71d10453SEric Joyner while (len < sizeof(dv->driver_string) && 1348*71d10453SEric Joyner IS_ASCII(dv->driver_string[len]) && dv->driver_string[len]) 1349*71d10453SEric Joyner len++; 1350*71d10453SEric Joyner 1351*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd); 1352*71d10453SEric Joyner } 1353*71d10453SEric Joyner 1354*71d10453SEric Joyner /** 1355*71d10453SEric Joyner * ice_aq_q_shutdown 1356*71d10453SEric Joyner * @hw: pointer to the HW struct 1357*71d10453SEric Joyner * @unloading: is the driver unloading itself 1358*71d10453SEric Joyner * 1359*71d10453SEric Joyner * Tell the Firmware that we're shutting down the AdminQ and whether 1360*71d10453SEric Joyner * or not the driver is unloading as well (0x0003). 1361*71d10453SEric Joyner */ 1362*71d10453SEric Joyner enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading) 1363*71d10453SEric Joyner { 1364*71d10453SEric Joyner struct ice_aqc_q_shutdown *cmd; 1365*71d10453SEric Joyner struct ice_aq_desc desc; 1366*71d10453SEric Joyner 1367*71d10453SEric Joyner cmd = &desc.params.q_shutdown; 1368*71d10453SEric Joyner 1369*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown); 1370*71d10453SEric Joyner 1371*71d10453SEric Joyner if (unloading) 1372*71d10453SEric Joyner cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING; 1373*71d10453SEric Joyner 1374*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 1375*71d10453SEric Joyner } 1376*71d10453SEric Joyner 1377*71d10453SEric Joyner /** 1378*71d10453SEric Joyner * ice_aq_req_res 1379*71d10453SEric Joyner * @hw: pointer to the HW struct 1380*71d10453SEric Joyner * @res: resource ID 1381*71d10453SEric Joyner * @access: access type 1382*71d10453SEric Joyner * @sdp_number: resource number 1383*71d10453SEric Joyner * @timeout: the maximum time in ms that the driver may hold the resource 1384*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 1385*71d10453SEric Joyner * 1386*71d10453SEric Joyner * Requests common resource using the admin queue commands (0x0008). 1387*71d10453SEric Joyner * When attempting to acquire the Global Config Lock, the driver can 1388*71d10453SEric Joyner * learn of three states: 1389*71d10453SEric Joyner * 1) ICE_SUCCESS - acquired lock, and can perform download package 1390*71d10453SEric Joyner * 2) ICE_ERR_AQ_ERROR - did not get lock, driver should fail to load 1391*71d10453SEric Joyner * 3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has 1392*71d10453SEric Joyner * successfully downloaded the package; the driver does 1393*71d10453SEric Joyner * not have to download the package and can continue 1394*71d10453SEric Joyner * loading 1395*71d10453SEric Joyner * 1396*71d10453SEric Joyner * Note that if the caller is in an acquire lock, perform action, release lock 1397*71d10453SEric Joyner * phase of operation, it is possible that the FW may detect a timeout and issue 1398*71d10453SEric Joyner * a CORER. In this case, the driver will receive a CORER interrupt and will 1399*71d10453SEric Joyner * have to determine its cause. The calling thread that is handling this flow 1400*71d10453SEric Joyner * will likely get an error propagated back to it indicating the Download 1401*71d10453SEric Joyner * Package, Update Package or the Release Resource AQ commands timed out. 1402*71d10453SEric Joyner */ 1403*71d10453SEric Joyner static enum ice_status 1404*71d10453SEric Joyner ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res, 1405*71d10453SEric Joyner enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout, 1406*71d10453SEric Joyner struct ice_sq_cd *cd) 1407*71d10453SEric Joyner { 1408*71d10453SEric Joyner struct ice_aqc_req_res *cmd_resp; 1409*71d10453SEric Joyner struct ice_aq_desc desc; 1410*71d10453SEric Joyner enum ice_status status; 1411*71d10453SEric Joyner 1412*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1413*71d10453SEric Joyner 1414*71d10453SEric Joyner cmd_resp = &desc.params.res_owner; 1415*71d10453SEric Joyner 1416*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res); 1417*71d10453SEric Joyner 1418*71d10453SEric Joyner cmd_resp->res_id = CPU_TO_LE16(res); 1419*71d10453SEric Joyner cmd_resp->access_type = CPU_TO_LE16(access); 1420*71d10453SEric Joyner cmd_resp->res_number = CPU_TO_LE32(sdp_number); 1421*71d10453SEric Joyner cmd_resp->timeout = CPU_TO_LE32(*timeout); 1422*71d10453SEric Joyner *timeout = 0; 1423*71d10453SEric Joyner 1424*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1425*71d10453SEric Joyner 1426*71d10453SEric Joyner /* The completion specifies the maximum time in ms that the driver 1427*71d10453SEric Joyner * may hold the resource in the Timeout field. 1428*71d10453SEric Joyner */ 1429*71d10453SEric Joyner 1430*71d10453SEric Joyner /* Global config lock response utilizes an additional status field. 1431*71d10453SEric Joyner * 1432*71d10453SEric Joyner * If the Global config lock resource is held by some other driver, the 1433*71d10453SEric Joyner * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field 1434*71d10453SEric Joyner * and the timeout field indicates the maximum time the current owner 1435*71d10453SEric Joyner * of the resource has to free it. 1436*71d10453SEric Joyner */ 1437*71d10453SEric Joyner if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) { 1438*71d10453SEric Joyner if (LE16_TO_CPU(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) { 1439*71d10453SEric Joyner *timeout = LE32_TO_CPU(cmd_resp->timeout); 1440*71d10453SEric Joyner return ICE_SUCCESS; 1441*71d10453SEric Joyner } else if (LE16_TO_CPU(cmd_resp->status) == 1442*71d10453SEric Joyner ICE_AQ_RES_GLBL_IN_PROG) { 1443*71d10453SEric Joyner *timeout = LE32_TO_CPU(cmd_resp->timeout); 1444*71d10453SEric Joyner return ICE_ERR_AQ_ERROR; 1445*71d10453SEric Joyner } else if (LE16_TO_CPU(cmd_resp->status) == 1446*71d10453SEric Joyner ICE_AQ_RES_GLBL_DONE) { 1447*71d10453SEric Joyner return ICE_ERR_AQ_NO_WORK; 1448*71d10453SEric Joyner } 1449*71d10453SEric Joyner 1450*71d10453SEric Joyner /* invalid FW response, force a timeout immediately */ 1451*71d10453SEric Joyner *timeout = 0; 1452*71d10453SEric Joyner return ICE_ERR_AQ_ERROR; 1453*71d10453SEric Joyner } 1454*71d10453SEric Joyner 1455*71d10453SEric Joyner /* If the resource is held by some other driver, the command completes 1456*71d10453SEric Joyner * with a busy return value and the timeout field indicates the maximum 1457*71d10453SEric Joyner * time the current owner of the resource has to free it. 1458*71d10453SEric Joyner */ 1459*71d10453SEric Joyner if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) 1460*71d10453SEric Joyner *timeout = LE32_TO_CPU(cmd_resp->timeout); 1461*71d10453SEric Joyner 1462*71d10453SEric Joyner return status; 1463*71d10453SEric Joyner } 1464*71d10453SEric Joyner 1465*71d10453SEric Joyner /** 1466*71d10453SEric Joyner * ice_aq_release_res 1467*71d10453SEric Joyner * @hw: pointer to the HW struct 1468*71d10453SEric Joyner * @res: resource ID 1469*71d10453SEric Joyner * @sdp_number: resource number 1470*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 1471*71d10453SEric Joyner * 1472*71d10453SEric Joyner * release common resource using the admin queue commands (0x0009) 1473*71d10453SEric Joyner */ 1474*71d10453SEric Joyner static enum ice_status 1475*71d10453SEric Joyner ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number, 1476*71d10453SEric Joyner struct ice_sq_cd *cd) 1477*71d10453SEric Joyner { 1478*71d10453SEric Joyner struct ice_aqc_req_res *cmd; 1479*71d10453SEric Joyner struct ice_aq_desc desc; 1480*71d10453SEric Joyner 1481*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1482*71d10453SEric Joyner 1483*71d10453SEric Joyner cmd = &desc.params.res_owner; 1484*71d10453SEric Joyner 1485*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res); 1486*71d10453SEric Joyner 1487*71d10453SEric Joyner cmd->res_id = CPU_TO_LE16(res); 1488*71d10453SEric Joyner cmd->res_number = CPU_TO_LE32(sdp_number); 1489*71d10453SEric Joyner 1490*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1491*71d10453SEric Joyner } 1492*71d10453SEric Joyner 1493*71d10453SEric Joyner /** 1494*71d10453SEric Joyner * ice_acquire_res 1495*71d10453SEric Joyner * @hw: pointer to the HW structure 1496*71d10453SEric Joyner * @res: resource ID 1497*71d10453SEric Joyner * @access: access type (read or write) 1498*71d10453SEric Joyner * @timeout: timeout in milliseconds 1499*71d10453SEric Joyner * 1500*71d10453SEric Joyner * This function will attempt to acquire the ownership of a resource. 1501*71d10453SEric Joyner */ 1502*71d10453SEric Joyner enum ice_status 1503*71d10453SEric Joyner ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, 1504*71d10453SEric Joyner enum ice_aq_res_access_type access, u32 timeout) 1505*71d10453SEric Joyner { 1506*71d10453SEric Joyner #define ICE_RES_POLLING_DELAY_MS 10 1507*71d10453SEric Joyner u32 delay = ICE_RES_POLLING_DELAY_MS; 1508*71d10453SEric Joyner u32 time_left = timeout; 1509*71d10453SEric Joyner enum ice_status status; 1510*71d10453SEric Joyner 1511*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1512*71d10453SEric Joyner 1513*71d10453SEric Joyner status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 1514*71d10453SEric Joyner 1515*71d10453SEric Joyner /* A return code of ICE_ERR_AQ_NO_WORK means that another driver has 1516*71d10453SEric Joyner * previously acquired the resource and performed any necessary updates; 1517*71d10453SEric Joyner * in this case the caller does not obtain the resource and has no 1518*71d10453SEric Joyner * further work to do. 1519*71d10453SEric Joyner */ 1520*71d10453SEric Joyner if (status == ICE_ERR_AQ_NO_WORK) 1521*71d10453SEric Joyner goto ice_acquire_res_exit; 1522*71d10453SEric Joyner 1523*71d10453SEric Joyner if (status) 1524*71d10453SEric Joyner ice_debug(hw, ICE_DBG_RES, 1525*71d10453SEric Joyner "resource %d acquire type %d failed.\n", res, access); 1526*71d10453SEric Joyner 1527*71d10453SEric Joyner /* If necessary, poll until the current lock owner timeouts */ 1528*71d10453SEric Joyner timeout = time_left; 1529*71d10453SEric Joyner while (status && timeout && time_left) { 1530*71d10453SEric Joyner ice_msec_delay(delay, true); 1531*71d10453SEric Joyner timeout = (timeout > delay) ? timeout - delay : 0; 1532*71d10453SEric Joyner status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL); 1533*71d10453SEric Joyner 1534*71d10453SEric Joyner if (status == ICE_ERR_AQ_NO_WORK) 1535*71d10453SEric Joyner /* lock free, but no work to do */ 1536*71d10453SEric Joyner break; 1537*71d10453SEric Joyner 1538*71d10453SEric Joyner if (!status) 1539*71d10453SEric Joyner /* lock acquired */ 1540*71d10453SEric Joyner break; 1541*71d10453SEric Joyner } 1542*71d10453SEric Joyner if (status && status != ICE_ERR_AQ_NO_WORK) 1543*71d10453SEric Joyner ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n"); 1544*71d10453SEric Joyner 1545*71d10453SEric Joyner ice_acquire_res_exit: 1546*71d10453SEric Joyner if (status == ICE_ERR_AQ_NO_WORK) { 1547*71d10453SEric Joyner if (access == ICE_RES_WRITE) 1548*71d10453SEric Joyner ice_debug(hw, ICE_DBG_RES, 1549*71d10453SEric Joyner "resource indicates no work to do.\n"); 1550*71d10453SEric Joyner else 1551*71d10453SEric Joyner ice_debug(hw, ICE_DBG_RES, 1552*71d10453SEric Joyner "Warning: ICE_ERR_AQ_NO_WORK not expected\n"); 1553*71d10453SEric Joyner } 1554*71d10453SEric Joyner return status; 1555*71d10453SEric Joyner } 1556*71d10453SEric Joyner 1557*71d10453SEric Joyner /** 1558*71d10453SEric Joyner * ice_release_res 1559*71d10453SEric Joyner * @hw: pointer to the HW structure 1560*71d10453SEric Joyner * @res: resource ID 1561*71d10453SEric Joyner * 1562*71d10453SEric Joyner * This function will release a resource using the proper Admin Command. 1563*71d10453SEric Joyner */ 1564*71d10453SEric Joyner void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res) 1565*71d10453SEric Joyner { 1566*71d10453SEric Joyner enum ice_status status; 1567*71d10453SEric Joyner u32 total_delay = 0; 1568*71d10453SEric Joyner 1569*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1570*71d10453SEric Joyner 1571*71d10453SEric Joyner status = ice_aq_release_res(hw, res, 0, NULL); 1572*71d10453SEric Joyner 1573*71d10453SEric Joyner /* there are some rare cases when trying to release the resource 1574*71d10453SEric Joyner * results in an admin queue timeout, so handle them correctly 1575*71d10453SEric Joyner */ 1576*71d10453SEric Joyner while ((status == ICE_ERR_AQ_TIMEOUT) && 1577*71d10453SEric Joyner (total_delay < hw->adminq.sq_cmd_timeout)) { 1578*71d10453SEric Joyner ice_msec_delay(1, true); 1579*71d10453SEric Joyner status = ice_aq_release_res(hw, res, 0, NULL); 1580*71d10453SEric Joyner total_delay++; 1581*71d10453SEric Joyner } 1582*71d10453SEric Joyner } 1583*71d10453SEric Joyner 1584*71d10453SEric Joyner /** 1585*71d10453SEric Joyner * ice_aq_alloc_free_res - command to allocate/free resources 1586*71d10453SEric Joyner * @hw: pointer to the HW struct 1587*71d10453SEric Joyner * @num_entries: number of resource entries in buffer 1588*71d10453SEric Joyner * @buf: Indirect buffer to hold data parameters and response 1589*71d10453SEric Joyner * @buf_size: size of buffer for indirect commands 1590*71d10453SEric Joyner * @opc: pass in the command opcode 1591*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 1592*71d10453SEric Joyner * 1593*71d10453SEric Joyner * Helper function to allocate/free resources using the admin queue commands 1594*71d10453SEric Joyner */ 1595*71d10453SEric Joyner enum ice_status 1596*71d10453SEric Joyner ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, 1597*71d10453SEric Joyner struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, 1598*71d10453SEric Joyner enum ice_adminq_opc opc, struct ice_sq_cd *cd) 1599*71d10453SEric Joyner { 1600*71d10453SEric Joyner struct ice_aqc_alloc_free_res_cmd *cmd; 1601*71d10453SEric Joyner struct ice_aq_desc desc; 1602*71d10453SEric Joyner 1603*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1604*71d10453SEric Joyner 1605*71d10453SEric Joyner cmd = &desc.params.sw_res_ctrl; 1606*71d10453SEric Joyner 1607*71d10453SEric Joyner if (!buf) 1608*71d10453SEric Joyner return ICE_ERR_PARAM; 1609*71d10453SEric Joyner 1610*71d10453SEric Joyner if (buf_size < (num_entries * sizeof(buf->elem[0]))) 1611*71d10453SEric Joyner return ICE_ERR_PARAM; 1612*71d10453SEric Joyner 1613*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, opc); 1614*71d10453SEric Joyner 1615*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1616*71d10453SEric Joyner 1617*71d10453SEric Joyner cmd->num_entries = CPU_TO_LE16(num_entries); 1618*71d10453SEric Joyner 1619*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 1620*71d10453SEric Joyner } 1621*71d10453SEric Joyner 1622*71d10453SEric Joyner /** 1623*71d10453SEric Joyner * ice_alloc_hw_res - allocate resource 1624*71d10453SEric Joyner * @hw: pointer to the HW struct 1625*71d10453SEric Joyner * @type: type of resource 1626*71d10453SEric Joyner * @num: number of resources to allocate 1627*71d10453SEric Joyner * @btm: allocate from bottom 1628*71d10453SEric Joyner * @res: pointer to array that will receive the resources 1629*71d10453SEric Joyner */ 1630*71d10453SEric Joyner enum ice_status 1631*71d10453SEric Joyner ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res) 1632*71d10453SEric Joyner { 1633*71d10453SEric Joyner struct ice_aqc_alloc_free_res_elem *buf; 1634*71d10453SEric Joyner enum ice_status status; 1635*71d10453SEric Joyner u16 buf_len; 1636*71d10453SEric Joyner 1637*71d10453SEric Joyner buf_len = ice_struct_size(buf, elem, num - 1); 1638*71d10453SEric Joyner buf = (struct ice_aqc_alloc_free_res_elem *) 1639*71d10453SEric Joyner ice_malloc(hw, buf_len); 1640*71d10453SEric Joyner if (!buf) 1641*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 1642*71d10453SEric Joyner 1643*71d10453SEric Joyner /* Prepare buffer to allocate resource. */ 1644*71d10453SEric Joyner buf->num_elems = CPU_TO_LE16(num); 1645*71d10453SEric Joyner buf->res_type = CPU_TO_LE16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED | 1646*71d10453SEric Joyner ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX); 1647*71d10453SEric Joyner if (btm) 1648*71d10453SEric Joyner buf->res_type |= CPU_TO_LE16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM); 1649*71d10453SEric Joyner 1650*71d10453SEric Joyner status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 1651*71d10453SEric Joyner ice_aqc_opc_alloc_res, NULL); 1652*71d10453SEric Joyner if (status) 1653*71d10453SEric Joyner goto ice_alloc_res_exit; 1654*71d10453SEric Joyner 1655*71d10453SEric Joyner ice_memcpy(res, buf->elem, sizeof(buf->elem) * num, 1656*71d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 1657*71d10453SEric Joyner 1658*71d10453SEric Joyner ice_alloc_res_exit: 1659*71d10453SEric Joyner ice_free(hw, buf); 1660*71d10453SEric Joyner return status; 1661*71d10453SEric Joyner } 1662*71d10453SEric Joyner 1663*71d10453SEric Joyner /** 1664*71d10453SEric Joyner * ice_free_hw_res - free allocated HW resource 1665*71d10453SEric Joyner * @hw: pointer to the HW struct 1666*71d10453SEric Joyner * @type: type of resource to free 1667*71d10453SEric Joyner * @num: number of resources 1668*71d10453SEric Joyner * @res: pointer to array that contains the resources to free 1669*71d10453SEric Joyner */ 1670*71d10453SEric Joyner enum ice_status 1671*71d10453SEric Joyner ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res) 1672*71d10453SEric Joyner { 1673*71d10453SEric Joyner struct ice_aqc_alloc_free_res_elem *buf; 1674*71d10453SEric Joyner enum ice_status status; 1675*71d10453SEric Joyner u16 buf_len; 1676*71d10453SEric Joyner 1677*71d10453SEric Joyner buf_len = ice_struct_size(buf, elem, num - 1); 1678*71d10453SEric Joyner buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 1679*71d10453SEric Joyner if (!buf) 1680*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 1681*71d10453SEric Joyner 1682*71d10453SEric Joyner /* Prepare buffer to free resource. */ 1683*71d10453SEric Joyner buf->num_elems = CPU_TO_LE16(num); 1684*71d10453SEric Joyner buf->res_type = CPU_TO_LE16(type); 1685*71d10453SEric Joyner ice_memcpy(buf->elem, res, sizeof(buf->elem) * num, 1686*71d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 1687*71d10453SEric Joyner 1688*71d10453SEric Joyner status = ice_aq_alloc_free_res(hw, num, buf, buf_len, 1689*71d10453SEric Joyner ice_aqc_opc_free_res, NULL); 1690*71d10453SEric Joyner if (status) 1691*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); 1692*71d10453SEric Joyner 1693*71d10453SEric Joyner ice_free(hw, buf); 1694*71d10453SEric Joyner return status; 1695*71d10453SEric Joyner } 1696*71d10453SEric Joyner 1697*71d10453SEric Joyner /** 1698*71d10453SEric Joyner * ice_get_num_per_func - determine number of resources per PF 1699*71d10453SEric Joyner * @hw: pointer to the HW structure 1700*71d10453SEric Joyner * @max: value to be evenly split between each PF 1701*71d10453SEric Joyner * 1702*71d10453SEric Joyner * Determine the number of valid functions by going through the bitmap returned 1703*71d10453SEric Joyner * from parsing capabilities and use this to calculate the number of resources 1704*71d10453SEric Joyner * per PF based on the max value passed in. 1705*71d10453SEric Joyner */ 1706*71d10453SEric Joyner static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max) 1707*71d10453SEric Joyner { 1708*71d10453SEric Joyner u8 funcs; 1709*71d10453SEric Joyner 1710*71d10453SEric Joyner #define ICE_CAPS_VALID_FUNCS_M 0xFF 1711*71d10453SEric Joyner funcs = ice_hweight8(hw->dev_caps.common_cap.valid_functions & 1712*71d10453SEric Joyner ICE_CAPS_VALID_FUNCS_M); 1713*71d10453SEric Joyner 1714*71d10453SEric Joyner if (!funcs) 1715*71d10453SEric Joyner return 0; 1716*71d10453SEric Joyner 1717*71d10453SEric Joyner return max / funcs; 1718*71d10453SEric Joyner } 1719*71d10453SEric Joyner 1720*71d10453SEric Joyner /** 1721*71d10453SEric Joyner * ice_print_led_caps - print LED capabilities 1722*71d10453SEric Joyner * @hw: pointer to the ice_hw instance 1723*71d10453SEric Joyner * @caps: pointer to common caps instance 1724*71d10453SEric Joyner * @prefix: string to prefix when printing 1725*71d10453SEric Joyner * @debug: set to indicate debug print 1726*71d10453SEric Joyner */ 1727*71d10453SEric Joyner static void 1728*71d10453SEric Joyner ice_print_led_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps, 1729*71d10453SEric Joyner char const *prefix, bool debug) 1730*71d10453SEric Joyner { 1731*71d10453SEric Joyner u8 i; 1732*71d10453SEric Joyner 1733*71d10453SEric Joyner if (debug) 1734*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "%s: led_pin_num = %d\n", prefix, 1735*71d10453SEric Joyner caps->led_pin_num); 1736*71d10453SEric Joyner else 1737*71d10453SEric Joyner ice_info(hw, "%s: led_pin_num = %d\n", prefix, 1738*71d10453SEric Joyner caps->led_pin_num); 1739*71d10453SEric Joyner 1740*71d10453SEric Joyner for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_LED; i++) { 1741*71d10453SEric Joyner if (!caps->led[i]) 1742*71d10453SEric Joyner continue; 1743*71d10453SEric Joyner 1744*71d10453SEric Joyner if (debug) 1745*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = %d\n", 1746*71d10453SEric Joyner prefix, i, caps->led[i]); 1747*71d10453SEric Joyner else 1748*71d10453SEric Joyner ice_info(hw, "%s: led[%d] = %d\n", prefix, i, 1749*71d10453SEric Joyner caps->led[i]); 1750*71d10453SEric Joyner } 1751*71d10453SEric Joyner } 1752*71d10453SEric Joyner 1753*71d10453SEric Joyner /** 1754*71d10453SEric Joyner * ice_print_sdp_caps - print SDP capabilities 1755*71d10453SEric Joyner * @hw: pointer to the ice_hw instance 1756*71d10453SEric Joyner * @caps: pointer to common caps instance 1757*71d10453SEric Joyner * @prefix: string to prefix when printing 1758*71d10453SEric Joyner * @debug: set to indicate debug print 1759*71d10453SEric Joyner */ 1760*71d10453SEric Joyner static void 1761*71d10453SEric Joyner ice_print_sdp_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps, 1762*71d10453SEric Joyner char const *prefix, bool debug) 1763*71d10453SEric Joyner { 1764*71d10453SEric Joyner u8 i; 1765*71d10453SEric Joyner 1766*71d10453SEric Joyner if (debug) 1767*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "%s: sdp_pin_num = %d\n", prefix, 1768*71d10453SEric Joyner caps->sdp_pin_num); 1769*71d10453SEric Joyner else 1770*71d10453SEric Joyner ice_info(hw, "%s: sdp_pin_num = %d\n", prefix, 1771*71d10453SEric Joyner caps->sdp_pin_num); 1772*71d10453SEric Joyner 1773*71d10453SEric Joyner for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_SDP; i++) { 1774*71d10453SEric Joyner if (!caps->sdp[i]) 1775*71d10453SEric Joyner continue; 1776*71d10453SEric Joyner 1777*71d10453SEric Joyner if (debug) 1778*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = %d\n", 1779*71d10453SEric Joyner prefix, i, caps->sdp[i]); 1780*71d10453SEric Joyner else 1781*71d10453SEric Joyner ice_info(hw, "%s: sdp[%d] = %d\n", prefix, 1782*71d10453SEric Joyner i, caps->sdp[i]); 1783*71d10453SEric Joyner } 1784*71d10453SEric Joyner } 1785*71d10453SEric Joyner 1786*71d10453SEric Joyner /** 1787*71d10453SEric Joyner * ice_parse_caps - parse function/device capabilities 1788*71d10453SEric Joyner * @hw: pointer to the HW struct 1789*71d10453SEric Joyner * @buf: pointer to a buffer containing function/device capability records 1790*71d10453SEric Joyner * @cap_count: number of capability records in the list 1791*71d10453SEric Joyner * @opc: type of capabilities list to parse 1792*71d10453SEric Joyner * 1793*71d10453SEric Joyner * Helper function to parse function(0x000a)/device(0x000b) capabilities list. 1794*71d10453SEric Joyner */ 1795*71d10453SEric Joyner static void 1796*71d10453SEric Joyner ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count, 1797*71d10453SEric Joyner enum ice_adminq_opc opc) 1798*71d10453SEric Joyner { 1799*71d10453SEric Joyner struct ice_aqc_list_caps_elem *cap_resp; 1800*71d10453SEric Joyner struct ice_hw_func_caps *func_p = NULL; 1801*71d10453SEric Joyner struct ice_hw_dev_caps *dev_p = NULL; 1802*71d10453SEric Joyner struct ice_hw_common_caps *caps; 1803*71d10453SEric Joyner char const *prefix; 1804*71d10453SEric Joyner u32 i; 1805*71d10453SEric Joyner 1806*71d10453SEric Joyner if (!buf) 1807*71d10453SEric Joyner return; 1808*71d10453SEric Joyner 1809*71d10453SEric Joyner cap_resp = (struct ice_aqc_list_caps_elem *)buf; 1810*71d10453SEric Joyner 1811*71d10453SEric Joyner if (opc == ice_aqc_opc_list_dev_caps) { 1812*71d10453SEric Joyner dev_p = &hw->dev_caps; 1813*71d10453SEric Joyner caps = &dev_p->common_cap; 1814*71d10453SEric Joyner prefix = "dev cap"; 1815*71d10453SEric Joyner } else if (opc == ice_aqc_opc_list_func_caps) { 1816*71d10453SEric Joyner func_p = &hw->func_caps; 1817*71d10453SEric Joyner caps = &func_p->common_cap; 1818*71d10453SEric Joyner prefix = "func cap"; 1819*71d10453SEric Joyner } else { 1820*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "wrong opcode\n"); 1821*71d10453SEric Joyner return; 1822*71d10453SEric Joyner } 1823*71d10453SEric Joyner 1824*71d10453SEric Joyner for (i = 0; caps && i < cap_count; i++, cap_resp++) { 1825*71d10453SEric Joyner u32 logical_id = LE32_TO_CPU(cap_resp->logical_id); 1826*71d10453SEric Joyner u32 phys_id = LE32_TO_CPU(cap_resp->phys_id); 1827*71d10453SEric Joyner u32 number = LE32_TO_CPU(cap_resp->number); 1828*71d10453SEric Joyner u16 cap = LE16_TO_CPU(cap_resp->cap); 1829*71d10453SEric Joyner 1830*71d10453SEric Joyner switch (cap) { 1831*71d10453SEric Joyner case ICE_AQC_CAPS_SWITCHING_MODE: 1832*71d10453SEric Joyner caps->switching_mode = number; 1833*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1834*71d10453SEric Joyner "%s: switching_mode = %d\n", prefix, 1835*71d10453SEric Joyner caps->switching_mode); 1836*71d10453SEric Joyner break; 1837*71d10453SEric Joyner case ICE_AQC_CAPS_MANAGEABILITY_MODE: 1838*71d10453SEric Joyner caps->mgmt_mode = number; 1839*71d10453SEric Joyner caps->mgmt_protocols_mctp = logical_id; 1840*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1841*71d10453SEric Joyner "%s: mgmt_mode = %d\n", prefix, 1842*71d10453SEric Joyner caps->mgmt_mode); 1843*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1844*71d10453SEric Joyner "%s: mgmt_protocols_mctp = %d\n", prefix, 1845*71d10453SEric Joyner caps->mgmt_protocols_mctp); 1846*71d10453SEric Joyner break; 1847*71d10453SEric Joyner case ICE_AQC_CAPS_OS2BMC: 1848*71d10453SEric Joyner caps->os2bmc = number; 1849*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1850*71d10453SEric Joyner "%s: os2bmc = %d\n", prefix, caps->os2bmc); 1851*71d10453SEric Joyner break; 1852*71d10453SEric Joyner case ICE_AQC_CAPS_VALID_FUNCTIONS: 1853*71d10453SEric Joyner caps->valid_functions = number; 1854*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1855*71d10453SEric Joyner "%s: valid_functions (bitmap) = %d\n", prefix, 1856*71d10453SEric Joyner caps->valid_functions); 1857*71d10453SEric Joyner 1858*71d10453SEric Joyner /* store func count for resource management purposes */ 1859*71d10453SEric Joyner if (dev_p) 1860*71d10453SEric Joyner dev_p->num_funcs = ice_hweight32(number); 1861*71d10453SEric Joyner break; 1862*71d10453SEric Joyner case ICE_AQC_CAPS_SRIOV: 1863*71d10453SEric Joyner caps->sr_iov_1_1 = (number == 1); 1864*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1865*71d10453SEric Joyner "%s: sr_iov_1_1 = %d\n", prefix, 1866*71d10453SEric Joyner caps->sr_iov_1_1); 1867*71d10453SEric Joyner break; 1868*71d10453SEric Joyner case ICE_AQC_CAPS_VF: 1869*71d10453SEric Joyner if (dev_p) { 1870*71d10453SEric Joyner dev_p->num_vfs_exposed = number; 1871*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1872*71d10453SEric Joyner "%s: num_vfs_exposed = %d\n", prefix, 1873*71d10453SEric Joyner dev_p->num_vfs_exposed); 1874*71d10453SEric Joyner } else if (func_p) { 1875*71d10453SEric Joyner func_p->num_allocd_vfs = number; 1876*71d10453SEric Joyner func_p->vf_base_id = logical_id; 1877*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1878*71d10453SEric Joyner "%s: num_allocd_vfs = %d\n", prefix, 1879*71d10453SEric Joyner func_p->num_allocd_vfs); 1880*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1881*71d10453SEric Joyner "%s: vf_base_id = %d\n", prefix, 1882*71d10453SEric Joyner func_p->vf_base_id); 1883*71d10453SEric Joyner } 1884*71d10453SEric Joyner break; 1885*71d10453SEric Joyner case ICE_AQC_CAPS_802_1QBG: 1886*71d10453SEric Joyner caps->evb_802_1_qbg = (number == 1); 1887*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1888*71d10453SEric Joyner "%s: evb_802_1_qbg = %d\n", prefix, number); 1889*71d10453SEric Joyner break; 1890*71d10453SEric Joyner case ICE_AQC_CAPS_802_1BR: 1891*71d10453SEric Joyner caps->evb_802_1_qbh = (number == 1); 1892*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1893*71d10453SEric Joyner "%s: evb_802_1_qbh = %d\n", prefix, number); 1894*71d10453SEric Joyner break; 1895*71d10453SEric Joyner case ICE_AQC_CAPS_VSI: 1896*71d10453SEric Joyner if (dev_p) { 1897*71d10453SEric Joyner dev_p->num_vsi_allocd_to_host = number; 1898*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1899*71d10453SEric Joyner "%s: num_vsi_allocd_to_host = %d\n", 1900*71d10453SEric Joyner prefix, 1901*71d10453SEric Joyner dev_p->num_vsi_allocd_to_host); 1902*71d10453SEric Joyner } else if (func_p) { 1903*71d10453SEric Joyner func_p->guar_num_vsi = 1904*71d10453SEric Joyner ice_get_num_per_func(hw, ICE_MAX_VSI); 1905*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1906*71d10453SEric Joyner "%s: guar_num_vsi (fw) = %d\n", 1907*71d10453SEric Joyner prefix, number); 1908*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1909*71d10453SEric Joyner "%s: guar_num_vsi = %d\n", 1910*71d10453SEric Joyner prefix, func_p->guar_num_vsi); 1911*71d10453SEric Joyner } 1912*71d10453SEric Joyner break; 1913*71d10453SEric Joyner case ICE_AQC_CAPS_DCB: 1914*71d10453SEric Joyner caps->dcb = (number == 1); 1915*71d10453SEric Joyner caps->active_tc_bitmap = logical_id; 1916*71d10453SEric Joyner caps->maxtc = phys_id; 1917*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1918*71d10453SEric Joyner "%s: dcb = %d\n", prefix, caps->dcb); 1919*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1920*71d10453SEric Joyner "%s: active_tc_bitmap = %d\n", prefix, 1921*71d10453SEric Joyner caps->active_tc_bitmap); 1922*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1923*71d10453SEric Joyner "%s: maxtc = %d\n", prefix, caps->maxtc); 1924*71d10453SEric Joyner break; 1925*71d10453SEric Joyner case ICE_AQC_CAPS_ISCSI: 1926*71d10453SEric Joyner caps->iscsi = (number == 1); 1927*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1928*71d10453SEric Joyner "%s: iscsi = %d\n", prefix, caps->iscsi); 1929*71d10453SEric Joyner break; 1930*71d10453SEric Joyner case ICE_AQC_CAPS_RSS: 1931*71d10453SEric Joyner caps->rss_table_size = number; 1932*71d10453SEric Joyner caps->rss_table_entry_width = logical_id; 1933*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1934*71d10453SEric Joyner "%s: rss_table_size = %d\n", prefix, 1935*71d10453SEric Joyner caps->rss_table_size); 1936*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1937*71d10453SEric Joyner "%s: rss_table_entry_width = %d\n", prefix, 1938*71d10453SEric Joyner caps->rss_table_entry_width); 1939*71d10453SEric Joyner break; 1940*71d10453SEric Joyner case ICE_AQC_CAPS_RXQS: 1941*71d10453SEric Joyner caps->num_rxq = number; 1942*71d10453SEric Joyner caps->rxq_first_id = phys_id; 1943*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1944*71d10453SEric Joyner "%s: num_rxq = %d\n", prefix, 1945*71d10453SEric Joyner caps->num_rxq); 1946*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1947*71d10453SEric Joyner "%s: rxq_first_id = %d\n", prefix, 1948*71d10453SEric Joyner caps->rxq_first_id); 1949*71d10453SEric Joyner break; 1950*71d10453SEric Joyner case ICE_AQC_CAPS_TXQS: 1951*71d10453SEric Joyner caps->num_txq = number; 1952*71d10453SEric Joyner caps->txq_first_id = phys_id; 1953*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1954*71d10453SEric Joyner "%s: num_txq = %d\n", prefix, 1955*71d10453SEric Joyner caps->num_txq); 1956*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1957*71d10453SEric Joyner "%s: txq_first_id = %d\n", prefix, 1958*71d10453SEric Joyner caps->txq_first_id); 1959*71d10453SEric Joyner break; 1960*71d10453SEric Joyner case ICE_AQC_CAPS_MSIX: 1961*71d10453SEric Joyner caps->num_msix_vectors = number; 1962*71d10453SEric Joyner caps->msix_vector_first_id = phys_id; 1963*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1964*71d10453SEric Joyner "%s: num_msix_vectors = %d\n", prefix, 1965*71d10453SEric Joyner caps->num_msix_vectors); 1966*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1967*71d10453SEric Joyner "%s: msix_vector_first_id = %d\n", prefix, 1968*71d10453SEric Joyner caps->msix_vector_first_id); 1969*71d10453SEric Joyner break; 1970*71d10453SEric Joyner case ICE_AQC_CAPS_NVM_VER: 1971*71d10453SEric Joyner break; 1972*71d10453SEric Joyner case ICE_AQC_CAPS_NVM_MGMT: 1973*71d10453SEric Joyner caps->nvm_unified_update = 1974*71d10453SEric Joyner (number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ? 1975*71d10453SEric Joyner true : false; 1976*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1977*71d10453SEric Joyner "%s: nvm_unified_update = %d\n", prefix, 1978*71d10453SEric Joyner caps->nvm_unified_update); 1979*71d10453SEric Joyner break; 1980*71d10453SEric Joyner case ICE_AQC_CAPS_CEM: 1981*71d10453SEric Joyner caps->mgmt_cem = (number == 1); 1982*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 1983*71d10453SEric Joyner "%s: mgmt_cem = %d\n", prefix, 1984*71d10453SEric Joyner caps->mgmt_cem); 1985*71d10453SEric Joyner break; 1986*71d10453SEric Joyner case ICE_AQC_CAPS_LED: 1987*71d10453SEric Joyner if (phys_id < ICE_MAX_SUPPORTED_GPIO_LED) { 1988*71d10453SEric Joyner caps->led[phys_id] = true; 1989*71d10453SEric Joyner caps->led_pin_num++; 1990*71d10453SEric Joyner } 1991*71d10453SEric Joyner break; 1992*71d10453SEric Joyner case ICE_AQC_CAPS_SDP: 1993*71d10453SEric Joyner if (phys_id < ICE_MAX_SUPPORTED_GPIO_SDP) { 1994*71d10453SEric Joyner caps->sdp[phys_id] = true; 1995*71d10453SEric Joyner caps->sdp_pin_num++; 1996*71d10453SEric Joyner } 1997*71d10453SEric Joyner break; 1998*71d10453SEric Joyner case ICE_AQC_CAPS_WR_CSR_PROT: 1999*71d10453SEric Joyner caps->wr_csr_prot = number; 2000*71d10453SEric Joyner caps->wr_csr_prot |= (u64)logical_id << 32; 2001*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 2002*71d10453SEric Joyner "%s: wr_csr_prot = 0x%llX\n", prefix, 2003*71d10453SEric Joyner (unsigned long long)caps->wr_csr_prot); 2004*71d10453SEric Joyner break; 2005*71d10453SEric Joyner case ICE_AQC_CAPS_WOL_PROXY: 2006*71d10453SEric Joyner caps->num_wol_proxy_fltr = number; 2007*71d10453SEric Joyner caps->wol_proxy_vsi_seid = logical_id; 2008*71d10453SEric Joyner caps->apm_wol_support = !!(phys_id & ICE_WOL_SUPPORT_M); 2009*71d10453SEric Joyner caps->acpi_prog_mthd = !!(phys_id & 2010*71d10453SEric Joyner ICE_ACPI_PROG_MTHD_M); 2011*71d10453SEric Joyner caps->proxy_support = !!(phys_id & ICE_PROXY_SUPPORT_M); 2012*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 2013*71d10453SEric Joyner "%s: num_wol_proxy_fltr = %d\n", prefix, 2014*71d10453SEric Joyner caps->num_wol_proxy_fltr); 2015*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 2016*71d10453SEric Joyner "%s: wol_proxy_vsi_seid = %d\n", prefix, 2017*71d10453SEric Joyner caps->wol_proxy_vsi_seid); 2018*71d10453SEric Joyner break; 2019*71d10453SEric Joyner case ICE_AQC_CAPS_MAX_MTU: 2020*71d10453SEric Joyner caps->max_mtu = number; 2021*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n", 2022*71d10453SEric Joyner prefix, caps->max_mtu); 2023*71d10453SEric Joyner break; 2024*71d10453SEric Joyner default: 2025*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 2026*71d10453SEric Joyner "%s: unknown capability[%d]: 0x%x\n", prefix, 2027*71d10453SEric Joyner i, cap); 2028*71d10453SEric Joyner break; 2029*71d10453SEric Joyner } 2030*71d10453SEric Joyner } 2031*71d10453SEric Joyner 2032*71d10453SEric Joyner ice_print_led_caps(hw, caps, prefix, true); 2033*71d10453SEric Joyner ice_print_sdp_caps(hw, caps, prefix, true); 2034*71d10453SEric Joyner 2035*71d10453SEric Joyner /* Re-calculate capabilities that are dependent on the number of 2036*71d10453SEric Joyner * physical ports; i.e. some features are not supported or function 2037*71d10453SEric Joyner * differently on devices with more than 4 ports. 2038*71d10453SEric Joyner */ 2039*71d10453SEric Joyner if (hw->dev_caps.num_funcs > 4) { 2040*71d10453SEric Joyner /* Max 4 TCs per port */ 2041*71d10453SEric Joyner caps->maxtc = 4; 2042*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 2043*71d10453SEric Joyner "%s: maxtc = %d (based on #ports)\n", prefix, 2044*71d10453SEric Joyner caps->maxtc); 2045*71d10453SEric Joyner } 2046*71d10453SEric Joyner } 2047*71d10453SEric Joyner 2048*71d10453SEric Joyner /** 2049*71d10453SEric Joyner * ice_aq_discover_caps - query function/device capabilities 2050*71d10453SEric Joyner * @hw: pointer to the HW struct 2051*71d10453SEric Joyner * @buf: a virtual buffer to hold the capabilities 2052*71d10453SEric Joyner * @buf_size: Size of the virtual buffer 2053*71d10453SEric Joyner * @cap_count: cap count needed if AQ err==ENOMEM 2054*71d10453SEric Joyner * @opc: capabilities type to discover - pass in the command opcode 2055*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 2056*71d10453SEric Joyner * 2057*71d10453SEric Joyner * Get the function(0x000a)/device(0x000b) capabilities description from 2058*71d10453SEric Joyner * the firmware. 2059*71d10453SEric Joyner */ 2060*71d10453SEric Joyner enum ice_status 2061*71d10453SEric Joyner ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, 2062*71d10453SEric Joyner enum ice_adminq_opc opc, struct ice_sq_cd *cd) 2063*71d10453SEric Joyner { 2064*71d10453SEric Joyner struct ice_aqc_list_caps *cmd; 2065*71d10453SEric Joyner struct ice_aq_desc desc; 2066*71d10453SEric Joyner enum ice_status status; 2067*71d10453SEric Joyner 2068*71d10453SEric Joyner cmd = &desc.params.get_cap; 2069*71d10453SEric Joyner 2070*71d10453SEric Joyner if (opc != ice_aqc_opc_list_func_caps && 2071*71d10453SEric Joyner opc != ice_aqc_opc_list_dev_caps) 2072*71d10453SEric Joyner return ICE_ERR_PARAM; 2073*71d10453SEric Joyner 2074*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, opc); 2075*71d10453SEric Joyner 2076*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2077*71d10453SEric Joyner if (!status) 2078*71d10453SEric Joyner ice_parse_caps(hw, buf, LE32_TO_CPU(cmd->count), opc); 2079*71d10453SEric Joyner else if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOMEM) 2080*71d10453SEric Joyner *cap_count = LE32_TO_CPU(cmd->count); 2081*71d10453SEric Joyner return status; 2082*71d10453SEric Joyner } 2083*71d10453SEric Joyner 2084*71d10453SEric Joyner /** 2085*71d10453SEric Joyner * ice_discover_caps - get info about the HW 2086*71d10453SEric Joyner * @hw: pointer to the hardware structure 2087*71d10453SEric Joyner * @opc: capabilities type to discover - pass in the command opcode 2088*71d10453SEric Joyner */ 2089*71d10453SEric Joyner static enum ice_status 2090*71d10453SEric Joyner ice_discover_caps(struct ice_hw *hw, enum ice_adminq_opc opc) 2091*71d10453SEric Joyner { 2092*71d10453SEric Joyner enum ice_status status; 2093*71d10453SEric Joyner u32 cap_count; 2094*71d10453SEric Joyner u16 cbuf_len; 2095*71d10453SEric Joyner u8 retries; 2096*71d10453SEric Joyner 2097*71d10453SEric Joyner /* The driver doesn't know how many capabilities the device will return 2098*71d10453SEric Joyner * so the buffer size required isn't known ahead of time. The driver 2099*71d10453SEric Joyner * starts with cbuf_len and if this turns out to be insufficient, the 2100*71d10453SEric Joyner * device returns ICE_AQ_RC_ENOMEM and also the cap_count it needs. 2101*71d10453SEric Joyner * The driver then allocates the buffer based on the count and retries 2102*71d10453SEric Joyner * the operation. So it follows that the retry count is 2. 2103*71d10453SEric Joyner */ 2104*71d10453SEric Joyner #define ICE_GET_CAP_BUF_COUNT 40 2105*71d10453SEric Joyner #define ICE_GET_CAP_RETRY_COUNT 2 2106*71d10453SEric Joyner 2107*71d10453SEric Joyner cap_count = ICE_GET_CAP_BUF_COUNT; 2108*71d10453SEric Joyner retries = ICE_GET_CAP_RETRY_COUNT; 2109*71d10453SEric Joyner 2110*71d10453SEric Joyner do { 2111*71d10453SEric Joyner void *cbuf; 2112*71d10453SEric Joyner 2113*71d10453SEric Joyner cbuf_len = (u16)(cap_count * 2114*71d10453SEric Joyner sizeof(struct ice_aqc_list_caps_elem)); 2115*71d10453SEric Joyner cbuf = ice_malloc(hw, cbuf_len); 2116*71d10453SEric Joyner if (!cbuf) 2117*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 2118*71d10453SEric Joyner 2119*71d10453SEric Joyner status = ice_aq_discover_caps(hw, cbuf, cbuf_len, &cap_count, 2120*71d10453SEric Joyner opc, NULL); 2121*71d10453SEric Joyner ice_free(hw, cbuf); 2122*71d10453SEric Joyner 2123*71d10453SEric Joyner if (!status || hw->adminq.sq_last_status != ICE_AQ_RC_ENOMEM) 2124*71d10453SEric Joyner break; 2125*71d10453SEric Joyner 2126*71d10453SEric Joyner /* If ENOMEM is returned, try again with bigger buffer */ 2127*71d10453SEric Joyner } while (--retries); 2128*71d10453SEric Joyner 2129*71d10453SEric Joyner return status; 2130*71d10453SEric Joyner } 2131*71d10453SEric Joyner 2132*71d10453SEric Joyner /** 2133*71d10453SEric Joyner * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode 2134*71d10453SEric Joyner * @hw: pointer to the hardware structure 2135*71d10453SEric Joyner */ 2136*71d10453SEric Joyner void ice_set_safe_mode_caps(struct ice_hw *hw) 2137*71d10453SEric Joyner { 2138*71d10453SEric Joyner struct ice_hw_func_caps *func_caps = &hw->func_caps; 2139*71d10453SEric Joyner struct ice_hw_dev_caps *dev_caps = &hw->dev_caps; 2140*71d10453SEric Joyner u32 valid_func, rxq_first_id, txq_first_id; 2141*71d10453SEric Joyner u32 msix_vector_first_id, max_mtu; 2142*71d10453SEric Joyner u32 num_funcs; 2143*71d10453SEric Joyner 2144*71d10453SEric Joyner /* cache some func_caps values that should be restored after memset */ 2145*71d10453SEric Joyner valid_func = func_caps->common_cap.valid_functions; 2146*71d10453SEric Joyner txq_first_id = func_caps->common_cap.txq_first_id; 2147*71d10453SEric Joyner rxq_first_id = func_caps->common_cap.rxq_first_id; 2148*71d10453SEric Joyner msix_vector_first_id = func_caps->common_cap.msix_vector_first_id; 2149*71d10453SEric Joyner max_mtu = func_caps->common_cap.max_mtu; 2150*71d10453SEric Joyner 2151*71d10453SEric Joyner /* unset func capabilities */ 2152*71d10453SEric Joyner memset(func_caps, 0, sizeof(*func_caps)); 2153*71d10453SEric Joyner 2154*71d10453SEric Joyner /* restore cached values */ 2155*71d10453SEric Joyner func_caps->common_cap.valid_functions = valid_func; 2156*71d10453SEric Joyner func_caps->common_cap.txq_first_id = txq_first_id; 2157*71d10453SEric Joyner func_caps->common_cap.rxq_first_id = rxq_first_id; 2158*71d10453SEric Joyner func_caps->common_cap.msix_vector_first_id = msix_vector_first_id; 2159*71d10453SEric Joyner func_caps->common_cap.max_mtu = max_mtu; 2160*71d10453SEric Joyner 2161*71d10453SEric Joyner /* one Tx and one Rx queue in safe mode */ 2162*71d10453SEric Joyner func_caps->common_cap.num_rxq = 1; 2163*71d10453SEric Joyner func_caps->common_cap.num_txq = 1; 2164*71d10453SEric Joyner 2165*71d10453SEric Joyner /* two MSIX vectors, one for traffic and one for misc causes */ 2166*71d10453SEric Joyner func_caps->common_cap.num_msix_vectors = 2; 2167*71d10453SEric Joyner func_caps->guar_num_vsi = 1; 2168*71d10453SEric Joyner 2169*71d10453SEric Joyner /* cache some dev_caps values that should be restored after memset */ 2170*71d10453SEric Joyner valid_func = dev_caps->common_cap.valid_functions; 2171*71d10453SEric Joyner txq_first_id = dev_caps->common_cap.txq_first_id; 2172*71d10453SEric Joyner rxq_first_id = dev_caps->common_cap.rxq_first_id; 2173*71d10453SEric Joyner msix_vector_first_id = dev_caps->common_cap.msix_vector_first_id; 2174*71d10453SEric Joyner max_mtu = dev_caps->common_cap.max_mtu; 2175*71d10453SEric Joyner num_funcs = dev_caps->num_funcs; 2176*71d10453SEric Joyner 2177*71d10453SEric Joyner /* unset dev capabilities */ 2178*71d10453SEric Joyner memset(dev_caps, 0, sizeof(*dev_caps)); 2179*71d10453SEric Joyner 2180*71d10453SEric Joyner /* restore cached values */ 2181*71d10453SEric Joyner dev_caps->common_cap.valid_functions = valid_func; 2182*71d10453SEric Joyner dev_caps->common_cap.txq_first_id = txq_first_id; 2183*71d10453SEric Joyner dev_caps->common_cap.rxq_first_id = rxq_first_id; 2184*71d10453SEric Joyner dev_caps->common_cap.msix_vector_first_id = msix_vector_first_id; 2185*71d10453SEric Joyner dev_caps->common_cap.max_mtu = max_mtu; 2186*71d10453SEric Joyner dev_caps->num_funcs = num_funcs; 2187*71d10453SEric Joyner 2188*71d10453SEric Joyner /* one Tx and one Rx queue per function in safe mode */ 2189*71d10453SEric Joyner dev_caps->common_cap.num_rxq = num_funcs; 2190*71d10453SEric Joyner dev_caps->common_cap.num_txq = num_funcs; 2191*71d10453SEric Joyner 2192*71d10453SEric Joyner /* two MSIX vectors per function */ 2193*71d10453SEric Joyner dev_caps->common_cap.num_msix_vectors = 2 * num_funcs; 2194*71d10453SEric Joyner } 2195*71d10453SEric Joyner 2196*71d10453SEric Joyner /** 2197*71d10453SEric Joyner * ice_get_caps - get info about the HW 2198*71d10453SEric Joyner * @hw: pointer to the hardware structure 2199*71d10453SEric Joyner */ 2200*71d10453SEric Joyner enum ice_status ice_get_caps(struct ice_hw *hw) 2201*71d10453SEric Joyner { 2202*71d10453SEric Joyner enum ice_status status; 2203*71d10453SEric Joyner 2204*71d10453SEric Joyner status = ice_discover_caps(hw, ice_aqc_opc_list_dev_caps); 2205*71d10453SEric Joyner if (!status) 2206*71d10453SEric Joyner status = ice_discover_caps(hw, ice_aqc_opc_list_func_caps); 2207*71d10453SEric Joyner 2208*71d10453SEric Joyner return status; 2209*71d10453SEric Joyner } 2210*71d10453SEric Joyner 2211*71d10453SEric Joyner /** 2212*71d10453SEric Joyner * ice_aq_manage_mac_write - manage MAC address write command 2213*71d10453SEric Joyner * @hw: pointer to the HW struct 2214*71d10453SEric Joyner * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address 2215*71d10453SEric Joyner * @flags: flags to control write behavior 2216*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 2217*71d10453SEric Joyner * 2218*71d10453SEric Joyner * This function is used to write MAC address to the NVM (0x0108). 2219*71d10453SEric Joyner */ 2220*71d10453SEric Joyner enum ice_status 2221*71d10453SEric Joyner ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags, 2222*71d10453SEric Joyner struct ice_sq_cd *cd) 2223*71d10453SEric Joyner { 2224*71d10453SEric Joyner struct ice_aqc_manage_mac_write *cmd; 2225*71d10453SEric Joyner struct ice_aq_desc desc; 2226*71d10453SEric Joyner 2227*71d10453SEric Joyner cmd = &desc.params.mac_write; 2228*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write); 2229*71d10453SEric Joyner 2230*71d10453SEric Joyner cmd->flags = flags; 2231*71d10453SEric Joyner ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_DMA); 2232*71d10453SEric Joyner 2233*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 2234*71d10453SEric Joyner } 2235*71d10453SEric Joyner 2236*71d10453SEric Joyner /** 2237*71d10453SEric Joyner * ice_aq_clear_pxe_mode 2238*71d10453SEric Joyner * @hw: pointer to the HW struct 2239*71d10453SEric Joyner * 2240*71d10453SEric Joyner * Tell the firmware that the driver is taking over from PXE (0x0110). 2241*71d10453SEric Joyner */ 2242*71d10453SEric Joyner static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw) 2243*71d10453SEric Joyner { 2244*71d10453SEric Joyner struct ice_aq_desc desc; 2245*71d10453SEric Joyner 2246*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode); 2247*71d10453SEric Joyner desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT; 2248*71d10453SEric Joyner 2249*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 2250*71d10453SEric Joyner } 2251*71d10453SEric Joyner 2252*71d10453SEric Joyner /** 2253*71d10453SEric Joyner * ice_clear_pxe_mode - clear pxe operations mode 2254*71d10453SEric Joyner * @hw: pointer to the HW struct 2255*71d10453SEric Joyner * 2256*71d10453SEric Joyner * Make sure all PXE mode settings are cleared, including things 2257*71d10453SEric Joyner * like descriptor fetch/write-back mode. 2258*71d10453SEric Joyner */ 2259*71d10453SEric Joyner void ice_clear_pxe_mode(struct ice_hw *hw) 2260*71d10453SEric Joyner { 2261*71d10453SEric Joyner if (ice_check_sq_alive(hw, &hw->adminq)) 2262*71d10453SEric Joyner ice_aq_clear_pxe_mode(hw); 2263*71d10453SEric Joyner } 2264*71d10453SEric Joyner 2265*71d10453SEric Joyner /** 2266*71d10453SEric Joyner * ice_aq_set_port_params - set physical port parameters. 2267*71d10453SEric Joyner * @pi: pointer to the port info struct 2268*71d10453SEric Joyner * @bad_frame_vsi: defines the VSI to which bad frames are forwarded 2269*71d10453SEric Joyner * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI 2270*71d10453SEric Joyner * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded 2271*71d10453SEric Joyner * @double_vlan: if set double VLAN is enabled 2272*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 2273*71d10453SEric Joyner * 2274*71d10453SEric Joyner * Set Physical port parameters (0x0203) 2275*71d10453SEric Joyner */ 2276*71d10453SEric Joyner enum ice_status 2277*71d10453SEric Joyner ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi, 2278*71d10453SEric Joyner bool save_bad_pac, bool pad_short_pac, bool double_vlan, 2279*71d10453SEric Joyner struct ice_sq_cd *cd) 2280*71d10453SEric Joyner 2281*71d10453SEric Joyner { 2282*71d10453SEric Joyner struct ice_aqc_set_port_params *cmd; 2283*71d10453SEric Joyner struct ice_hw *hw = pi->hw; 2284*71d10453SEric Joyner struct ice_aq_desc desc; 2285*71d10453SEric Joyner u16 cmd_flags = 0; 2286*71d10453SEric Joyner 2287*71d10453SEric Joyner cmd = &desc.params.set_port_params; 2288*71d10453SEric Joyner 2289*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params); 2290*71d10453SEric Joyner cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi); 2291*71d10453SEric Joyner if (save_bad_pac) 2292*71d10453SEric Joyner cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS; 2293*71d10453SEric Joyner if (pad_short_pac) 2294*71d10453SEric Joyner cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS; 2295*71d10453SEric Joyner if (double_vlan) 2296*71d10453SEric Joyner cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA; 2297*71d10453SEric Joyner cmd->cmd_flags = CPU_TO_LE16(cmd_flags); 2298*71d10453SEric Joyner 2299*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 2300*71d10453SEric Joyner } 2301*71d10453SEric Joyner 2302*71d10453SEric Joyner /** 2303*71d10453SEric Joyner * ice_get_link_speed_based_on_phy_type - returns link speed 2304*71d10453SEric Joyner * @phy_type_low: lower part of phy_type 2305*71d10453SEric Joyner * @phy_type_high: higher part of phy_type 2306*71d10453SEric Joyner * 2307*71d10453SEric Joyner * This helper function will convert an entry in PHY type structure 2308*71d10453SEric Joyner * [phy_type_low, phy_type_high] to its corresponding link speed. 2309*71d10453SEric Joyner * Note: In the structure of [phy_type_low, phy_type_high], there should 2310*71d10453SEric Joyner * be one bit set, as this function will convert one PHY type to its 2311*71d10453SEric Joyner * speed. 2312*71d10453SEric Joyner * If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned 2313*71d10453SEric Joyner * If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned 2314*71d10453SEric Joyner */ 2315*71d10453SEric Joyner static u16 2316*71d10453SEric Joyner ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) 2317*71d10453SEric Joyner { 2318*71d10453SEric Joyner u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; 2319*71d10453SEric Joyner u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; 2320*71d10453SEric Joyner 2321*71d10453SEric Joyner switch (phy_type_low) { 2322*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100BASE_TX: 2323*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100M_SGMII: 2324*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB; 2325*71d10453SEric Joyner break; 2326*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_T: 2327*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_SX: 2328*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_LX: 2329*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1000BASE_KX: 2330*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_1G_SGMII: 2331*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB; 2332*71d10453SEric Joyner break; 2333*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_2500BASE_T: 2334*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_2500BASE_X: 2335*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_2500BASE_KX: 2336*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB; 2337*71d10453SEric Joyner break; 2338*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_5GBASE_T: 2339*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_5GBASE_KR: 2340*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB; 2341*71d10453SEric Joyner break; 2342*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_T: 2343*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10G_SFI_DA: 2344*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_SR: 2345*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_LR: 2346*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 2347*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC: 2348*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 2349*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB; 2350*71d10453SEric Joyner break; 2351*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_T: 2352*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_CR: 2353*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 2354*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_CR1: 2355*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_SR: 2356*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_LR: 2357*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_KR: 2358*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 2359*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25GBASE_KR1: 2360*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC: 2361*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 2362*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB; 2363*71d10453SEric Joyner break; 2364*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_CR4: 2365*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_SR4: 2366*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_LR4: 2367*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40GBASE_KR4: 2368*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC: 2369*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_40G_XLAUI: 2370*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB; 2371*71d10453SEric Joyner break; 2372*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_CR2: 2373*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_SR2: 2374*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_LR2: 2375*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_KR2: 2376*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: 2377*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_LAUI2: 2378*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: 2379*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_AUI2: 2380*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_CP: 2381*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_SR: 2382*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_FR: 2383*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_LR: 2384*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 2385*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: 2386*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_50G_AUI1: 2387*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB; 2388*71d10453SEric Joyner break; 2389*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_CR4: 2390*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_SR4: 2391*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_LR4: 2392*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_KR4: 2393*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: 2394*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100G_CAUI4: 2395*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: 2396*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100G_AUI4: 2397*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 2398*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 2399*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_CP2: 2400*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_SR2: 2401*71d10453SEric Joyner case ICE_PHY_TYPE_LOW_100GBASE_DR: 2402*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB; 2403*71d10453SEric Joyner break; 2404*71d10453SEric Joyner default: 2405*71d10453SEric Joyner speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; 2406*71d10453SEric Joyner break; 2407*71d10453SEric Joyner } 2408*71d10453SEric Joyner 2409*71d10453SEric Joyner switch (phy_type_high) { 2410*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 2411*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: 2412*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100G_CAUI2: 2413*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: 2414*71d10453SEric Joyner case ICE_PHY_TYPE_HIGH_100G_AUI2: 2415*71d10453SEric Joyner speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB; 2416*71d10453SEric Joyner break; 2417*71d10453SEric Joyner default: 2418*71d10453SEric Joyner speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; 2419*71d10453SEric Joyner break; 2420*71d10453SEric Joyner } 2421*71d10453SEric Joyner 2422*71d10453SEric Joyner if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN && 2423*71d10453SEric Joyner speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN) 2424*71d10453SEric Joyner return ICE_AQ_LINK_SPEED_UNKNOWN; 2425*71d10453SEric Joyner else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN && 2426*71d10453SEric Joyner speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN) 2427*71d10453SEric Joyner return ICE_AQ_LINK_SPEED_UNKNOWN; 2428*71d10453SEric Joyner else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN && 2429*71d10453SEric Joyner speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN) 2430*71d10453SEric Joyner return speed_phy_type_low; 2431*71d10453SEric Joyner else 2432*71d10453SEric Joyner return speed_phy_type_high; 2433*71d10453SEric Joyner } 2434*71d10453SEric Joyner 2435*71d10453SEric Joyner /** 2436*71d10453SEric Joyner * ice_update_phy_type 2437*71d10453SEric Joyner * @phy_type_low: pointer to the lower part of phy_type 2438*71d10453SEric Joyner * @phy_type_high: pointer to the higher part of phy_type 2439*71d10453SEric Joyner * @link_speeds_bitmap: targeted link speeds bitmap 2440*71d10453SEric Joyner * 2441*71d10453SEric Joyner * Note: For the link_speeds_bitmap structure, you can check it at 2442*71d10453SEric Joyner * [ice_aqc_get_link_status->link_speed]. Caller can pass in 2443*71d10453SEric Joyner * link_speeds_bitmap include multiple speeds. 2444*71d10453SEric Joyner * 2445*71d10453SEric Joyner * Each entry in this [phy_type_low, phy_type_high] structure will 2446*71d10453SEric Joyner * present a certain link speed. This helper function will turn on bits 2447*71d10453SEric Joyner * in [phy_type_low, phy_type_high] structure based on the value of 2448*71d10453SEric Joyner * link_speeds_bitmap input parameter. 2449*71d10453SEric Joyner */ 2450*71d10453SEric Joyner void 2451*71d10453SEric Joyner ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, 2452*71d10453SEric Joyner u16 link_speeds_bitmap) 2453*71d10453SEric Joyner { 2454*71d10453SEric Joyner u64 pt_high; 2455*71d10453SEric Joyner u64 pt_low; 2456*71d10453SEric Joyner int index; 2457*71d10453SEric Joyner u16 speed; 2458*71d10453SEric Joyner 2459*71d10453SEric Joyner /* We first check with low part of phy_type */ 2460*71d10453SEric Joyner for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) { 2461*71d10453SEric Joyner pt_low = BIT_ULL(index); 2462*71d10453SEric Joyner speed = ice_get_link_speed_based_on_phy_type(pt_low, 0); 2463*71d10453SEric Joyner 2464*71d10453SEric Joyner if (link_speeds_bitmap & speed) 2465*71d10453SEric Joyner *phy_type_low |= BIT_ULL(index); 2466*71d10453SEric Joyner } 2467*71d10453SEric Joyner 2468*71d10453SEric Joyner /* We then check with high part of phy_type */ 2469*71d10453SEric Joyner for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) { 2470*71d10453SEric Joyner pt_high = BIT_ULL(index); 2471*71d10453SEric Joyner speed = ice_get_link_speed_based_on_phy_type(0, pt_high); 2472*71d10453SEric Joyner 2473*71d10453SEric Joyner if (link_speeds_bitmap & speed) 2474*71d10453SEric Joyner *phy_type_high |= BIT_ULL(index); 2475*71d10453SEric Joyner } 2476*71d10453SEric Joyner } 2477*71d10453SEric Joyner 2478*71d10453SEric Joyner /** 2479*71d10453SEric Joyner * ice_aq_set_phy_cfg 2480*71d10453SEric Joyner * @hw: pointer to the HW struct 2481*71d10453SEric Joyner * @pi: port info structure of the interested logical port 2482*71d10453SEric Joyner * @cfg: structure with PHY configuration data to be set 2483*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 2484*71d10453SEric Joyner * 2485*71d10453SEric Joyner * Set the various PHY configuration parameters supported on the Port. 2486*71d10453SEric Joyner * One or more of the Set PHY config parameters may be ignored in an MFP 2487*71d10453SEric Joyner * mode as the PF may not have the privilege to set some of the PHY Config 2488*71d10453SEric Joyner * parameters. This status will be indicated by the command response (0x0601). 2489*71d10453SEric Joyner */ 2490*71d10453SEric Joyner enum ice_status 2491*71d10453SEric Joyner ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi, 2492*71d10453SEric Joyner struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd) 2493*71d10453SEric Joyner { 2494*71d10453SEric Joyner struct ice_aq_desc desc; 2495*71d10453SEric Joyner enum ice_status status; 2496*71d10453SEric Joyner 2497*71d10453SEric Joyner if (!cfg) 2498*71d10453SEric Joyner return ICE_ERR_PARAM; 2499*71d10453SEric Joyner 2500*71d10453SEric Joyner /* Ensure that only valid bits of cfg->caps can be turned on. */ 2501*71d10453SEric Joyner if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) { 2502*71d10453SEric Joyner ice_debug(hw, ICE_DBG_PHY, 2503*71d10453SEric Joyner "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n", 2504*71d10453SEric Joyner cfg->caps); 2505*71d10453SEric Joyner 2506*71d10453SEric Joyner cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK; 2507*71d10453SEric Joyner } 2508*71d10453SEric Joyner 2509*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg); 2510*71d10453SEric Joyner desc.params.set_phy.lport_num = pi->lport; 2511*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 2512*71d10453SEric Joyner 2513*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n", 2514*71d10453SEric Joyner (unsigned long long)LE64_TO_CPU(cfg->phy_type_low)); 2515*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n", 2516*71d10453SEric Joyner (unsigned long long)LE64_TO_CPU(cfg->phy_type_high)); 2517*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "caps = 0x%x\n", cfg->caps); 2518*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "low_power_ctrl_an = 0x%x\n", 2519*71d10453SEric Joyner cfg->low_power_ctrl_an); 2520*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "eee_cap = 0x%x\n", cfg->eee_cap); 2521*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "eeer_value = 0x%x\n", cfg->eeer_value); 2522*71d10453SEric Joyner ice_debug(hw, ICE_DBG_LINK, "link_fec_opt = 0x%x\n", cfg->link_fec_opt); 2523*71d10453SEric Joyner 2524*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd); 2525*71d10453SEric Joyner 2526*71d10453SEric Joyner if (!status) 2527*71d10453SEric Joyner pi->phy.curr_user_phy_cfg = *cfg; 2528*71d10453SEric Joyner 2529*71d10453SEric Joyner return status; 2530*71d10453SEric Joyner } 2531*71d10453SEric Joyner 2532*71d10453SEric Joyner /** 2533*71d10453SEric Joyner * ice_update_link_info - update status of the HW network link 2534*71d10453SEric Joyner * @pi: port info structure of the interested logical port 2535*71d10453SEric Joyner */ 2536*71d10453SEric Joyner enum ice_status ice_update_link_info(struct ice_port_info *pi) 2537*71d10453SEric Joyner { 2538*71d10453SEric Joyner struct ice_link_status *li; 2539*71d10453SEric Joyner enum ice_status status; 2540*71d10453SEric Joyner 2541*71d10453SEric Joyner if (!pi) 2542*71d10453SEric Joyner return ICE_ERR_PARAM; 2543*71d10453SEric Joyner 2544*71d10453SEric Joyner li = &pi->phy.link_info; 2545*71d10453SEric Joyner 2546*71d10453SEric Joyner status = ice_aq_get_link_info(pi, true, NULL, NULL); 2547*71d10453SEric Joyner if (status) 2548*71d10453SEric Joyner return status; 2549*71d10453SEric Joyner 2550*71d10453SEric Joyner if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) { 2551*71d10453SEric Joyner struct ice_aqc_get_phy_caps_data *pcaps; 2552*71d10453SEric Joyner struct ice_hw *hw; 2553*71d10453SEric Joyner 2554*71d10453SEric Joyner hw = pi->hw; 2555*71d10453SEric Joyner pcaps = (struct ice_aqc_get_phy_caps_data *) 2556*71d10453SEric Joyner ice_malloc(hw, sizeof(*pcaps)); 2557*71d10453SEric Joyner if (!pcaps) 2558*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 2559*71d10453SEric Joyner 2560*71d10453SEric Joyner status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, 2561*71d10453SEric Joyner pcaps, NULL); 2562*71d10453SEric Joyner if (status == ICE_SUCCESS) 2563*71d10453SEric Joyner ice_memcpy(li->module_type, &pcaps->module_type, 2564*71d10453SEric Joyner sizeof(li->module_type), 2565*71d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 2566*71d10453SEric Joyner 2567*71d10453SEric Joyner ice_free(hw, pcaps); 2568*71d10453SEric Joyner } 2569*71d10453SEric Joyner 2570*71d10453SEric Joyner return status; 2571*71d10453SEric Joyner } 2572*71d10453SEric Joyner 2573*71d10453SEric Joyner /** 2574*71d10453SEric Joyner * ice_cache_phy_user_req 2575*71d10453SEric Joyner * @pi: port information structure 2576*71d10453SEric Joyner * @cache_data: PHY logging data 2577*71d10453SEric Joyner * @cache_mode: PHY logging mode 2578*71d10453SEric Joyner * 2579*71d10453SEric Joyner * Log the user request on (FC, FEC, SPEED) for later user. 2580*71d10453SEric Joyner */ 2581*71d10453SEric Joyner static void 2582*71d10453SEric Joyner ice_cache_phy_user_req(struct ice_port_info *pi, 2583*71d10453SEric Joyner struct ice_phy_cache_mode_data cache_data, 2584*71d10453SEric Joyner enum ice_phy_cache_mode cache_mode) 2585*71d10453SEric Joyner { 2586*71d10453SEric Joyner if (!pi) 2587*71d10453SEric Joyner return; 2588*71d10453SEric Joyner 2589*71d10453SEric Joyner switch (cache_mode) { 2590*71d10453SEric Joyner case ICE_FC_MODE: 2591*71d10453SEric Joyner pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req; 2592*71d10453SEric Joyner break; 2593*71d10453SEric Joyner case ICE_SPEED_MODE: 2594*71d10453SEric Joyner pi->phy.curr_user_speed_req = 2595*71d10453SEric Joyner cache_data.data.curr_user_speed_req; 2596*71d10453SEric Joyner break; 2597*71d10453SEric Joyner case ICE_FEC_MODE: 2598*71d10453SEric Joyner pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req; 2599*71d10453SEric Joyner break; 2600*71d10453SEric Joyner default: 2601*71d10453SEric Joyner break; 2602*71d10453SEric Joyner } 2603*71d10453SEric Joyner } 2604*71d10453SEric Joyner 2605*71d10453SEric Joyner /** 2606*71d10453SEric Joyner * ice_caps_to_fc_mode 2607*71d10453SEric Joyner * @caps: PHY capabilities 2608*71d10453SEric Joyner * 2609*71d10453SEric Joyner * Convert PHY FC capabilities to ice FC mode 2610*71d10453SEric Joyner */ 2611*71d10453SEric Joyner enum ice_fc_mode ice_caps_to_fc_mode(u8 caps) 2612*71d10453SEric Joyner { 2613*71d10453SEric Joyner if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE && 2614*71d10453SEric Joyner caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 2615*71d10453SEric Joyner return ICE_FC_FULL; 2616*71d10453SEric Joyner 2617*71d10453SEric Joyner if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) 2618*71d10453SEric Joyner return ICE_FC_TX_PAUSE; 2619*71d10453SEric Joyner 2620*71d10453SEric Joyner if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 2621*71d10453SEric Joyner return ICE_FC_RX_PAUSE; 2622*71d10453SEric Joyner 2623*71d10453SEric Joyner return ICE_FC_NONE; 2624*71d10453SEric Joyner } 2625*71d10453SEric Joyner 2626*71d10453SEric Joyner /** 2627*71d10453SEric Joyner * ice_caps_to_fec_mode 2628*71d10453SEric Joyner * @caps: PHY capabilities 2629*71d10453SEric Joyner * @fec_options: Link FEC options 2630*71d10453SEric Joyner * 2631*71d10453SEric Joyner * Convert PHY FEC capabilities to ice FEC mode 2632*71d10453SEric Joyner */ 2633*71d10453SEric Joyner enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options) 2634*71d10453SEric Joyner { 2635*71d10453SEric Joyner if (caps & ICE_AQC_PHY_EN_AUTO_FEC) 2636*71d10453SEric Joyner return ICE_FEC_AUTO; 2637*71d10453SEric Joyner 2638*71d10453SEric Joyner if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN | 2639*71d10453SEric Joyner ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ | 2640*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN | 2641*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_KR_REQ)) 2642*71d10453SEric Joyner return ICE_FEC_BASER; 2643*71d10453SEric Joyner 2644*71d10453SEric Joyner if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ | 2645*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_RS_544_REQ | 2646*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN)) 2647*71d10453SEric Joyner return ICE_FEC_RS; 2648*71d10453SEric Joyner 2649*71d10453SEric Joyner return ICE_FEC_NONE; 2650*71d10453SEric Joyner } 2651*71d10453SEric Joyner 2652*71d10453SEric Joyner /** 2653*71d10453SEric Joyner * ice_set_fc 2654*71d10453SEric Joyner * @pi: port information structure 2655*71d10453SEric Joyner * @aq_failures: pointer to status code, specific to ice_set_fc routine 2656*71d10453SEric Joyner * @ena_auto_link_update: enable automatic link update 2657*71d10453SEric Joyner * 2658*71d10453SEric Joyner * Set the requested flow control mode. 2659*71d10453SEric Joyner */ 2660*71d10453SEric Joyner enum ice_status 2661*71d10453SEric Joyner ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) 2662*71d10453SEric Joyner { 2663*71d10453SEric Joyner struct ice_aqc_set_phy_cfg_data cfg = { 0 }; 2664*71d10453SEric Joyner struct ice_phy_cache_mode_data cache_data; 2665*71d10453SEric Joyner struct ice_aqc_get_phy_caps_data *pcaps; 2666*71d10453SEric Joyner enum ice_status status; 2667*71d10453SEric Joyner u8 pause_mask = 0x0; 2668*71d10453SEric Joyner struct ice_hw *hw; 2669*71d10453SEric Joyner 2670*71d10453SEric Joyner if (!pi || !aq_failures) 2671*71d10453SEric Joyner return ICE_ERR_PARAM; 2672*71d10453SEric Joyner 2673*71d10453SEric Joyner hw = pi->hw; 2674*71d10453SEric Joyner *aq_failures = ICE_SET_FC_AQ_FAIL_NONE; 2675*71d10453SEric Joyner 2676*71d10453SEric Joyner /* Cache user FC request */ 2677*71d10453SEric Joyner cache_data.data.curr_user_fc_req = pi->fc.req_mode; 2678*71d10453SEric Joyner ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE); 2679*71d10453SEric Joyner 2680*71d10453SEric Joyner pcaps = (struct ice_aqc_get_phy_caps_data *) 2681*71d10453SEric Joyner ice_malloc(hw, sizeof(*pcaps)); 2682*71d10453SEric Joyner if (!pcaps) 2683*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 2684*71d10453SEric Joyner 2685*71d10453SEric Joyner switch (pi->fc.req_mode) { 2686*71d10453SEric Joyner case ICE_FC_AUTO: 2687*71d10453SEric Joyner /* Query the value of FC that both the NIC and attached media 2688*71d10453SEric Joyner * can do. 2689*71d10453SEric Joyner */ 2690*71d10453SEric Joyner status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, 2691*71d10453SEric Joyner pcaps, NULL); 2692*71d10453SEric Joyner if (status) { 2693*71d10453SEric Joyner *aq_failures = ICE_SET_FC_AQ_FAIL_GET; 2694*71d10453SEric Joyner goto out; 2695*71d10453SEric Joyner } 2696*71d10453SEric Joyner 2697*71d10453SEric Joyner pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE; 2698*71d10453SEric Joyner pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE; 2699*71d10453SEric Joyner break; 2700*71d10453SEric Joyner case ICE_FC_FULL: 2701*71d10453SEric Joyner pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE; 2702*71d10453SEric Joyner pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE; 2703*71d10453SEric Joyner break; 2704*71d10453SEric Joyner case ICE_FC_RX_PAUSE: 2705*71d10453SEric Joyner pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE; 2706*71d10453SEric Joyner break; 2707*71d10453SEric Joyner case ICE_FC_TX_PAUSE: 2708*71d10453SEric Joyner pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE; 2709*71d10453SEric Joyner break; 2710*71d10453SEric Joyner default: 2711*71d10453SEric Joyner break; 2712*71d10453SEric Joyner } 2713*71d10453SEric Joyner 2714*71d10453SEric Joyner /* Get the current PHY config */ 2715*71d10453SEric Joyner ice_memset(pcaps, 0, sizeof(*pcaps), ICE_NONDMA_MEM); 2716*71d10453SEric Joyner status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 2717*71d10453SEric Joyner NULL); 2718*71d10453SEric Joyner if (status) { 2719*71d10453SEric Joyner *aq_failures = ICE_SET_FC_AQ_FAIL_GET; 2720*71d10453SEric Joyner goto out; 2721*71d10453SEric Joyner } 2722*71d10453SEric Joyner 2723*71d10453SEric Joyner ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg); 2724*71d10453SEric Joyner 2725*71d10453SEric Joyner /* clear the old pause settings */ 2726*71d10453SEric Joyner cfg.caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE | 2727*71d10453SEric Joyner ICE_AQC_PHY_EN_RX_LINK_PAUSE); 2728*71d10453SEric Joyner 2729*71d10453SEric Joyner /* set the new capabilities */ 2730*71d10453SEric Joyner cfg.caps |= pause_mask; 2731*71d10453SEric Joyner 2732*71d10453SEric Joyner /* If the capabilities have changed, then set the new config */ 2733*71d10453SEric Joyner if (cfg.caps != pcaps->caps) { 2734*71d10453SEric Joyner int retry_count, retry_max = 10; 2735*71d10453SEric Joyner 2736*71d10453SEric Joyner /* Auto restart link so settings take effect */ 2737*71d10453SEric Joyner if (ena_auto_link_update) 2738*71d10453SEric Joyner cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 2739*71d10453SEric Joyner 2740*71d10453SEric Joyner status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL); 2741*71d10453SEric Joyner if (status) { 2742*71d10453SEric Joyner *aq_failures = ICE_SET_FC_AQ_FAIL_SET; 2743*71d10453SEric Joyner goto out; 2744*71d10453SEric Joyner } 2745*71d10453SEric Joyner 2746*71d10453SEric Joyner /* Update the link info 2747*71d10453SEric Joyner * It sometimes takes a really long time for link to 2748*71d10453SEric Joyner * come back from the atomic reset. Thus, we wait a 2749*71d10453SEric Joyner * little bit. 2750*71d10453SEric Joyner */ 2751*71d10453SEric Joyner for (retry_count = 0; retry_count < retry_max; retry_count++) { 2752*71d10453SEric Joyner status = ice_update_link_info(pi); 2753*71d10453SEric Joyner 2754*71d10453SEric Joyner if (status == ICE_SUCCESS) 2755*71d10453SEric Joyner break; 2756*71d10453SEric Joyner 2757*71d10453SEric Joyner ice_msec_delay(100, true); 2758*71d10453SEric Joyner } 2759*71d10453SEric Joyner 2760*71d10453SEric Joyner if (status) 2761*71d10453SEric Joyner *aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE; 2762*71d10453SEric Joyner } 2763*71d10453SEric Joyner 2764*71d10453SEric Joyner out: 2765*71d10453SEric Joyner ice_free(hw, pcaps); 2766*71d10453SEric Joyner return status; 2767*71d10453SEric Joyner } 2768*71d10453SEric Joyner 2769*71d10453SEric Joyner /** 2770*71d10453SEric Joyner * ice_phy_caps_equals_cfg 2771*71d10453SEric Joyner * @phy_caps: PHY capabilities 2772*71d10453SEric Joyner * @phy_cfg: PHY configuration 2773*71d10453SEric Joyner * 2774*71d10453SEric Joyner * Helper function to determine if PHY capabilities matches PHY 2775*71d10453SEric Joyner * configuration 2776*71d10453SEric Joyner */ 2777*71d10453SEric Joyner bool 2778*71d10453SEric Joyner ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps, 2779*71d10453SEric Joyner struct ice_aqc_set_phy_cfg_data *phy_cfg) 2780*71d10453SEric Joyner { 2781*71d10453SEric Joyner u8 caps_mask, cfg_mask; 2782*71d10453SEric Joyner 2783*71d10453SEric Joyner if (!phy_caps || !phy_cfg) 2784*71d10453SEric Joyner return false; 2785*71d10453SEric Joyner 2786*71d10453SEric Joyner /* These bits are not common between capabilities and configuration. 2787*71d10453SEric Joyner * Do not use them to determine equality. 2788*71d10453SEric Joyner */ 2789*71d10453SEric Joyner caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE | 2790*71d10453SEric Joyner ICE_AQC_PHY_EN_MOD_QUAL); 2791*71d10453SEric Joyner cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 2792*71d10453SEric Joyner 2793*71d10453SEric Joyner if (phy_caps->phy_type_low != phy_cfg->phy_type_low || 2794*71d10453SEric Joyner phy_caps->phy_type_high != phy_cfg->phy_type_high || 2795*71d10453SEric Joyner ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) || 2796*71d10453SEric Joyner phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an || 2797*71d10453SEric Joyner phy_caps->eee_cap != phy_cfg->eee_cap || 2798*71d10453SEric Joyner phy_caps->eeer_value != phy_cfg->eeer_value || 2799*71d10453SEric Joyner phy_caps->link_fec_options != phy_cfg->link_fec_opt) 2800*71d10453SEric Joyner return false; 2801*71d10453SEric Joyner 2802*71d10453SEric Joyner return true; 2803*71d10453SEric Joyner } 2804*71d10453SEric Joyner 2805*71d10453SEric Joyner /** 2806*71d10453SEric Joyner * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data 2807*71d10453SEric Joyner * @pi: port information structure 2808*71d10453SEric Joyner * @caps: PHY ability structure to copy date from 2809*71d10453SEric Joyner * @cfg: PHY configuration structure to copy data to 2810*71d10453SEric Joyner * 2811*71d10453SEric Joyner * Helper function to copy AQC PHY get ability data to PHY set configuration 2812*71d10453SEric Joyner * data structure 2813*71d10453SEric Joyner */ 2814*71d10453SEric Joyner void 2815*71d10453SEric Joyner ice_copy_phy_caps_to_cfg(struct ice_port_info *pi, 2816*71d10453SEric Joyner struct ice_aqc_get_phy_caps_data *caps, 2817*71d10453SEric Joyner struct ice_aqc_set_phy_cfg_data *cfg) 2818*71d10453SEric Joyner { 2819*71d10453SEric Joyner if (!pi || !caps || !cfg) 2820*71d10453SEric Joyner return; 2821*71d10453SEric Joyner 2822*71d10453SEric Joyner ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM); 2823*71d10453SEric Joyner cfg->phy_type_low = caps->phy_type_low; 2824*71d10453SEric Joyner cfg->phy_type_high = caps->phy_type_high; 2825*71d10453SEric Joyner cfg->caps = caps->caps; 2826*71d10453SEric Joyner cfg->low_power_ctrl_an = caps->low_power_ctrl_an; 2827*71d10453SEric Joyner cfg->eee_cap = caps->eee_cap; 2828*71d10453SEric Joyner cfg->eeer_value = caps->eeer_value; 2829*71d10453SEric Joyner cfg->link_fec_opt = caps->link_fec_options; 2830*71d10453SEric Joyner cfg->module_compliance_enforcement = 2831*71d10453SEric Joyner caps->module_compliance_enforcement; 2832*71d10453SEric Joyner 2833*71d10453SEric Joyner if (ice_fw_supports_link_override(pi->hw)) { 2834*71d10453SEric Joyner struct ice_link_default_override_tlv tlv; 2835*71d10453SEric Joyner 2836*71d10453SEric Joyner if (ice_get_link_default_override(&tlv, pi)) 2837*71d10453SEric Joyner return; 2838*71d10453SEric Joyner 2839*71d10453SEric Joyner if (tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) 2840*71d10453SEric Joyner cfg->module_compliance_enforcement |= 2841*71d10453SEric Joyner ICE_LINK_OVERRIDE_STRICT_MODE; 2842*71d10453SEric Joyner } 2843*71d10453SEric Joyner } 2844*71d10453SEric Joyner 2845*71d10453SEric Joyner /** 2846*71d10453SEric Joyner * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode 2847*71d10453SEric Joyner * @pi: port information structure 2848*71d10453SEric Joyner * @cfg: PHY configuration data to set FEC mode 2849*71d10453SEric Joyner * @fec: FEC mode to configure 2850*71d10453SEric Joyner */ 2851*71d10453SEric Joyner enum ice_status 2852*71d10453SEric Joyner ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg, 2853*71d10453SEric Joyner enum ice_fec_mode fec) 2854*71d10453SEric Joyner { 2855*71d10453SEric Joyner struct ice_aqc_get_phy_caps_data *pcaps; 2856*71d10453SEric Joyner enum ice_status status = ICE_SUCCESS; 2857*71d10453SEric Joyner struct ice_hw *hw; 2858*71d10453SEric Joyner 2859*71d10453SEric Joyner if (!pi || !cfg) 2860*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 2861*71d10453SEric Joyner 2862*71d10453SEric Joyner hw = pi->hw; 2863*71d10453SEric Joyner 2864*71d10453SEric Joyner pcaps = (struct ice_aqc_get_phy_caps_data *) 2865*71d10453SEric Joyner ice_malloc(hw, sizeof(*pcaps)); 2866*71d10453SEric Joyner if (!pcaps) 2867*71d10453SEric Joyner return ICE_ERR_NO_MEMORY; 2868*71d10453SEric Joyner 2869*71d10453SEric Joyner status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps, 2870*71d10453SEric Joyner NULL); 2871*71d10453SEric Joyner if (status) 2872*71d10453SEric Joyner goto out; 2873*71d10453SEric Joyner 2874*71d10453SEric Joyner switch (fec) { 2875*71d10453SEric Joyner case ICE_FEC_BASER: 2876*71d10453SEric Joyner /* Clear RS bits, and AND BASE-R ability 2877*71d10453SEric Joyner * bits and OR request bits. 2878*71d10453SEric Joyner */ 2879*71d10453SEric Joyner cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN | 2880*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN; 2881*71d10453SEric Joyner cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ | 2882*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_KR_REQ; 2883*71d10453SEric Joyner break; 2884*71d10453SEric Joyner case ICE_FEC_RS: 2885*71d10453SEric Joyner /* Clear BASE-R bits, and AND RS ability 2886*71d10453SEric Joyner * bits and OR request bits. 2887*71d10453SEric Joyner */ 2888*71d10453SEric Joyner cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN; 2889*71d10453SEric Joyner cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ | 2890*71d10453SEric Joyner ICE_AQC_PHY_FEC_25G_RS_544_REQ; 2891*71d10453SEric Joyner break; 2892*71d10453SEric Joyner case ICE_FEC_NONE: 2893*71d10453SEric Joyner /* Clear all FEC option bits. */ 2894*71d10453SEric Joyner cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK; 2895*71d10453SEric Joyner break; 2896*71d10453SEric Joyner case ICE_FEC_AUTO: 2897*71d10453SEric Joyner /* AND auto FEC bit, and all caps bits. */ 2898*71d10453SEric Joyner cfg->caps &= ICE_AQC_PHY_CAPS_MASK; 2899*71d10453SEric Joyner cfg->link_fec_opt |= pcaps->link_fec_options; 2900*71d10453SEric Joyner break; 2901*71d10453SEric Joyner default: 2902*71d10453SEric Joyner status = ICE_ERR_PARAM; 2903*71d10453SEric Joyner break; 2904*71d10453SEric Joyner } 2905*71d10453SEric Joyner 2906*71d10453SEric Joyner if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw)) { 2907*71d10453SEric Joyner struct ice_link_default_override_tlv tlv; 2908*71d10453SEric Joyner 2909*71d10453SEric Joyner if (ice_get_link_default_override(&tlv, pi)) 2910*71d10453SEric Joyner goto out; 2911*71d10453SEric Joyner 2912*71d10453SEric Joyner if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && 2913*71d10453SEric Joyner (tlv.options & ICE_LINK_OVERRIDE_EN)) 2914*71d10453SEric Joyner cfg->link_fec_opt = tlv.fec_options; 2915*71d10453SEric Joyner } 2916*71d10453SEric Joyner 2917*71d10453SEric Joyner out: 2918*71d10453SEric Joyner ice_free(hw, pcaps); 2919*71d10453SEric Joyner 2920*71d10453SEric Joyner return status; 2921*71d10453SEric Joyner } 2922*71d10453SEric Joyner 2923*71d10453SEric Joyner /** 2924*71d10453SEric Joyner * ice_get_link_status - get status of the HW network link 2925*71d10453SEric Joyner * @pi: port information structure 2926*71d10453SEric Joyner * @link_up: pointer to bool (true/false = linkup/linkdown) 2927*71d10453SEric Joyner * 2928*71d10453SEric Joyner * Variable link_up is true if link is up, false if link is down. 2929*71d10453SEric Joyner * The variable link_up is invalid if status is non zero. As a 2930*71d10453SEric Joyner * result of this call, link status reporting becomes enabled 2931*71d10453SEric Joyner */ 2932*71d10453SEric Joyner enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up) 2933*71d10453SEric Joyner { 2934*71d10453SEric Joyner struct ice_phy_info *phy_info; 2935*71d10453SEric Joyner enum ice_status status = ICE_SUCCESS; 2936*71d10453SEric Joyner 2937*71d10453SEric Joyner if (!pi || !link_up) 2938*71d10453SEric Joyner return ICE_ERR_PARAM; 2939*71d10453SEric Joyner 2940*71d10453SEric Joyner phy_info = &pi->phy; 2941*71d10453SEric Joyner 2942*71d10453SEric Joyner if (phy_info->get_link_info) { 2943*71d10453SEric Joyner status = ice_update_link_info(pi); 2944*71d10453SEric Joyner 2945*71d10453SEric Joyner if (status) 2946*71d10453SEric Joyner ice_debug(pi->hw, ICE_DBG_LINK, 2947*71d10453SEric Joyner "get link status error, status = %d\n", 2948*71d10453SEric Joyner status); 2949*71d10453SEric Joyner } 2950*71d10453SEric Joyner 2951*71d10453SEric Joyner *link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP; 2952*71d10453SEric Joyner 2953*71d10453SEric Joyner return status; 2954*71d10453SEric Joyner } 2955*71d10453SEric Joyner 2956*71d10453SEric Joyner /** 2957*71d10453SEric Joyner * ice_aq_set_link_restart_an 2958*71d10453SEric Joyner * @pi: pointer to the port information structure 2959*71d10453SEric Joyner * @ena_link: if true: enable link, if false: disable link 2960*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 2961*71d10453SEric Joyner * 2962*71d10453SEric Joyner * Sets up the link and restarts the Auto-Negotiation over the link. 2963*71d10453SEric Joyner */ 2964*71d10453SEric Joyner enum ice_status 2965*71d10453SEric Joyner ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link, 2966*71d10453SEric Joyner struct ice_sq_cd *cd) 2967*71d10453SEric Joyner { 2968*71d10453SEric Joyner struct ice_aqc_restart_an *cmd; 2969*71d10453SEric Joyner struct ice_aq_desc desc; 2970*71d10453SEric Joyner 2971*71d10453SEric Joyner cmd = &desc.params.restart_an; 2972*71d10453SEric Joyner 2973*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an); 2974*71d10453SEric Joyner 2975*71d10453SEric Joyner cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART; 2976*71d10453SEric Joyner cmd->lport_num = pi->lport; 2977*71d10453SEric Joyner if (ena_link) 2978*71d10453SEric Joyner cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE; 2979*71d10453SEric Joyner else 2980*71d10453SEric Joyner cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE; 2981*71d10453SEric Joyner 2982*71d10453SEric Joyner return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd); 2983*71d10453SEric Joyner } 2984*71d10453SEric Joyner 2985*71d10453SEric Joyner /** 2986*71d10453SEric Joyner * ice_aq_set_event_mask 2987*71d10453SEric Joyner * @hw: pointer to the HW struct 2988*71d10453SEric Joyner * @port_num: port number of the physical function 2989*71d10453SEric Joyner * @mask: event mask to be set 2990*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 2991*71d10453SEric Joyner * 2992*71d10453SEric Joyner * Set event mask (0x0613) 2993*71d10453SEric Joyner */ 2994*71d10453SEric Joyner enum ice_status 2995*71d10453SEric Joyner ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask, 2996*71d10453SEric Joyner struct ice_sq_cd *cd) 2997*71d10453SEric Joyner { 2998*71d10453SEric Joyner struct ice_aqc_set_event_mask *cmd; 2999*71d10453SEric Joyner struct ice_aq_desc desc; 3000*71d10453SEric Joyner 3001*71d10453SEric Joyner cmd = &desc.params.set_event_mask; 3002*71d10453SEric Joyner 3003*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask); 3004*71d10453SEric Joyner 3005*71d10453SEric Joyner cmd->lport_num = port_num; 3006*71d10453SEric Joyner 3007*71d10453SEric Joyner cmd->event_mask = CPU_TO_LE16(mask); 3008*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 3009*71d10453SEric Joyner } 3010*71d10453SEric Joyner 3011*71d10453SEric Joyner /** 3012*71d10453SEric Joyner * ice_aq_set_mac_loopback 3013*71d10453SEric Joyner * @hw: pointer to the HW struct 3014*71d10453SEric Joyner * @ena_lpbk: Enable or Disable loopback 3015*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 3016*71d10453SEric Joyner * 3017*71d10453SEric Joyner * Enable/disable loopback on a given port 3018*71d10453SEric Joyner */ 3019*71d10453SEric Joyner enum ice_status 3020*71d10453SEric Joyner ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd) 3021*71d10453SEric Joyner { 3022*71d10453SEric Joyner struct ice_aqc_set_mac_lb *cmd; 3023*71d10453SEric Joyner struct ice_aq_desc desc; 3024*71d10453SEric Joyner 3025*71d10453SEric Joyner cmd = &desc.params.set_mac_lb; 3026*71d10453SEric Joyner 3027*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb); 3028*71d10453SEric Joyner if (ena_lpbk) 3029*71d10453SEric Joyner cmd->lb_mode = ICE_AQ_MAC_LB_EN; 3030*71d10453SEric Joyner 3031*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 3032*71d10453SEric Joyner } 3033*71d10453SEric Joyner 3034*71d10453SEric Joyner /** 3035*71d10453SEric Joyner * ice_aq_set_port_id_led 3036*71d10453SEric Joyner * @pi: pointer to the port information 3037*71d10453SEric Joyner * @is_orig_mode: is this LED set to original mode (by the net-list) 3038*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 3039*71d10453SEric Joyner * 3040*71d10453SEric Joyner * Set LED value for the given port (0x06e9) 3041*71d10453SEric Joyner */ 3042*71d10453SEric Joyner enum ice_status 3043*71d10453SEric Joyner ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode, 3044*71d10453SEric Joyner struct ice_sq_cd *cd) 3045*71d10453SEric Joyner { 3046*71d10453SEric Joyner struct ice_aqc_set_port_id_led *cmd; 3047*71d10453SEric Joyner struct ice_hw *hw = pi->hw; 3048*71d10453SEric Joyner struct ice_aq_desc desc; 3049*71d10453SEric Joyner 3050*71d10453SEric Joyner cmd = &desc.params.set_port_id_led; 3051*71d10453SEric Joyner 3052*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led); 3053*71d10453SEric Joyner 3054*71d10453SEric Joyner if (is_orig_mode) 3055*71d10453SEric Joyner cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG; 3056*71d10453SEric Joyner else 3057*71d10453SEric Joyner cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK; 3058*71d10453SEric Joyner 3059*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 3060*71d10453SEric Joyner } 3061*71d10453SEric Joyner 3062*71d10453SEric Joyner /** 3063*71d10453SEric Joyner * ice_aq_sff_eeprom 3064*71d10453SEric Joyner * @hw: pointer to the HW struct 3065*71d10453SEric Joyner * @lport: bits [7:0] = logical port, bit [8] = logical port valid 3066*71d10453SEric Joyner * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default) 3067*71d10453SEric Joyner * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding. 3068*71d10453SEric Joyner * @page: QSFP page 3069*71d10453SEric Joyner * @set_page: set or ignore the page 3070*71d10453SEric Joyner * @data: pointer to data buffer to be read/written to the I2C device. 3071*71d10453SEric Joyner * @length: 1-16 for read, 1 for write. 3072*71d10453SEric Joyner * @write: 0 read, 1 for write. 3073*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 3074*71d10453SEric Joyner * 3075*71d10453SEric Joyner * Read/Write SFF EEPROM (0x06EE) 3076*71d10453SEric Joyner */ 3077*71d10453SEric Joyner enum ice_status 3078*71d10453SEric Joyner ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr, 3079*71d10453SEric Joyner u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length, 3080*71d10453SEric Joyner bool write, struct ice_sq_cd *cd) 3081*71d10453SEric Joyner { 3082*71d10453SEric Joyner struct ice_aqc_sff_eeprom *cmd; 3083*71d10453SEric Joyner struct ice_aq_desc desc; 3084*71d10453SEric Joyner enum ice_status status; 3085*71d10453SEric Joyner 3086*71d10453SEric Joyner if (!data || (mem_addr & 0xff00)) 3087*71d10453SEric Joyner return ICE_ERR_PARAM; 3088*71d10453SEric Joyner 3089*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom); 3090*71d10453SEric Joyner cmd = &desc.params.read_write_sff_param; 3091*71d10453SEric Joyner desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD | ICE_AQ_FLAG_BUF); 3092*71d10453SEric Joyner cmd->lport_num = (u8)(lport & 0xff); 3093*71d10453SEric Joyner cmd->lport_num_valid = (u8)((lport >> 8) & 0x01); 3094*71d10453SEric Joyner cmd->i2c_bus_addr = CPU_TO_LE16(((bus_addr >> 1) & 3095*71d10453SEric Joyner ICE_AQC_SFF_I2CBUS_7BIT_M) | 3096*71d10453SEric Joyner ((set_page << 3097*71d10453SEric Joyner ICE_AQC_SFF_SET_EEPROM_PAGE_S) & 3098*71d10453SEric Joyner ICE_AQC_SFF_SET_EEPROM_PAGE_M)); 3099*71d10453SEric Joyner cmd->i2c_mem_addr = CPU_TO_LE16(mem_addr & 0xff); 3100*71d10453SEric Joyner cmd->eeprom_page = CPU_TO_LE16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S); 3101*71d10453SEric Joyner if (write) 3102*71d10453SEric Joyner cmd->i2c_bus_addr |= CPU_TO_LE16(ICE_AQC_SFF_IS_WRITE); 3103*71d10453SEric Joyner 3104*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, data, length, cd); 3105*71d10453SEric Joyner return status; 3106*71d10453SEric Joyner } 3107*71d10453SEric Joyner 3108*71d10453SEric Joyner /** 3109*71d10453SEric Joyner * __ice_aq_get_set_rss_lut 3110*71d10453SEric Joyner * @hw: pointer to the hardware structure 3111*71d10453SEric Joyner * @vsi_id: VSI FW index 3112*71d10453SEric Joyner * @lut_type: LUT table type 3113*71d10453SEric Joyner * @lut: pointer to the LUT buffer provided by the caller 3114*71d10453SEric Joyner * @lut_size: size of the LUT buffer 3115*71d10453SEric Joyner * @glob_lut_idx: global LUT index 3116*71d10453SEric Joyner * @set: set true to set the table, false to get the table 3117*71d10453SEric Joyner * 3118*71d10453SEric Joyner * Internal function to get (0x0B05) or set (0x0B03) RSS look up table 3119*71d10453SEric Joyner */ 3120*71d10453SEric Joyner static enum ice_status 3121*71d10453SEric Joyner __ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut, 3122*71d10453SEric Joyner u16 lut_size, u8 glob_lut_idx, bool set) 3123*71d10453SEric Joyner { 3124*71d10453SEric Joyner struct ice_aqc_get_set_rss_lut *cmd_resp; 3125*71d10453SEric Joyner struct ice_aq_desc desc; 3126*71d10453SEric Joyner enum ice_status status; 3127*71d10453SEric Joyner u16 flags = 0; 3128*71d10453SEric Joyner 3129*71d10453SEric Joyner cmd_resp = &desc.params.get_set_rss_lut; 3130*71d10453SEric Joyner 3131*71d10453SEric Joyner if (set) { 3132*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut); 3133*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 3134*71d10453SEric Joyner } else { 3135*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut); 3136*71d10453SEric Joyner } 3137*71d10453SEric Joyner 3138*71d10453SEric Joyner cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id << 3139*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_VSI_ID_S) & 3140*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_VSI_ID_M) | 3141*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_VSI_VALID); 3142*71d10453SEric Joyner 3143*71d10453SEric Joyner switch (lut_type) { 3144*71d10453SEric Joyner case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI: 3145*71d10453SEric Joyner case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF: 3146*71d10453SEric Joyner case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL: 3147*71d10453SEric Joyner flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) & 3148*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M); 3149*71d10453SEric Joyner break; 3150*71d10453SEric Joyner default: 3151*71d10453SEric Joyner status = ICE_ERR_PARAM; 3152*71d10453SEric Joyner goto ice_aq_get_set_rss_lut_exit; 3153*71d10453SEric Joyner } 3154*71d10453SEric Joyner 3155*71d10453SEric Joyner if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) { 3156*71d10453SEric Joyner flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) & 3157*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M); 3158*71d10453SEric Joyner 3159*71d10453SEric Joyner if (!set) 3160*71d10453SEric Joyner goto ice_aq_get_set_rss_lut_send; 3161*71d10453SEric Joyner } else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { 3162*71d10453SEric Joyner if (!set) 3163*71d10453SEric Joyner goto ice_aq_get_set_rss_lut_send; 3164*71d10453SEric Joyner } else { 3165*71d10453SEric Joyner goto ice_aq_get_set_rss_lut_send; 3166*71d10453SEric Joyner } 3167*71d10453SEric Joyner 3168*71d10453SEric Joyner /* LUT size is only valid for Global and PF table types */ 3169*71d10453SEric Joyner switch (lut_size) { 3170*71d10453SEric Joyner case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128: 3171*71d10453SEric Joyner flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG << 3172*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & 3173*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; 3174*71d10453SEric Joyner break; 3175*71d10453SEric Joyner case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512: 3176*71d10453SEric Joyner flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG << 3177*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & 3178*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; 3179*71d10453SEric Joyner break; 3180*71d10453SEric Joyner case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K: 3181*71d10453SEric Joyner if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { 3182*71d10453SEric Joyner flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG << 3183*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & 3184*71d10453SEric Joyner ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; 3185*71d10453SEric Joyner break; 3186*71d10453SEric Joyner } 3187*71d10453SEric Joyner /* fall-through */ 3188*71d10453SEric Joyner default: 3189*71d10453SEric Joyner status = ICE_ERR_PARAM; 3190*71d10453SEric Joyner goto ice_aq_get_set_rss_lut_exit; 3191*71d10453SEric Joyner } 3192*71d10453SEric Joyner 3193*71d10453SEric Joyner ice_aq_get_set_rss_lut_send: 3194*71d10453SEric Joyner cmd_resp->flags = CPU_TO_LE16(flags); 3195*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL); 3196*71d10453SEric Joyner 3197*71d10453SEric Joyner ice_aq_get_set_rss_lut_exit: 3198*71d10453SEric Joyner return status; 3199*71d10453SEric Joyner } 3200*71d10453SEric Joyner 3201*71d10453SEric Joyner /** 3202*71d10453SEric Joyner * ice_aq_get_rss_lut 3203*71d10453SEric Joyner * @hw: pointer to the hardware structure 3204*71d10453SEric Joyner * @vsi_handle: software VSI handle 3205*71d10453SEric Joyner * @lut_type: LUT table type 3206*71d10453SEric Joyner * @lut: pointer to the LUT buffer provided by the caller 3207*71d10453SEric Joyner * @lut_size: size of the LUT buffer 3208*71d10453SEric Joyner * 3209*71d10453SEric Joyner * get the RSS lookup table, PF or VSI type 3210*71d10453SEric Joyner */ 3211*71d10453SEric Joyner enum ice_status 3212*71d10453SEric Joyner ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type, 3213*71d10453SEric Joyner u8 *lut, u16 lut_size) 3214*71d10453SEric Joyner { 3215*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) 3216*71d10453SEric Joyner return ICE_ERR_PARAM; 3217*71d10453SEric Joyner 3218*71d10453SEric Joyner return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle), 3219*71d10453SEric Joyner lut_type, lut, lut_size, 0, false); 3220*71d10453SEric Joyner } 3221*71d10453SEric Joyner 3222*71d10453SEric Joyner /** 3223*71d10453SEric Joyner * ice_aq_set_rss_lut 3224*71d10453SEric Joyner * @hw: pointer to the hardware structure 3225*71d10453SEric Joyner * @vsi_handle: software VSI handle 3226*71d10453SEric Joyner * @lut_type: LUT table type 3227*71d10453SEric Joyner * @lut: pointer to the LUT buffer provided by the caller 3228*71d10453SEric Joyner * @lut_size: size of the LUT buffer 3229*71d10453SEric Joyner * 3230*71d10453SEric Joyner * set the RSS lookup table, PF or VSI type 3231*71d10453SEric Joyner */ 3232*71d10453SEric Joyner enum ice_status 3233*71d10453SEric Joyner ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type, 3234*71d10453SEric Joyner u8 *lut, u16 lut_size) 3235*71d10453SEric Joyner { 3236*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) 3237*71d10453SEric Joyner return ICE_ERR_PARAM; 3238*71d10453SEric Joyner 3239*71d10453SEric Joyner return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle), 3240*71d10453SEric Joyner lut_type, lut, lut_size, 0, true); 3241*71d10453SEric Joyner } 3242*71d10453SEric Joyner 3243*71d10453SEric Joyner /** 3244*71d10453SEric Joyner * __ice_aq_get_set_rss_key 3245*71d10453SEric Joyner * @hw: pointer to the HW struct 3246*71d10453SEric Joyner * @vsi_id: VSI FW index 3247*71d10453SEric Joyner * @key: pointer to key info struct 3248*71d10453SEric Joyner * @set: set true to set the key, false to get the key 3249*71d10453SEric Joyner * 3250*71d10453SEric Joyner * get (0x0B04) or set (0x0B02) the RSS key per VSI 3251*71d10453SEric Joyner */ 3252*71d10453SEric Joyner static enum 3253*71d10453SEric Joyner ice_status __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id, 3254*71d10453SEric Joyner struct ice_aqc_get_set_rss_keys *key, 3255*71d10453SEric Joyner bool set) 3256*71d10453SEric Joyner { 3257*71d10453SEric Joyner struct ice_aqc_get_set_rss_key *cmd_resp; 3258*71d10453SEric Joyner u16 key_size = sizeof(*key); 3259*71d10453SEric Joyner struct ice_aq_desc desc; 3260*71d10453SEric Joyner 3261*71d10453SEric Joyner cmd_resp = &desc.params.get_set_rss_key; 3262*71d10453SEric Joyner 3263*71d10453SEric Joyner if (set) { 3264*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key); 3265*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 3266*71d10453SEric Joyner } else { 3267*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key); 3268*71d10453SEric Joyner } 3269*71d10453SEric Joyner 3270*71d10453SEric Joyner cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id << 3271*71d10453SEric Joyner ICE_AQC_GSET_RSS_KEY_VSI_ID_S) & 3272*71d10453SEric Joyner ICE_AQC_GSET_RSS_KEY_VSI_ID_M) | 3273*71d10453SEric Joyner ICE_AQC_GSET_RSS_KEY_VSI_VALID); 3274*71d10453SEric Joyner 3275*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, key, key_size, NULL); 3276*71d10453SEric Joyner } 3277*71d10453SEric Joyner 3278*71d10453SEric Joyner /** 3279*71d10453SEric Joyner * ice_aq_get_rss_key 3280*71d10453SEric Joyner * @hw: pointer to the HW struct 3281*71d10453SEric Joyner * @vsi_handle: software VSI handle 3282*71d10453SEric Joyner * @key: pointer to key info struct 3283*71d10453SEric Joyner * 3284*71d10453SEric Joyner * get the RSS key per VSI 3285*71d10453SEric Joyner */ 3286*71d10453SEric Joyner enum ice_status 3287*71d10453SEric Joyner ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle, 3288*71d10453SEric Joyner struct ice_aqc_get_set_rss_keys *key) 3289*71d10453SEric Joyner { 3290*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || !key) 3291*71d10453SEric Joyner return ICE_ERR_PARAM; 3292*71d10453SEric Joyner 3293*71d10453SEric Joyner return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle), 3294*71d10453SEric Joyner key, false); 3295*71d10453SEric Joyner } 3296*71d10453SEric Joyner 3297*71d10453SEric Joyner /** 3298*71d10453SEric Joyner * ice_aq_set_rss_key 3299*71d10453SEric Joyner * @hw: pointer to the HW struct 3300*71d10453SEric Joyner * @vsi_handle: software VSI handle 3301*71d10453SEric Joyner * @keys: pointer to key info struct 3302*71d10453SEric Joyner * 3303*71d10453SEric Joyner * set the RSS key per VSI 3304*71d10453SEric Joyner */ 3305*71d10453SEric Joyner enum ice_status 3306*71d10453SEric Joyner ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle, 3307*71d10453SEric Joyner struct ice_aqc_get_set_rss_keys *keys) 3308*71d10453SEric Joyner { 3309*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || !keys) 3310*71d10453SEric Joyner return ICE_ERR_PARAM; 3311*71d10453SEric Joyner 3312*71d10453SEric Joyner return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle), 3313*71d10453SEric Joyner keys, true); 3314*71d10453SEric Joyner } 3315*71d10453SEric Joyner 3316*71d10453SEric Joyner /** 3317*71d10453SEric Joyner * ice_aq_add_lan_txq 3318*71d10453SEric Joyner * @hw: pointer to the hardware structure 3319*71d10453SEric Joyner * @num_qgrps: Number of added queue groups 3320*71d10453SEric Joyner * @qg_list: list of queue groups to be added 3321*71d10453SEric Joyner * @buf_size: size of buffer for indirect command 3322*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 3323*71d10453SEric Joyner * 3324*71d10453SEric Joyner * Add Tx LAN queue (0x0C30) 3325*71d10453SEric Joyner * 3326*71d10453SEric Joyner * NOTE: 3327*71d10453SEric Joyner * Prior to calling add Tx LAN queue: 3328*71d10453SEric Joyner * Initialize the following as part of the Tx queue context: 3329*71d10453SEric Joyner * Completion queue ID if the queue uses Completion queue, Quanta profile, 3330*71d10453SEric Joyner * Cache profile and Packet shaper profile. 3331*71d10453SEric Joyner * 3332*71d10453SEric Joyner * After add Tx LAN queue AQ command is completed: 3333*71d10453SEric Joyner * Interrupts should be associated with specific queues, 3334*71d10453SEric Joyner * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue 3335*71d10453SEric Joyner * flow. 3336*71d10453SEric Joyner */ 3337*71d10453SEric Joyner enum ice_status 3338*71d10453SEric Joyner ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps, 3339*71d10453SEric Joyner struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size, 3340*71d10453SEric Joyner struct ice_sq_cd *cd) 3341*71d10453SEric Joyner { 3342*71d10453SEric Joyner u16 i, sum_header_size, sum_q_size = 0; 3343*71d10453SEric Joyner struct ice_aqc_add_tx_qgrp *list; 3344*71d10453SEric Joyner struct ice_aqc_add_txqs *cmd; 3345*71d10453SEric Joyner struct ice_aq_desc desc; 3346*71d10453SEric Joyner 3347*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3348*71d10453SEric Joyner 3349*71d10453SEric Joyner cmd = &desc.params.add_txqs; 3350*71d10453SEric Joyner 3351*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs); 3352*71d10453SEric Joyner 3353*71d10453SEric Joyner if (!qg_list) 3354*71d10453SEric Joyner return ICE_ERR_PARAM; 3355*71d10453SEric Joyner 3356*71d10453SEric Joyner if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS) 3357*71d10453SEric Joyner return ICE_ERR_PARAM; 3358*71d10453SEric Joyner 3359*71d10453SEric Joyner sum_header_size = num_qgrps * 3360*71d10453SEric Joyner (sizeof(*qg_list) - sizeof(*qg_list->txqs)); 3361*71d10453SEric Joyner 3362*71d10453SEric Joyner list = qg_list; 3363*71d10453SEric Joyner for (i = 0; i < num_qgrps; i++) { 3364*71d10453SEric Joyner struct ice_aqc_add_txqs_perq *q = list->txqs; 3365*71d10453SEric Joyner 3366*71d10453SEric Joyner sum_q_size += list->num_txqs * sizeof(*q); 3367*71d10453SEric Joyner list = (struct ice_aqc_add_tx_qgrp *)(q + list->num_txqs); 3368*71d10453SEric Joyner } 3369*71d10453SEric Joyner 3370*71d10453SEric Joyner if (buf_size != (sum_header_size + sum_q_size)) 3371*71d10453SEric Joyner return ICE_ERR_PARAM; 3372*71d10453SEric Joyner 3373*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 3374*71d10453SEric Joyner 3375*71d10453SEric Joyner cmd->num_qgrps = num_qgrps; 3376*71d10453SEric Joyner 3377*71d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); 3378*71d10453SEric Joyner } 3379*71d10453SEric Joyner 3380*71d10453SEric Joyner /** 3381*71d10453SEric Joyner * ice_aq_dis_lan_txq 3382*71d10453SEric Joyner * @hw: pointer to the hardware structure 3383*71d10453SEric Joyner * @num_qgrps: number of groups in the list 3384*71d10453SEric Joyner * @qg_list: the list of groups to disable 3385*71d10453SEric Joyner * @buf_size: the total size of the qg_list buffer in bytes 3386*71d10453SEric Joyner * @rst_src: if called due to reset, specifies the reset source 3387*71d10453SEric Joyner * @vmvf_num: the relative VM or VF number that is undergoing the reset 3388*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 3389*71d10453SEric Joyner * 3390*71d10453SEric Joyner * Disable LAN Tx queue (0x0C31) 3391*71d10453SEric Joyner */ 3392*71d10453SEric Joyner static enum ice_status 3393*71d10453SEric Joyner ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, 3394*71d10453SEric Joyner struct ice_aqc_dis_txq_item *qg_list, u16 buf_size, 3395*71d10453SEric Joyner enum ice_disq_rst_src rst_src, u16 vmvf_num, 3396*71d10453SEric Joyner struct ice_sq_cd *cd) 3397*71d10453SEric Joyner { 3398*71d10453SEric Joyner struct ice_aqc_dis_txqs *cmd; 3399*71d10453SEric Joyner struct ice_aq_desc desc; 3400*71d10453SEric Joyner enum ice_status status; 3401*71d10453SEric Joyner u16 i, sz = 0; 3402*71d10453SEric Joyner 3403*71d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3404*71d10453SEric Joyner cmd = &desc.params.dis_txqs; 3405*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs); 3406*71d10453SEric Joyner 3407*71d10453SEric Joyner /* qg_list can be NULL only in VM/VF reset flow */ 3408*71d10453SEric Joyner if (!qg_list && !rst_src) 3409*71d10453SEric Joyner return ICE_ERR_PARAM; 3410*71d10453SEric Joyner 3411*71d10453SEric Joyner if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS) 3412*71d10453SEric Joyner return ICE_ERR_PARAM; 3413*71d10453SEric Joyner 3414*71d10453SEric Joyner cmd->num_entries = num_qgrps; 3415*71d10453SEric Joyner 3416*71d10453SEric Joyner cmd->vmvf_and_timeout = CPU_TO_LE16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) & 3417*71d10453SEric Joyner ICE_AQC_Q_DIS_TIMEOUT_M); 3418*71d10453SEric Joyner 3419*71d10453SEric Joyner switch (rst_src) { 3420*71d10453SEric Joyner case ICE_VM_RESET: 3421*71d10453SEric Joyner cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET; 3422*71d10453SEric Joyner cmd->vmvf_and_timeout |= 3423*71d10453SEric Joyner CPU_TO_LE16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M); 3424*71d10453SEric Joyner break; 3425*71d10453SEric Joyner case ICE_VF_RESET: 3426*71d10453SEric Joyner cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET; 3427*71d10453SEric Joyner /* In this case, FW expects vmvf_num to be absolute VF ID */ 3428*71d10453SEric Joyner cmd->vmvf_and_timeout |= 3429*71d10453SEric Joyner CPU_TO_LE16((vmvf_num + hw->func_caps.vf_base_id) & 3430*71d10453SEric Joyner ICE_AQC_Q_DIS_VMVF_NUM_M); 3431*71d10453SEric Joyner break; 3432*71d10453SEric Joyner case ICE_NO_RESET: 3433*71d10453SEric Joyner default: 3434*71d10453SEric Joyner break; 3435*71d10453SEric Joyner } 3436*71d10453SEric Joyner 3437*71d10453SEric Joyner /* flush pipe on time out */ 3438*71d10453SEric Joyner cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE; 3439*71d10453SEric Joyner /* If no queue group info, we are in a reset flow. Issue the AQ */ 3440*71d10453SEric Joyner if (!qg_list) 3441*71d10453SEric Joyner goto do_aq; 3442*71d10453SEric Joyner 3443*71d10453SEric Joyner /* set RD bit to indicate that command buffer is provided by the driver 3444*71d10453SEric Joyner * and it needs to be read by the firmware 3445*71d10453SEric Joyner */ 3446*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 3447*71d10453SEric Joyner 3448*71d10453SEric Joyner for (i = 0; i < num_qgrps; ++i) { 3449*71d10453SEric Joyner /* Calculate the size taken up by the queue IDs in this group */ 3450*71d10453SEric Joyner sz += qg_list[i].num_qs * sizeof(qg_list[i].q_id); 3451*71d10453SEric Joyner 3452*71d10453SEric Joyner /* Add the size of the group header */ 3453*71d10453SEric Joyner sz += sizeof(qg_list[i]) - sizeof(qg_list[i].q_id); 3454*71d10453SEric Joyner 3455*71d10453SEric Joyner /* If the num of queues is even, add 2 bytes of padding */ 3456*71d10453SEric Joyner if ((qg_list[i].num_qs % 2) == 0) 3457*71d10453SEric Joyner sz += 2; 3458*71d10453SEric Joyner } 3459*71d10453SEric Joyner 3460*71d10453SEric Joyner if (buf_size != sz) 3461*71d10453SEric Joyner return ICE_ERR_PARAM; 3462*71d10453SEric Joyner 3463*71d10453SEric Joyner do_aq: 3464*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); 3465*71d10453SEric Joyner if (status) { 3466*71d10453SEric Joyner if (!qg_list) 3467*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n", 3468*71d10453SEric Joyner vmvf_num, hw->adminq.sq_last_status); 3469*71d10453SEric Joyner else 3470*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n", 3471*71d10453SEric Joyner LE16_TO_CPU(qg_list[0].q_id[0]), 3472*71d10453SEric Joyner hw->adminq.sq_last_status); 3473*71d10453SEric Joyner } 3474*71d10453SEric Joyner return status; 3475*71d10453SEric Joyner } 3476*71d10453SEric Joyner 3477*71d10453SEric Joyner /** 3478*71d10453SEric Joyner * ice_aq_move_recfg_lan_txq 3479*71d10453SEric Joyner * @hw: pointer to the hardware structure 3480*71d10453SEric Joyner * @num_qs: number of queues to move/reconfigure 3481*71d10453SEric Joyner * @is_move: true if this operation involves node movement 3482*71d10453SEric Joyner * @is_tc_change: true if this operation involves a TC change 3483*71d10453SEric Joyner * @subseq_call: true if this operation is a subsequent call 3484*71d10453SEric Joyner * @flush_pipe: on timeout, true to flush pipe, false to return EAGAIN 3485*71d10453SEric Joyner * @timeout: timeout in units of 100 usec (valid values 0-50) 3486*71d10453SEric Joyner * @blocked_cgds: out param, bitmap of CGDs that timed out if returning EAGAIN 3487*71d10453SEric Joyner * @buf: struct containing src/dest TEID and per-queue info 3488*71d10453SEric Joyner * @buf_size: size of buffer for indirect command 3489*71d10453SEric Joyner * @txqs_moved: out param, number of queues successfully moved 3490*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 3491*71d10453SEric Joyner * 3492*71d10453SEric Joyner * Move / Reconfigure Tx LAN queues (0x0C32) 3493*71d10453SEric Joyner */ 3494*71d10453SEric Joyner enum ice_status 3495*71d10453SEric Joyner ice_aq_move_recfg_lan_txq(struct ice_hw *hw, u8 num_qs, bool is_move, 3496*71d10453SEric Joyner bool is_tc_change, bool subseq_call, bool flush_pipe, 3497*71d10453SEric Joyner u8 timeout, u32 *blocked_cgds, 3498*71d10453SEric Joyner struct ice_aqc_move_txqs_data *buf, u16 buf_size, 3499*71d10453SEric Joyner u8 *txqs_moved, struct ice_sq_cd *cd) 3500*71d10453SEric Joyner { 3501*71d10453SEric Joyner struct ice_aqc_move_txqs *cmd; 3502*71d10453SEric Joyner struct ice_aq_desc desc; 3503*71d10453SEric Joyner enum ice_status status; 3504*71d10453SEric Joyner 3505*71d10453SEric Joyner cmd = &desc.params.move_txqs; 3506*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_move_recfg_txqs); 3507*71d10453SEric Joyner 3508*71d10453SEric Joyner #define ICE_LAN_TXQ_MOVE_TIMEOUT_MAX 50 3509*71d10453SEric Joyner if (timeout > ICE_LAN_TXQ_MOVE_TIMEOUT_MAX) 3510*71d10453SEric Joyner return ICE_ERR_PARAM; 3511*71d10453SEric Joyner 3512*71d10453SEric Joyner if (is_tc_change && !flush_pipe && !blocked_cgds) 3513*71d10453SEric Joyner return ICE_ERR_PARAM; 3514*71d10453SEric Joyner 3515*71d10453SEric Joyner if (!is_move && !is_tc_change) 3516*71d10453SEric Joyner return ICE_ERR_PARAM; 3517*71d10453SEric Joyner 3518*71d10453SEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 3519*71d10453SEric Joyner 3520*71d10453SEric Joyner if (is_move) 3521*71d10453SEric Joyner cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_MOVE; 3522*71d10453SEric Joyner 3523*71d10453SEric Joyner if (is_tc_change) 3524*71d10453SEric Joyner cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_TC_CHANGE; 3525*71d10453SEric Joyner 3526*71d10453SEric Joyner if (subseq_call) 3527*71d10453SEric Joyner cmd->cmd_type |= ICE_AQC_Q_CMD_SUBSEQ_CALL; 3528*71d10453SEric Joyner 3529*71d10453SEric Joyner if (flush_pipe) 3530*71d10453SEric Joyner cmd->cmd_type |= ICE_AQC_Q_CMD_FLUSH_PIPE; 3531*71d10453SEric Joyner 3532*71d10453SEric Joyner cmd->num_qs = num_qs; 3533*71d10453SEric Joyner cmd->timeout = ((timeout << ICE_AQC_Q_CMD_TIMEOUT_S) & 3534*71d10453SEric Joyner ICE_AQC_Q_CMD_TIMEOUT_M); 3535*71d10453SEric Joyner 3536*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 3537*71d10453SEric Joyner 3538*71d10453SEric Joyner if (!status && txqs_moved) 3539*71d10453SEric Joyner *txqs_moved = cmd->num_qs; 3540*71d10453SEric Joyner 3541*71d10453SEric Joyner if (hw->adminq.sq_last_status == ICE_AQ_RC_EAGAIN && 3542*71d10453SEric Joyner is_tc_change && !flush_pipe) 3543*71d10453SEric Joyner *blocked_cgds = LE32_TO_CPU(cmd->blocked_cgds); 3544*71d10453SEric Joyner 3545*71d10453SEric Joyner return status; 3546*71d10453SEric Joyner } 3547*71d10453SEric Joyner 3548*71d10453SEric Joyner /* End of FW Admin Queue command wrappers */ 3549*71d10453SEric Joyner 3550*71d10453SEric Joyner /** 3551*71d10453SEric Joyner * ice_write_byte - write a byte to a packed context structure 3552*71d10453SEric Joyner * @src_ctx: the context structure to read from 3553*71d10453SEric Joyner * @dest_ctx: the context to be written to 3554*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3555*71d10453SEric Joyner */ 3556*71d10453SEric Joyner static void 3557*71d10453SEric Joyner ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 3558*71d10453SEric Joyner { 3559*71d10453SEric Joyner u8 src_byte, dest_byte, mask; 3560*71d10453SEric Joyner u8 *from, *dest; 3561*71d10453SEric Joyner u16 shift_width; 3562*71d10453SEric Joyner 3563*71d10453SEric Joyner /* copy from the next struct field */ 3564*71d10453SEric Joyner from = src_ctx + ce_info->offset; 3565*71d10453SEric Joyner 3566*71d10453SEric Joyner /* prepare the bits and mask */ 3567*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3568*71d10453SEric Joyner mask = (u8)(BIT(ce_info->width) - 1); 3569*71d10453SEric Joyner 3570*71d10453SEric Joyner src_byte = *from; 3571*71d10453SEric Joyner src_byte &= mask; 3572*71d10453SEric Joyner 3573*71d10453SEric Joyner /* shift to correct alignment */ 3574*71d10453SEric Joyner mask <<= shift_width; 3575*71d10453SEric Joyner src_byte <<= shift_width; 3576*71d10453SEric Joyner 3577*71d10453SEric Joyner /* get the current bits from the target bit string */ 3578*71d10453SEric Joyner dest = dest_ctx + (ce_info->lsb / 8); 3579*71d10453SEric Joyner 3580*71d10453SEric Joyner ice_memcpy(&dest_byte, dest, sizeof(dest_byte), ICE_DMA_TO_NONDMA); 3581*71d10453SEric Joyner 3582*71d10453SEric Joyner dest_byte &= ~mask; /* get the bits not changing */ 3583*71d10453SEric Joyner dest_byte |= src_byte; /* add in the new bits */ 3584*71d10453SEric Joyner 3585*71d10453SEric Joyner /* put it all back */ 3586*71d10453SEric Joyner ice_memcpy(dest, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA); 3587*71d10453SEric Joyner } 3588*71d10453SEric Joyner 3589*71d10453SEric Joyner /** 3590*71d10453SEric Joyner * ice_write_word - write a word to a packed context structure 3591*71d10453SEric Joyner * @src_ctx: the context structure to read from 3592*71d10453SEric Joyner * @dest_ctx: the context to be written to 3593*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3594*71d10453SEric Joyner */ 3595*71d10453SEric Joyner static void 3596*71d10453SEric Joyner ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 3597*71d10453SEric Joyner { 3598*71d10453SEric Joyner u16 src_word, mask; 3599*71d10453SEric Joyner __le16 dest_word; 3600*71d10453SEric Joyner u8 *from, *dest; 3601*71d10453SEric Joyner u16 shift_width; 3602*71d10453SEric Joyner 3603*71d10453SEric Joyner /* copy from the next struct field */ 3604*71d10453SEric Joyner from = src_ctx + ce_info->offset; 3605*71d10453SEric Joyner 3606*71d10453SEric Joyner /* prepare the bits and mask */ 3607*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3608*71d10453SEric Joyner mask = BIT(ce_info->width) - 1; 3609*71d10453SEric Joyner 3610*71d10453SEric Joyner /* don't swizzle the bits until after the mask because the mask bits 3611*71d10453SEric Joyner * will be in a different bit position on big endian machines 3612*71d10453SEric Joyner */ 3613*71d10453SEric Joyner src_word = *(u16 *)from; 3614*71d10453SEric Joyner src_word &= mask; 3615*71d10453SEric Joyner 3616*71d10453SEric Joyner /* shift to correct alignment */ 3617*71d10453SEric Joyner mask <<= shift_width; 3618*71d10453SEric Joyner src_word <<= shift_width; 3619*71d10453SEric Joyner 3620*71d10453SEric Joyner /* get the current bits from the target bit string */ 3621*71d10453SEric Joyner dest = dest_ctx + (ce_info->lsb / 8); 3622*71d10453SEric Joyner 3623*71d10453SEric Joyner ice_memcpy(&dest_word, dest, sizeof(dest_word), ICE_DMA_TO_NONDMA); 3624*71d10453SEric Joyner 3625*71d10453SEric Joyner dest_word &= ~(CPU_TO_LE16(mask)); /* get the bits not changing */ 3626*71d10453SEric Joyner dest_word |= CPU_TO_LE16(src_word); /* add in the new bits */ 3627*71d10453SEric Joyner 3628*71d10453SEric Joyner /* put it all back */ 3629*71d10453SEric Joyner ice_memcpy(dest, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA); 3630*71d10453SEric Joyner } 3631*71d10453SEric Joyner 3632*71d10453SEric Joyner /** 3633*71d10453SEric Joyner * ice_write_dword - write a dword to a packed context structure 3634*71d10453SEric Joyner * @src_ctx: the context structure to read from 3635*71d10453SEric Joyner * @dest_ctx: the context to be written to 3636*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3637*71d10453SEric Joyner */ 3638*71d10453SEric Joyner static void 3639*71d10453SEric Joyner ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 3640*71d10453SEric Joyner { 3641*71d10453SEric Joyner u32 src_dword, mask; 3642*71d10453SEric Joyner __le32 dest_dword; 3643*71d10453SEric Joyner u8 *from, *dest; 3644*71d10453SEric Joyner u16 shift_width; 3645*71d10453SEric Joyner 3646*71d10453SEric Joyner /* copy from the next struct field */ 3647*71d10453SEric Joyner from = src_ctx + ce_info->offset; 3648*71d10453SEric Joyner 3649*71d10453SEric Joyner /* prepare the bits and mask */ 3650*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3651*71d10453SEric Joyner 3652*71d10453SEric Joyner /* if the field width is exactly 32 on an x86 machine, then the shift 3653*71d10453SEric Joyner * operation will not work because the SHL instructions count is masked 3654*71d10453SEric Joyner * to 5 bits so the shift will do nothing 3655*71d10453SEric Joyner */ 3656*71d10453SEric Joyner if (ce_info->width < 32) 3657*71d10453SEric Joyner mask = BIT(ce_info->width) - 1; 3658*71d10453SEric Joyner else 3659*71d10453SEric Joyner mask = (u32)~0; 3660*71d10453SEric Joyner 3661*71d10453SEric Joyner /* don't swizzle the bits until after the mask because the mask bits 3662*71d10453SEric Joyner * will be in a different bit position on big endian machines 3663*71d10453SEric Joyner */ 3664*71d10453SEric Joyner src_dword = *(u32 *)from; 3665*71d10453SEric Joyner src_dword &= mask; 3666*71d10453SEric Joyner 3667*71d10453SEric Joyner /* shift to correct alignment */ 3668*71d10453SEric Joyner mask <<= shift_width; 3669*71d10453SEric Joyner src_dword <<= shift_width; 3670*71d10453SEric Joyner 3671*71d10453SEric Joyner /* get the current bits from the target bit string */ 3672*71d10453SEric Joyner dest = dest_ctx + (ce_info->lsb / 8); 3673*71d10453SEric Joyner 3674*71d10453SEric Joyner ice_memcpy(&dest_dword, dest, sizeof(dest_dword), ICE_DMA_TO_NONDMA); 3675*71d10453SEric Joyner 3676*71d10453SEric Joyner dest_dword &= ~(CPU_TO_LE32(mask)); /* get the bits not changing */ 3677*71d10453SEric Joyner dest_dword |= CPU_TO_LE32(src_dword); /* add in the new bits */ 3678*71d10453SEric Joyner 3679*71d10453SEric Joyner /* put it all back */ 3680*71d10453SEric Joyner ice_memcpy(dest, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA); 3681*71d10453SEric Joyner } 3682*71d10453SEric Joyner 3683*71d10453SEric Joyner /** 3684*71d10453SEric Joyner * ice_write_qword - write a qword to a packed context structure 3685*71d10453SEric Joyner * @src_ctx: the context structure to read from 3686*71d10453SEric Joyner * @dest_ctx: the context to be written to 3687*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3688*71d10453SEric Joyner */ 3689*71d10453SEric Joyner static void 3690*71d10453SEric Joyner ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 3691*71d10453SEric Joyner { 3692*71d10453SEric Joyner u64 src_qword, mask; 3693*71d10453SEric Joyner __le64 dest_qword; 3694*71d10453SEric Joyner u8 *from, *dest; 3695*71d10453SEric Joyner u16 shift_width; 3696*71d10453SEric Joyner 3697*71d10453SEric Joyner /* copy from the next struct field */ 3698*71d10453SEric Joyner from = src_ctx + ce_info->offset; 3699*71d10453SEric Joyner 3700*71d10453SEric Joyner /* prepare the bits and mask */ 3701*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3702*71d10453SEric Joyner 3703*71d10453SEric Joyner /* if the field width is exactly 64 on an x86 machine, then the shift 3704*71d10453SEric Joyner * operation will not work because the SHL instructions count is masked 3705*71d10453SEric Joyner * to 6 bits so the shift will do nothing 3706*71d10453SEric Joyner */ 3707*71d10453SEric Joyner if (ce_info->width < 64) 3708*71d10453SEric Joyner mask = BIT_ULL(ce_info->width) - 1; 3709*71d10453SEric Joyner else 3710*71d10453SEric Joyner mask = (u64)~0; 3711*71d10453SEric Joyner 3712*71d10453SEric Joyner /* don't swizzle the bits until after the mask because the mask bits 3713*71d10453SEric Joyner * will be in a different bit position on big endian machines 3714*71d10453SEric Joyner */ 3715*71d10453SEric Joyner src_qword = *(u64 *)from; 3716*71d10453SEric Joyner src_qword &= mask; 3717*71d10453SEric Joyner 3718*71d10453SEric Joyner /* shift to correct alignment */ 3719*71d10453SEric Joyner mask <<= shift_width; 3720*71d10453SEric Joyner src_qword <<= shift_width; 3721*71d10453SEric Joyner 3722*71d10453SEric Joyner /* get the current bits from the target bit string */ 3723*71d10453SEric Joyner dest = dest_ctx + (ce_info->lsb / 8); 3724*71d10453SEric Joyner 3725*71d10453SEric Joyner ice_memcpy(&dest_qword, dest, sizeof(dest_qword), ICE_DMA_TO_NONDMA); 3726*71d10453SEric Joyner 3727*71d10453SEric Joyner dest_qword &= ~(CPU_TO_LE64(mask)); /* get the bits not changing */ 3728*71d10453SEric Joyner dest_qword |= CPU_TO_LE64(src_qword); /* add in the new bits */ 3729*71d10453SEric Joyner 3730*71d10453SEric Joyner /* put it all back */ 3731*71d10453SEric Joyner ice_memcpy(dest, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA); 3732*71d10453SEric Joyner } 3733*71d10453SEric Joyner 3734*71d10453SEric Joyner /** 3735*71d10453SEric Joyner * ice_set_ctx - set context bits in packed structure 3736*71d10453SEric Joyner * @src_ctx: pointer to a generic non-packed context structure 3737*71d10453SEric Joyner * @dest_ctx: pointer to memory for the packed structure 3738*71d10453SEric Joyner * @ce_info: a description of the structure to be transformed 3739*71d10453SEric Joyner */ 3740*71d10453SEric Joyner enum ice_status 3741*71d10453SEric Joyner ice_set_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) 3742*71d10453SEric Joyner { 3743*71d10453SEric Joyner int f; 3744*71d10453SEric Joyner 3745*71d10453SEric Joyner for (f = 0; ce_info[f].width; f++) { 3746*71d10453SEric Joyner /* We have to deal with each element of the FW response 3747*71d10453SEric Joyner * using the correct size so that we are correct regardless 3748*71d10453SEric Joyner * of the endianness of the machine. 3749*71d10453SEric Joyner */ 3750*71d10453SEric Joyner switch (ce_info[f].size_of) { 3751*71d10453SEric Joyner case sizeof(u8): 3752*71d10453SEric Joyner ice_write_byte(src_ctx, dest_ctx, &ce_info[f]); 3753*71d10453SEric Joyner break; 3754*71d10453SEric Joyner case sizeof(u16): 3755*71d10453SEric Joyner ice_write_word(src_ctx, dest_ctx, &ce_info[f]); 3756*71d10453SEric Joyner break; 3757*71d10453SEric Joyner case sizeof(u32): 3758*71d10453SEric Joyner ice_write_dword(src_ctx, dest_ctx, &ce_info[f]); 3759*71d10453SEric Joyner break; 3760*71d10453SEric Joyner case sizeof(u64): 3761*71d10453SEric Joyner ice_write_qword(src_ctx, dest_ctx, &ce_info[f]); 3762*71d10453SEric Joyner break; 3763*71d10453SEric Joyner default: 3764*71d10453SEric Joyner return ICE_ERR_INVAL_SIZE; 3765*71d10453SEric Joyner } 3766*71d10453SEric Joyner } 3767*71d10453SEric Joyner 3768*71d10453SEric Joyner return ICE_SUCCESS; 3769*71d10453SEric Joyner } 3770*71d10453SEric Joyner 3771*71d10453SEric Joyner /** 3772*71d10453SEric Joyner * ice_read_byte - read context byte into struct 3773*71d10453SEric Joyner * @src_ctx: the context structure to read from 3774*71d10453SEric Joyner * @dest_ctx: the context to be written to 3775*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3776*71d10453SEric Joyner */ 3777*71d10453SEric Joyner static void 3778*71d10453SEric Joyner ice_read_byte(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) 3779*71d10453SEric Joyner { 3780*71d10453SEric Joyner u8 dest_byte, mask; 3781*71d10453SEric Joyner u8 *src, *target; 3782*71d10453SEric Joyner u16 shift_width; 3783*71d10453SEric Joyner 3784*71d10453SEric Joyner /* prepare the bits and mask */ 3785*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3786*71d10453SEric Joyner mask = (u8)(BIT(ce_info->width) - 1); 3787*71d10453SEric Joyner 3788*71d10453SEric Joyner /* shift to correct alignment */ 3789*71d10453SEric Joyner mask <<= shift_width; 3790*71d10453SEric Joyner 3791*71d10453SEric Joyner /* get the current bits from the src bit string */ 3792*71d10453SEric Joyner src = src_ctx + (ce_info->lsb / 8); 3793*71d10453SEric Joyner 3794*71d10453SEric Joyner ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_DMA_TO_NONDMA); 3795*71d10453SEric Joyner 3796*71d10453SEric Joyner dest_byte &= ~(mask); 3797*71d10453SEric Joyner 3798*71d10453SEric Joyner dest_byte >>= shift_width; 3799*71d10453SEric Joyner 3800*71d10453SEric Joyner /* get the address from the struct field */ 3801*71d10453SEric Joyner target = dest_ctx + ce_info->offset; 3802*71d10453SEric Joyner 3803*71d10453SEric Joyner /* put it back in the struct */ 3804*71d10453SEric Joyner ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA); 3805*71d10453SEric Joyner } 3806*71d10453SEric Joyner 3807*71d10453SEric Joyner /** 3808*71d10453SEric Joyner * ice_read_word - read context word into struct 3809*71d10453SEric Joyner * @src_ctx: the context structure to read from 3810*71d10453SEric Joyner * @dest_ctx: the context to be written to 3811*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3812*71d10453SEric Joyner */ 3813*71d10453SEric Joyner static void 3814*71d10453SEric Joyner ice_read_word(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) 3815*71d10453SEric Joyner { 3816*71d10453SEric Joyner u16 dest_word, mask; 3817*71d10453SEric Joyner u8 *src, *target; 3818*71d10453SEric Joyner __le16 src_word; 3819*71d10453SEric Joyner u16 shift_width; 3820*71d10453SEric Joyner 3821*71d10453SEric Joyner /* prepare the bits and mask */ 3822*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3823*71d10453SEric Joyner mask = BIT(ce_info->width) - 1; 3824*71d10453SEric Joyner 3825*71d10453SEric Joyner /* shift to correct alignment */ 3826*71d10453SEric Joyner mask <<= shift_width; 3827*71d10453SEric Joyner 3828*71d10453SEric Joyner /* get the current bits from the src bit string */ 3829*71d10453SEric Joyner src = src_ctx + (ce_info->lsb / 8); 3830*71d10453SEric Joyner 3831*71d10453SEric Joyner ice_memcpy(&src_word, src, sizeof(src_word), ICE_DMA_TO_NONDMA); 3832*71d10453SEric Joyner 3833*71d10453SEric Joyner /* the data in the memory is stored as little endian so mask it 3834*71d10453SEric Joyner * correctly 3835*71d10453SEric Joyner */ 3836*71d10453SEric Joyner src_word &= ~(CPU_TO_LE16(mask)); 3837*71d10453SEric Joyner 3838*71d10453SEric Joyner /* get the data back into host order before shifting */ 3839*71d10453SEric Joyner dest_word = LE16_TO_CPU(src_word); 3840*71d10453SEric Joyner 3841*71d10453SEric Joyner dest_word >>= shift_width; 3842*71d10453SEric Joyner 3843*71d10453SEric Joyner /* get the address from the struct field */ 3844*71d10453SEric Joyner target = dest_ctx + ce_info->offset; 3845*71d10453SEric Joyner 3846*71d10453SEric Joyner /* put it back in the struct */ 3847*71d10453SEric Joyner ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA); 3848*71d10453SEric Joyner } 3849*71d10453SEric Joyner 3850*71d10453SEric Joyner /** 3851*71d10453SEric Joyner * ice_read_dword - read context dword into struct 3852*71d10453SEric Joyner * @src_ctx: the context structure to read from 3853*71d10453SEric Joyner * @dest_ctx: the context to be written to 3854*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3855*71d10453SEric Joyner */ 3856*71d10453SEric Joyner static void 3857*71d10453SEric Joyner ice_read_dword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) 3858*71d10453SEric Joyner { 3859*71d10453SEric Joyner u32 dest_dword, mask; 3860*71d10453SEric Joyner __le32 src_dword; 3861*71d10453SEric Joyner u8 *src, *target; 3862*71d10453SEric Joyner u16 shift_width; 3863*71d10453SEric Joyner 3864*71d10453SEric Joyner /* prepare the bits and mask */ 3865*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3866*71d10453SEric Joyner 3867*71d10453SEric Joyner /* if the field width is exactly 32 on an x86 machine, then the shift 3868*71d10453SEric Joyner * operation will not work because the SHL instructions count is masked 3869*71d10453SEric Joyner * to 5 bits so the shift will do nothing 3870*71d10453SEric Joyner */ 3871*71d10453SEric Joyner if (ce_info->width < 32) 3872*71d10453SEric Joyner mask = BIT(ce_info->width) - 1; 3873*71d10453SEric Joyner else 3874*71d10453SEric Joyner mask = (u32)~0; 3875*71d10453SEric Joyner 3876*71d10453SEric Joyner /* shift to correct alignment */ 3877*71d10453SEric Joyner mask <<= shift_width; 3878*71d10453SEric Joyner 3879*71d10453SEric Joyner /* get the current bits from the src bit string */ 3880*71d10453SEric Joyner src = src_ctx + (ce_info->lsb / 8); 3881*71d10453SEric Joyner 3882*71d10453SEric Joyner ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_DMA_TO_NONDMA); 3883*71d10453SEric Joyner 3884*71d10453SEric Joyner /* the data in the memory is stored as little endian so mask it 3885*71d10453SEric Joyner * correctly 3886*71d10453SEric Joyner */ 3887*71d10453SEric Joyner src_dword &= ~(CPU_TO_LE32(mask)); 3888*71d10453SEric Joyner 3889*71d10453SEric Joyner /* get the data back into host order before shifting */ 3890*71d10453SEric Joyner dest_dword = LE32_TO_CPU(src_dword); 3891*71d10453SEric Joyner 3892*71d10453SEric Joyner dest_dword >>= shift_width; 3893*71d10453SEric Joyner 3894*71d10453SEric Joyner /* get the address from the struct field */ 3895*71d10453SEric Joyner target = dest_ctx + ce_info->offset; 3896*71d10453SEric Joyner 3897*71d10453SEric Joyner /* put it back in the struct */ 3898*71d10453SEric Joyner ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA); 3899*71d10453SEric Joyner } 3900*71d10453SEric Joyner 3901*71d10453SEric Joyner /** 3902*71d10453SEric Joyner * ice_read_qword - read context qword into struct 3903*71d10453SEric Joyner * @src_ctx: the context structure to read from 3904*71d10453SEric Joyner * @dest_ctx: the context to be written to 3905*71d10453SEric Joyner * @ce_info: a description of the struct to be filled 3906*71d10453SEric Joyner */ 3907*71d10453SEric Joyner static void 3908*71d10453SEric Joyner ice_read_qword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) 3909*71d10453SEric Joyner { 3910*71d10453SEric Joyner u64 dest_qword, mask; 3911*71d10453SEric Joyner __le64 src_qword; 3912*71d10453SEric Joyner u8 *src, *target; 3913*71d10453SEric Joyner u16 shift_width; 3914*71d10453SEric Joyner 3915*71d10453SEric Joyner /* prepare the bits and mask */ 3916*71d10453SEric Joyner shift_width = ce_info->lsb % 8; 3917*71d10453SEric Joyner 3918*71d10453SEric Joyner /* if the field width is exactly 64 on an x86 machine, then the shift 3919*71d10453SEric Joyner * operation will not work because the SHL instructions count is masked 3920*71d10453SEric Joyner * to 6 bits so the shift will do nothing 3921*71d10453SEric Joyner */ 3922*71d10453SEric Joyner if (ce_info->width < 64) 3923*71d10453SEric Joyner mask = BIT_ULL(ce_info->width) - 1; 3924*71d10453SEric Joyner else 3925*71d10453SEric Joyner mask = (u64)~0; 3926*71d10453SEric Joyner 3927*71d10453SEric Joyner /* shift to correct alignment */ 3928*71d10453SEric Joyner mask <<= shift_width; 3929*71d10453SEric Joyner 3930*71d10453SEric Joyner /* get the current bits from the src bit string */ 3931*71d10453SEric Joyner src = src_ctx + (ce_info->lsb / 8); 3932*71d10453SEric Joyner 3933*71d10453SEric Joyner ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_DMA_TO_NONDMA); 3934*71d10453SEric Joyner 3935*71d10453SEric Joyner /* the data in the memory is stored as little endian so mask it 3936*71d10453SEric Joyner * correctly 3937*71d10453SEric Joyner */ 3938*71d10453SEric Joyner src_qword &= ~(CPU_TO_LE64(mask)); 3939*71d10453SEric Joyner 3940*71d10453SEric Joyner /* get the data back into host order before shifting */ 3941*71d10453SEric Joyner dest_qword = LE64_TO_CPU(src_qword); 3942*71d10453SEric Joyner 3943*71d10453SEric Joyner dest_qword >>= shift_width; 3944*71d10453SEric Joyner 3945*71d10453SEric Joyner /* get the address from the struct field */ 3946*71d10453SEric Joyner target = dest_ctx + ce_info->offset; 3947*71d10453SEric Joyner 3948*71d10453SEric Joyner /* put it back in the struct */ 3949*71d10453SEric Joyner ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA); 3950*71d10453SEric Joyner } 3951*71d10453SEric Joyner 3952*71d10453SEric Joyner /** 3953*71d10453SEric Joyner * ice_get_ctx - extract context bits from a packed structure 3954*71d10453SEric Joyner * @src_ctx: pointer to a generic packed context structure 3955*71d10453SEric Joyner * @dest_ctx: pointer to a generic non-packed context structure 3956*71d10453SEric Joyner * @ce_info: a description of the structure to be read from 3957*71d10453SEric Joyner */ 3958*71d10453SEric Joyner enum ice_status 3959*71d10453SEric Joyner ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) 3960*71d10453SEric Joyner { 3961*71d10453SEric Joyner int f; 3962*71d10453SEric Joyner 3963*71d10453SEric Joyner for (f = 0; ce_info[f].width; f++) { 3964*71d10453SEric Joyner switch (ce_info[f].size_of) { 3965*71d10453SEric Joyner case 1: 3966*71d10453SEric Joyner ice_read_byte(src_ctx, dest_ctx, &ce_info[f]); 3967*71d10453SEric Joyner break; 3968*71d10453SEric Joyner case 2: 3969*71d10453SEric Joyner ice_read_word(src_ctx, dest_ctx, &ce_info[f]); 3970*71d10453SEric Joyner break; 3971*71d10453SEric Joyner case 4: 3972*71d10453SEric Joyner ice_read_dword(src_ctx, dest_ctx, &ce_info[f]); 3973*71d10453SEric Joyner break; 3974*71d10453SEric Joyner case 8: 3975*71d10453SEric Joyner ice_read_qword(src_ctx, dest_ctx, &ce_info[f]); 3976*71d10453SEric Joyner break; 3977*71d10453SEric Joyner default: 3978*71d10453SEric Joyner /* nothing to do, just keep going */ 3979*71d10453SEric Joyner break; 3980*71d10453SEric Joyner } 3981*71d10453SEric Joyner } 3982*71d10453SEric Joyner 3983*71d10453SEric Joyner return ICE_SUCCESS; 3984*71d10453SEric Joyner } 3985*71d10453SEric Joyner 3986*71d10453SEric Joyner /** 3987*71d10453SEric Joyner * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC 3988*71d10453SEric Joyner * @hw: pointer to the HW struct 3989*71d10453SEric Joyner * @vsi_handle: software VSI handle 3990*71d10453SEric Joyner * @tc: TC number 3991*71d10453SEric Joyner * @q_handle: software queue handle 3992*71d10453SEric Joyner */ 3993*71d10453SEric Joyner struct ice_q_ctx * 3994*71d10453SEric Joyner ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle) 3995*71d10453SEric Joyner { 3996*71d10453SEric Joyner struct ice_vsi_ctx *vsi; 3997*71d10453SEric Joyner struct ice_q_ctx *q_ctx; 3998*71d10453SEric Joyner 3999*71d10453SEric Joyner vsi = ice_get_vsi_ctx(hw, vsi_handle); 4000*71d10453SEric Joyner if (!vsi) 4001*71d10453SEric Joyner return NULL; 4002*71d10453SEric Joyner if (q_handle >= vsi->num_lan_q_entries[tc]) 4003*71d10453SEric Joyner return NULL; 4004*71d10453SEric Joyner if (!vsi->lan_q_ctx[tc]) 4005*71d10453SEric Joyner return NULL; 4006*71d10453SEric Joyner q_ctx = vsi->lan_q_ctx[tc]; 4007*71d10453SEric Joyner return &q_ctx[q_handle]; 4008*71d10453SEric Joyner } 4009*71d10453SEric Joyner 4010*71d10453SEric Joyner /** 4011*71d10453SEric Joyner * ice_ena_vsi_txq 4012*71d10453SEric Joyner * @pi: port information structure 4013*71d10453SEric Joyner * @vsi_handle: software VSI handle 4014*71d10453SEric Joyner * @tc: TC number 4015*71d10453SEric Joyner * @q_handle: software queue handle 4016*71d10453SEric Joyner * @num_qgrps: Number of added queue groups 4017*71d10453SEric Joyner * @buf: list of queue groups to be added 4018*71d10453SEric Joyner * @buf_size: size of buffer for indirect command 4019*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 4020*71d10453SEric Joyner * 4021*71d10453SEric Joyner * This function adds one LAN queue 4022*71d10453SEric Joyner */ 4023*71d10453SEric Joyner enum ice_status 4024*71d10453SEric Joyner ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle, 4025*71d10453SEric Joyner u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size, 4026*71d10453SEric Joyner struct ice_sq_cd *cd) 4027*71d10453SEric Joyner { 4028*71d10453SEric Joyner struct ice_aqc_txsched_elem_data node = { 0 }; 4029*71d10453SEric Joyner struct ice_sched_node *parent; 4030*71d10453SEric Joyner struct ice_q_ctx *q_ctx; 4031*71d10453SEric Joyner enum ice_status status; 4032*71d10453SEric Joyner struct ice_hw *hw; 4033*71d10453SEric Joyner 4034*71d10453SEric Joyner if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 4035*71d10453SEric Joyner return ICE_ERR_CFG; 4036*71d10453SEric Joyner 4037*71d10453SEric Joyner if (num_qgrps > 1 || buf->num_txqs > 1) 4038*71d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 4039*71d10453SEric Joyner 4040*71d10453SEric Joyner hw = pi->hw; 4041*71d10453SEric Joyner 4042*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle)) 4043*71d10453SEric Joyner return ICE_ERR_PARAM; 4044*71d10453SEric Joyner 4045*71d10453SEric Joyner ice_acquire_lock(&pi->sched_lock); 4046*71d10453SEric Joyner 4047*71d10453SEric Joyner q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle); 4048*71d10453SEric Joyner if (!q_ctx) { 4049*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n", 4050*71d10453SEric Joyner q_handle); 4051*71d10453SEric Joyner status = ICE_ERR_PARAM; 4052*71d10453SEric Joyner goto ena_txq_exit; 4053*71d10453SEric Joyner } 4054*71d10453SEric Joyner 4055*71d10453SEric Joyner /* find a parent node */ 4056*71d10453SEric Joyner parent = ice_sched_get_free_qparent(pi, vsi_handle, tc, 4057*71d10453SEric Joyner ICE_SCHED_NODE_OWNER_LAN); 4058*71d10453SEric Joyner if (!parent) { 4059*71d10453SEric Joyner status = ICE_ERR_PARAM; 4060*71d10453SEric Joyner goto ena_txq_exit; 4061*71d10453SEric Joyner } 4062*71d10453SEric Joyner 4063*71d10453SEric Joyner buf->parent_teid = parent->info.node_teid; 4064*71d10453SEric Joyner node.parent_teid = parent->info.node_teid; 4065*71d10453SEric Joyner /* Mark that the values in the "generic" section as valid. The default 4066*71d10453SEric Joyner * value in the "generic" section is zero. This means that : 4067*71d10453SEric Joyner * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0. 4068*71d10453SEric Joyner * - 0 priority among siblings, indicated by Bit 1-3. 4069*71d10453SEric Joyner * - WFQ, indicated by Bit 4. 4070*71d10453SEric Joyner * - 0 Adjustment value is used in PSM credit update flow, indicated by 4071*71d10453SEric Joyner * Bit 5-6. 4072*71d10453SEric Joyner * - Bit 7 is reserved. 4073*71d10453SEric Joyner * Without setting the generic section as valid in valid_sections, the 4074*71d10453SEric Joyner * Admin queue command will fail with error code ICE_AQ_RC_EINVAL. 4075*71d10453SEric Joyner */ 4076*71d10453SEric Joyner buf->txqs[0].info.valid_sections = ICE_AQC_ELEM_VALID_GENERIC; 4077*71d10453SEric Joyner 4078*71d10453SEric Joyner /* add the LAN queue */ 4079*71d10453SEric Joyner status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd); 4080*71d10453SEric Joyner if (status != ICE_SUCCESS) { 4081*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n", 4082*71d10453SEric Joyner LE16_TO_CPU(buf->txqs[0].txq_id), 4083*71d10453SEric Joyner hw->adminq.sq_last_status); 4084*71d10453SEric Joyner goto ena_txq_exit; 4085*71d10453SEric Joyner } 4086*71d10453SEric Joyner 4087*71d10453SEric Joyner node.node_teid = buf->txqs[0].q_teid; 4088*71d10453SEric Joyner node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF; 4089*71d10453SEric Joyner q_ctx->q_handle = q_handle; 4090*71d10453SEric Joyner q_ctx->q_teid = LE32_TO_CPU(node.node_teid); 4091*71d10453SEric Joyner 4092*71d10453SEric Joyner /* add a leaf node into scheduler tree queue layer */ 4093*71d10453SEric Joyner status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node); 4094*71d10453SEric Joyner if (!status) 4095*71d10453SEric Joyner status = ice_sched_replay_q_bw(pi, q_ctx); 4096*71d10453SEric Joyner 4097*71d10453SEric Joyner ena_txq_exit: 4098*71d10453SEric Joyner ice_release_lock(&pi->sched_lock); 4099*71d10453SEric Joyner return status; 4100*71d10453SEric Joyner } 4101*71d10453SEric Joyner 4102*71d10453SEric Joyner /** 4103*71d10453SEric Joyner * ice_dis_vsi_txq 4104*71d10453SEric Joyner * @pi: port information structure 4105*71d10453SEric Joyner * @vsi_handle: software VSI handle 4106*71d10453SEric Joyner * @tc: TC number 4107*71d10453SEric Joyner * @num_queues: number of queues 4108*71d10453SEric Joyner * @q_handles: pointer to software queue handle array 4109*71d10453SEric Joyner * @q_ids: pointer to the q_id array 4110*71d10453SEric Joyner * @q_teids: pointer to queue node teids 4111*71d10453SEric Joyner * @rst_src: if called due to reset, specifies the reset source 4112*71d10453SEric Joyner * @vmvf_num: the relative VM or VF number that is undergoing the reset 4113*71d10453SEric Joyner * @cd: pointer to command details structure or NULL 4114*71d10453SEric Joyner * 4115*71d10453SEric Joyner * This function removes queues and their corresponding nodes in SW DB 4116*71d10453SEric Joyner */ 4117*71d10453SEric Joyner enum ice_status 4118*71d10453SEric Joyner ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues, 4119*71d10453SEric Joyner u16 *q_handles, u16 *q_ids, u32 *q_teids, 4120*71d10453SEric Joyner enum ice_disq_rst_src rst_src, u16 vmvf_num, 4121*71d10453SEric Joyner struct ice_sq_cd *cd) 4122*71d10453SEric Joyner { 4123*71d10453SEric Joyner enum ice_status status = ICE_ERR_DOES_NOT_EXIST; 4124*71d10453SEric Joyner struct ice_aqc_dis_txq_item qg_list; 4125*71d10453SEric Joyner struct ice_q_ctx *q_ctx; 4126*71d10453SEric Joyner u16 i; 4127*71d10453SEric Joyner 4128*71d10453SEric Joyner if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 4129*71d10453SEric Joyner return ICE_ERR_CFG; 4130*71d10453SEric Joyner 4131*71d10453SEric Joyner if (!num_queues) { 4132*71d10453SEric Joyner /* if queue is disabled already yet the disable queue command 4133*71d10453SEric Joyner * has to be sent to complete the VF reset, then call 4134*71d10453SEric Joyner * ice_aq_dis_lan_txq without any queue information 4135*71d10453SEric Joyner */ 4136*71d10453SEric Joyner if (rst_src) 4137*71d10453SEric Joyner return ice_aq_dis_lan_txq(pi->hw, 0, NULL, 0, rst_src, 4138*71d10453SEric Joyner vmvf_num, NULL); 4139*71d10453SEric Joyner return ICE_ERR_CFG; 4140*71d10453SEric Joyner } 4141*71d10453SEric Joyner 4142*71d10453SEric Joyner ice_acquire_lock(&pi->sched_lock); 4143*71d10453SEric Joyner 4144*71d10453SEric Joyner for (i = 0; i < num_queues; i++) { 4145*71d10453SEric Joyner struct ice_sched_node *node; 4146*71d10453SEric Joyner 4147*71d10453SEric Joyner node = ice_sched_find_node_by_teid(pi->root, q_teids[i]); 4148*71d10453SEric Joyner if (!node) 4149*71d10453SEric Joyner continue; 4150*71d10453SEric Joyner q_ctx = ice_get_lan_q_ctx(pi->hw, vsi_handle, tc, q_handles[i]); 4151*71d10453SEric Joyner if (!q_ctx) { 4152*71d10453SEric Joyner ice_debug(pi->hw, ICE_DBG_SCHED, "invalid queue handle%d\n", 4153*71d10453SEric Joyner q_handles[i]); 4154*71d10453SEric Joyner continue; 4155*71d10453SEric Joyner } 4156*71d10453SEric Joyner if (q_ctx->q_handle != q_handles[i]) { 4157*71d10453SEric Joyner ice_debug(pi->hw, ICE_DBG_SCHED, "Err:handles %d %d\n", 4158*71d10453SEric Joyner q_ctx->q_handle, q_handles[i]); 4159*71d10453SEric Joyner continue; 4160*71d10453SEric Joyner } 4161*71d10453SEric Joyner qg_list.parent_teid = node->info.parent_teid; 4162*71d10453SEric Joyner qg_list.num_qs = 1; 4163*71d10453SEric Joyner qg_list.q_id[0] = CPU_TO_LE16(q_ids[i]); 4164*71d10453SEric Joyner status = ice_aq_dis_lan_txq(pi->hw, 1, &qg_list, 4165*71d10453SEric Joyner sizeof(qg_list), rst_src, vmvf_num, 4166*71d10453SEric Joyner cd); 4167*71d10453SEric Joyner 4168*71d10453SEric Joyner if (status != ICE_SUCCESS) 4169*71d10453SEric Joyner break; 4170*71d10453SEric Joyner ice_free_sched_node(pi, node); 4171*71d10453SEric Joyner q_ctx->q_handle = ICE_INVAL_Q_HANDLE; 4172*71d10453SEric Joyner } 4173*71d10453SEric Joyner ice_release_lock(&pi->sched_lock); 4174*71d10453SEric Joyner return status; 4175*71d10453SEric Joyner } 4176*71d10453SEric Joyner 4177*71d10453SEric Joyner /** 4178*71d10453SEric Joyner * ice_cfg_vsi_qs - configure the new/existing VSI queues 4179*71d10453SEric Joyner * @pi: port information structure 4180*71d10453SEric Joyner * @vsi_handle: software VSI handle 4181*71d10453SEric Joyner * @tc_bitmap: TC bitmap 4182*71d10453SEric Joyner * @maxqs: max queues array per TC 4183*71d10453SEric Joyner * @owner: LAN or RDMA 4184*71d10453SEric Joyner * 4185*71d10453SEric Joyner * This function adds/updates the VSI queues per TC. 4186*71d10453SEric Joyner */ 4187*71d10453SEric Joyner static enum ice_status 4188*71d10453SEric Joyner ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap, 4189*71d10453SEric Joyner u16 *maxqs, u8 owner) 4190*71d10453SEric Joyner { 4191*71d10453SEric Joyner enum ice_status status = ICE_SUCCESS; 4192*71d10453SEric Joyner u8 i; 4193*71d10453SEric Joyner 4194*71d10453SEric Joyner if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) 4195*71d10453SEric Joyner return ICE_ERR_CFG; 4196*71d10453SEric Joyner 4197*71d10453SEric Joyner if (!ice_is_vsi_valid(pi->hw, vsi_handle)) 4198*71d10453SEric Joyner return ICE_ERR_PARAM; 4199*71d10453SEric Joyner 4200*71d10453SEric Joyner ice_acquire_lock(&pi->sched_lock); 4201*71d10453SEric Joyner 4202*71d10453SEric Joyner ice_for_each_traffic_class(i) { 4203*71d10453SEric Joyner /* configuration is possible only if TC node is present */ 4204*71d10453SEric Joyner if (!ice_sched_get_tc_node(pi, i)) 4205*71d10453SEric Joyner continue; 4206*71d10453SEric Joyner 4207*71d10453SEric Joyner status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner, 4208*71d10453SEric Joyner ice_is_tc_ena(tc_bitmap, i)); 4209*71d10453SEric Joyner if (status) 4210*71d10453SEric Joyner break; 4211*71d10453SEric Joyner } 4212*71d10453SEric Joyner 4213*71d10453SEric Joyner ice_release_lock(&pi->sched_lock); 4214*71d10453SEric Joyner return status; 4215*71d10453SEric Joyner } 4216*71d10453SEric Joyner 4217*71d10453SEric Joyner /** 4218*71d10453SEric Joyner * ice_cfg_vsi_lan - configure VSI LAN queues 4219*71d10453SEric Joyner * @pi: port information structure 4220*71d10453SEric Joyner * @vsi_handle: software VSI handle 4221*71d10453SEric Joyner * @tc_bitmap: TC bitmap 4222*71d10453SEric Joyner * @max_lanqs: max LAN queues array per TC 4223*71d10453SEric Joyner * 4224*71d10453SEric Joyner * This function adds/updates the VSI LAN queues per TC. 4225*71d10453SEric Joyner */ 4226*71d10453SEric Joyner enum ice_status 4227*71d10453SEric Joyner ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap, 4228*71d10453SEric Joyner u16 *max_lanqs) 4229*71d10453SEric Joyner { 4230*71d10453SEric Joyner return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs, 4231*71d10453SEric Joyner ICE_SCHED_NODE_OWNER_LAN); 4232*71d10453SEric Joyner } 4233*71d10453SEric Joyner 4234*71d10453SEric Joyner /** 4235*71d10453SEric Joyner * ice_replay_pre_init - replay pre initialization 4236*71d10453SEric Joyner * @hw: pointer to the HW struct 4237*71d10453SEric Joyner * 4238*71d10453SEric Joyner * Initializes required config data for VSI, FD, ACL, and RSS before replay. 4239*71d10453SEric Joyner */ 4240*71d10453SEric Joyner static enum ice_status ice_replay_pre_init(struct ice_hw *hw) 4241*71d10453SEric Joyner { 4242*71d10453SEric Joyner struct ice_switch_info *sw = hw->switch_info; 4243*71d10453SEric Joyner u8 i; 4244*71d10453SEric Joyner 4245*71d10453SEric Joyner /* Delete old entries from replay filter list head if there is any */ 4246*71d10453SEric Joyner ice_rm_all_sw_replay_rule_info(hw); 4247*71d10453SEric Joyner /* In start of replay, move entries into replay_rules list, it 4248*71d10453SEric Joyner * will allow adding rules entries back to filt_rules list, 4249*71d10453SEric Joyner * which is operational list. 4250*71d10453SEric Joyner */ 4251*71d10453SEric Joyner for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) 4252*71d10453SEric Joyner LIST_REPLACE_INIT(&sw->recp_list[i].filt_rules, 4253*71d10453SEric Joyner &sw->recp_list[i].filt_replay_rules); 4254*71d10453SEric Joyner ice_sched_replay_agg_vsi_preinit(hw); 4255*71d10453SEric Joyner 4256*71d10453SEric Joyner return ice_sched_replay_tc_node_bw(hw->port_info); 4257*71d10453SEric Joyner } 4258*71d10453SEric Joyner 4259*71d10453SEric Joyner /** 4260*71d10453SEric Joyner * ice_replay_vsi - replay VSI configuration 4261*71d10453SEric Joyner * @hw: pointer to the HW struct 4262*71d10453SEric Joyner * @vsi_handle: driver VSI handle 4263*71d10453SEric Joyner * 4264*71d10453SEric Joyner * Restore all VSI configuration after reset. It is required to call this 4265*71d10453SEric Joyner * function with main VSI first. 4266*71d10453SEric Joyner */ 4267*71d10453SEric Joyner enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle) 4268*71d10453SEric Joyner { 4269*71d10453SEric Joyner enum ice_status status; 4270*71d10453SEric Joyner 4271*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle)) 4272*71d10453SEric Joyner return ICE_ERR_PARAM; 4273*71d10453SEric Joyner 4274*71d10453SEric Joyner /* Replay pre-initialization if there is any */ 4275*71d10453SEric Joyner if (vsi_handle == ICE_MAIN_VSI_HANDLE) { 4276*71d10453SEric Joyner status = ice_replay_pre_init(hw); 4277*71d10453SEric Joyner if (status) 4278*71d10453SEric Joyner return status; 4279*71d10453SEric Joyner } 4280*71d10453SEric Joyner /* Replay per VSI all RSS configurations */ 4281*71d10453SEric Joyner status = ice_replay_rss_cfg(hw, vsi_handle); 4282*71d10453SEric Joyner if (status) 4283*71d10453SEric Joyner return status; 4284*71d10453SEric Joyner /* Replay per VSI all filters */ 4285*71d10453SEric Joyner status = ice_replay_vsi_all_fltr(hw, vsi_handle); 4286*71d10453SEric Joyner if (!status) 4287*71d10453SEric Joyner status = ice_replay_vsi_agg(hw, vsi_handle); 4288*71d10453SEric Joyner return status; 4289*71d10453SEric Joyner } 4290*71d10453SEric Joyner 4291*71d10453SEric Joyner /** 4292*71d10453SEric Joyner * ice_replay_post - post replay configuration cleanup 4293*71d10453SEric Joyner * @hw: pointer to the HW struct 4294*71d10453SEric Joyner * 4295*71d10453SEric Joyner * Post replay cleanup. 4296*71d10453SEric Joyner */ 4297*71d10453SEric Joyner void ice_replay_post(struct ice_hw *hw) 4298*71d10453SEric Joyner { 4299*71d10453SEric Joyner /* Delete old entries from replay filter list head */ 4300*71d10453SEric Joyner ice_rm_all_sw_replay_rule_info(hw); 4301*71d10453SEric Joyner ice_sched_replay_agg(hw); 4302*71d10453SEric Joyner } 4303*71d10453SEric Joyner 4304*71d10453SEric Joyner /** 4305*71d10453SEric Joyner * ice_stat_update40 - read 40 bit stat from the chip and update stat values 4306*71d10453SEric Joyner * @hw: ptr to the hardware info 4307*71d10453SEric Joyner * @reg: offset of 64 bit HW register to read from 4308*71d10453SEric Joyner * @prev_stat_loaded: bool to specify if previous stats are loaded 4309*71d10453SEric Joyner * @prev_stat: ptr to previous loaded stat value 4310*71d10453SEric Joyner * @cur_stat: ptr to current stat value 4311*71d10453SEric Joyner */ 4312*71d10453SEric Joyner void 4313*71d10453SEric Joyner ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, 4314*71d10453SEric Joyner u64 *prev_stat, u64 *cur_stat) 4315*71d10453SEric Joyner { 4316*71d10453SEric Joyner u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1); 4317*71d10453SEric Joyner 4318*71d10453SEric Joyner /* device stats are not reset at PFR, they likely will not be zeroed 4319*71d10453SEric Joyner * when the driver starts. Thus, save the value from the first read 4320*71d10453SEric Joyner * without adding to the statistic value so that we report stats which 4321*71d10453SEric Joyner * count up from zero. 4322*71d10453SEric Joyner */ 4323*71d10453SEric Joyner if (!prev_stat_loaded) { 4324*71d10453SEric Joyner *prev_stat = new_data; 4325*71d10453SEric Joyner return; 4326*71d10453SEric Joyner } 4327*71d10453SEric Joyner 4328*71d10453SEric Joyner /* Calculate the difference between the new and old values, and then 4329*71d10453SEric Joyner * add it to the software stat value. 4330*71d10453SEric Joyner */ 4331*71d10453SEric Joyner if (new_data >= *prev_stat) 4332*71d10453SEric Joyner *cur_stat += new_data - *prev_stat; 4333*71d10453SEric Joyner else 4334*71d10453SEric Joyner /* to manage the potential roll-over */ 4335*71d10453SEric Joyner *cur_stat += (new_data + BIT_ULL(40)) - *prev_stat; 4336*71d10453SEric Joyner 4337*71d10453SEric Joyner /* Update the previously stored value to prepare for next read */ 4338*71d10453SEric Joyner *prev_stat = new_data; 4339*71d10453SEric Joyner } 4340*71d10453SEric Joyner 4341*71d10453SEric Joyner /** 4342*71d10453SEric Joyner * ice_stat_update32 - read 32 bit stat from the chip and update stat values 4343*71d10453SEric Joyner * @hw: ptr to the hardware info 4344*71d10453SEric Joyner * @reg: offset of HW register to read from 4345*71d10453SEric Joyner * @prev_stat_loaded: bool to specify if previous stats are loaded 4346*71d10453SEric Joyner * @prev_stat: ptr to previous loaded stat value 4347*71d10453SEric Joyner * @cur_stat: ptr to current stat value 4348*71d10453SEric Joyner */ 4349*71d10453SEric Joyner void 4350*71d10453SEric Joyner ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, 4351*71d10453SEric Joyner u64 *prev_stat, u64 *cur_stat) 4352*71d10453SEric Joyner { 4353*71d10453SEric Joyner u32 new_data; 4354*71d10453SEric Joyner 4355*71d10453SEric Joyner new_data = rd32(hw, reg); 4356*71d10453SEric Joyner 4357*71d10453SEric Joyner /* device stats are not reset at PFR, they likely will not be zeroed 4358*71d10453SEric Joyner * when the driver starts. Thus, save the value from the first read 4359*71d10453SEric Joyner * without adding to the statistic value so that we report stats which 4360*71d10453SEric Joyner * count up from zero. 4361*71d10453SEric Joyner */ 4362*71d10453SEric Joyner if (!prev_stat_loaded) { 4363*71d10453SEric Joyner *prev_stat = new_data; 4364*71d10453SEric Joyner return; 4365*71d10453SEric Joyner } 4366*71d10453SEric Joyner 4367*71d10453SEric Joyner /* Calculate the difference between the new and old values, and then 4368*71d10453SEric Joyner * add it to the software stat value. 4369*71d10453SEric Joyner */ 4370*71d10453SEric Joyner if (new_data >= *prev_stat) 4371*71d10453SEric Joyner *cur_stat += new_data - *prev_stat; 4372*71d10453SEric Joyner else 4373*71d10453SEric Joyner /* to manage the potential roll-over */ 4374*71d10453SEric Joyner *cur_stat += (new_data + BIT_ULL(32)) - *prev_stat; 4375*71d10453SEric Joyner 4376*71d10453SEric Joyner /* Update the previously stored value to prepare for next read */ 4377*71d10453SEric Joyner *prev_stat = new_data; 4378*71d10453SEric Joyner } 4379*71d10453SEric Joyner 4380*71d10453SEric Joyner /** 4381*71d10453SEric Joyner * ice_stat_update_repc - read GLV_REPC stats from chip and update stat values 4382*71d10453SEric Joyner * @hw: ptr to the hardware info 4383*71d10453SEric Joyner * @vsi_handle: VSI handle 4384*71d10453SEric Joyner * @prev_stat_loaded: bool to specify if the previous stat values are loaded 4385*71d10453SEric Joyner * @cur_stats: ptr to current stats structure 4386*71d10453SEric Joyner * 4387*71d10453SEric Joyner * The GLV_REPC statistic register actually tracks two 16bit statistics, and 4388*71d10453SEric Joyner * thus cannot be read using the normal ice_stat_update32 function. 4389*71d10453SEric Joyner * 4390*71d10453SEric Joyner * Read the GLV_REPC register associated with the given VSI, and update the 4391*71d10453SEric Joyner * rx_no_desc and rx_error values in the ice_eth_stats structure. 4392*71d10453SEric Joyner * 4393*71d10453SEric Joyner * Because the statistics in GLV_REPC stick at 0xFFFF, the register must be 4394*71d10453SEric Joyner * cleared each time it's read. 4395*71d10453SEric Joyner * 4396*71d10453SEric Joyner * Note that the GLV_RDPC register also counts the causes that would trigger 4397*71d10453SEric Joyner * GLV_REPC. However, it does not give the finer grained detail about why the 4398*71d10453SEric Joyner * packets are being dropped. The GLV_REPC values can be used to distinguish 4399*71d10453SEric Joyner * whether Rx packets are dropped due to errors or due to no available 4400*71d10453SEric Joyner * descriptors. 4401*71d10453SEric Joyner */ 4402*71d10453SEric Joyner void 4403*71d10453SEric Joyner ice_stat_update_repc(struct ice_hw *hw, u16 vsi_handle, bool prev_stat_loaded, 4404*71d10453SEric Joyner struct ice_eth_stats *cur_stats) 4405*71d10453SEric Joyner { 4406*71d10453SEric Joyner u16 vsi_num, no_desc, error_cnt; 4407*71d10453SEric Joyner u32 repc; 4408*71d10453SEric Joyner 4409*71d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle)) 4410*71d10453SEric Joyner return; 4411*71d10453SEric Joyner 4412*71d10453SEric Joyner vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 4413*71d10453SEric Joyner 4414*71d10453SEric Joyner /* If we haven't loaded stats yet, just clear the current value */ 4415*71d10453SEric Joyner if (!prev_stat_loaded) { 4416*71d10453SEric Joyner wr32(hw, GLV_REPC(vsi_num), 0); 4417*71d10453SEric Joyner return; 4418*71d10453SEric Joyner } 4419*71d10453SEric Joyner 4420*71d10453SEric Joyner repc = rd32(hw, GLV_REPC(vsi_num)); 4421*71d10453SEric Joyner no_desc = (repc & GLV_REPC_NO_DESC_CNT_M) >> GLV_REPC_NO_DESC_CNT_S; 4422*71d10453SEric Joyner error_cnt = (repc & GLV_REPC_ERROR_CNT_M) >> GLV_REPC_ERROR_CNT_S; 4423*71d10453SEric Joyner 4424*71d10453SEric Joyner /* Clear the count by writing to the stats register */ 4425*71d10453SEric Joyner wr32(hw, GLV_REPC(vsi_num), 0); 4426*71d10453SEric Joyner 4427*71d10453SEric Joyner cur_stats->rx_no_desc += no_desc; 4428*71d10453SEric Joyner cur_stats->rx_errors += error_cnt; 4429*71d10453SEric Joyner } 4430*71d10453SEric Joyner 4431*71d10453SEric Joyner /** 4432*71d10453SEric Joyner * ice_aq_alternate_write 4433*71d10453SEric Joyner * @hw: pointer to the hardware structure 4434*71d10453SEric Joyner * @reg_addr0: address of first dword to be written 4435*71d10453SEric Joyner * @reg_val0: value to be written under 'reg_addr0' 4436*71d10453SEric Joyner * @reg_addr1: address of second dword to be written 4437*71d10453SEric Joyner * @reg_val1: value to be written under 'reg_addr1' 4438*71d10453SEric Joyner * 4439*71d10453SEric Joyner * Write one or two dwords to alternate structure. Fields are indicated 4440*71d10453SEric Joyner * by 'reg_addr0' and 'reg_addr1' register numbers. 4441*71d10453SEric Joyner */ 4442*71d10453SEric Joyner enum ice_status 4443*71d10453SEric Joyner ice_aq_alternate_write(struct ice_hw *hw, u32 reg_addr0, u32 reg_val0, 4444*71d10453SEric Joyner u32 reg_addr1, u32 reg_val1) 4445*71d10453SEric Joyner { 4446*71d10453SEric Joyner struct ice_aqc_read_write_alt_direct *cmd; 4447*71d10453SEric Joyner struct ice_aq_desc desc; 4448*71d10453SEric Joyner enum ice_status status; 4449*71d10453SEric Joyner 4450*71d10453SEric Joyner cmd = &desc.params.read_write_alt_direct; 4451*71d10453SEric Joyner 4452*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_alt_direct); 4453*71d10453SEric Joyner cmd->dword0_addr = CPU_TO_LE32(reg_addr0); 4454*71d10453SEric Joyner cmd->dword1_addr = CPU_TO_LE32(reg_addr1); 4455*71d10453SEric Joyner cmd->dword0_value = CPU_TO_LE32(reg_val0); 4456*71d10453SEric Joyner cmd->dword1_value = CPU_TO_LE32(reg_val1); 4457*71d10453SEric Joyner 4458*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 4459*71d10453SEric Joyner 4460*71d10453SEric Joyner return status; 4461*71d10453SEric Joyner } 4462*71d10453SEric Joyner 4463*71d10453SEric Joyner /** 4464*71d10453SEric Joyner * ice_aq_alternate_read 4465*71d10453SEric Joyner * @hw: pointer to the hardware structure 4466*71d10453SEric Joyner * @reg_addr0: address of first dword to be read 4467*71d10453SEric Joyner * @reg_val0: pointer for data read from 'reg_addr0' 4468*71d10453SEric Joyner * @reg_addr1: address of second dword to be read 4469*71d10453SEric Joyner * @reg_val1: pointer for data read from 'reg_addr1' 4470*71d10453SEric Joyner * 4471*71d10453SEric Joyner * Read one or two dwords from alternate structure. Fields are indicated 4472*71d10453SEric Joyner * by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer 4473*71d10453SEric Joyner * is not passed then only register at 'reg_addr0' is read. 4474*71d10453SEric Joyner */ 4475*71d10453SEric Joyner enum ice_status 4476*71d10453SEric Joyner ice_aq_alternate_read(struct ice_hw *hw, u32 reg_addr0, u32 *reg_val0, 4477*71d10453SEric Joyner u32 reg_addr1, u32 *reg_val1) 4478*71d10453SEric Joyner { 4479*71d10453SEric Joyner struct ice_aqc_read_write_alt_direct *cmd; 4480*71d10453SEric Joyner struct ice_aq_desc desc; 4481*71d10453SEric Joyner enum ice_status status; 4482*71d10453SEric Joyner 4483*71d10453SEric Joyner cmd = &desc.params.read_write_alt_direct; 4484*71d10453SEric Joyner 4485*71d10453SEric Joyner if (!reg_val0) 4486*71d10453SEric Joyner return ICE_ERR_PARAM; 4487*71d10453SEric Joyner 4488*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_alt_direct); 4489*71d10453SEric Joyner cmd->dword0_addr = CPU_TO_LE32(reg_addr0); 4490*71d10453SEric Joyner cmd->dword1_addr = CPU_TO_LE32(reg_addr1); 4491*71d10453SEric Joyner 4492*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 4493*71d10453SEric Joyner 4494*71d10453SEric Joyner if (status == ICE_SUCCESS) { 4495*71d10453SEric Joyner *reg_val0 = LE32_TO_CPU(cmd->dword0_value); 4496*71d10453SEric Joyner 4497*71d10453SEric Joyner if (reg_val1) 4498*71d10453SEric Joyner *reg_val1 = LE32_TO_CPU(cmd->dword1_value); 4499*71d10453SEric Joyner } 4500*71d10453SEric Joyner 4501*71d10453SEric Joyner return status; 4502*71d10453SEric Joyner } 4503*71d10453SEric Joyner 4504*71d10453SEric Joyner /** 4505*71d10453SEric Joyner * ice_aq_alternate_write_done 4506*71d10453SEric Joyner * @hw: pointer to the HW structure. 4507*71d10453SEric Joyner * @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS 4508*71d10453SEric Joyner * @reset_needed: indicates the SW should trigger GLOBAL reset 4509*71d10453SEric Joyner * 4510*71d10453SEric Joyner * Indicates to the FW that alternate structures have been changed. 4511*71d10453SEric Joyner */ 4512*71d10453SEric Joyner enum ice_status 4513*71d10453SEric Joyner ice_aq_alternate_write_done(struct ice_hw *hw, u8 bios_mode, bool *reset_needed) 4514*71d10453SEric Joyner { 4515*71d10453SEric Joyner struct ice_aqc_done_alt_write *cmd; 4516*71d10453SEric Joyner struct ice_aq_desc desc; 4517*71d10453SEric Joyner enum ice_status status; 4518*71d10453SEric Joyner 4519*71d10453SEric Joyner cmd = &desc.params.done_alt_write; 4520*71d10453SEric Joyner 4521*71d10453SEric Joyner if (!reset_needed) 4522*71d10453SEric Joyner return ICE_ERR_PARAM; 4523*71d10453SEric Joyner 4524*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_done_alt_write); 4525*71d10453SEric Joyner cmd->flags = bios_mode; 4526*71d10453SEric Joyner 4527*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 4528*71d10453SEric Joyner if (!status) 4529*71d10453SEric Joyner *reset_needed = (LE16_TO_CPU(cmd->flags) & 4530*71d10453SEric Joyner ICE_AQC_RESP_RESET_NEEDED) != 0; 4531*71d10453SEric Joyner 4532*71d10453SEric Joyner return status; 4533*71d10453SEric Joyner } 4534*71d10453SEric Joyner 4535*71d10453SEric Joyner /** 4536*71d10453SEric Joyner * ice_aq_alternate_clear 4537*71d10453SEric Joyner * @hw: pointer to the HW structure. 4538*71d10453SEric Joyner * 4539*71d10453SEric Joyner * Clear the alternate structures of the port from which the function 4540*71d10453SEric Joyner * is called. 4541*71d10453SEric Joyner */ 4542*71d10453SEric Joyner enum ice_status ice_aq_alternate_clear(struct ice_hw *hw) 4543*71d10453SEric Joyner { 4544*71d10453SEric Joyner struct ice_aq_desc desc; 4545*71d10453SEric Joyner enum ice_status status; 4546*71d10453SEric Joyner 4547*71d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_port_alt_write); 4548*71d10453SEric Joyner 4549*71d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 4550*71d10453SEric Joyner 4551*71d10453SEric Joyner return status; 4552*71d10453SEric Joyner } 4553*71d10453SEric Joyner 4554*71d10453SEric Joyner /** 4555*71d10453SEric Joyner * ice_sched_query_elem - query element information from HW 4556*71d10453SEric Joyner * @hw: pointer to the HW struct 4557*71d10453SEric Joyner * @node_teid: node TEID to be queried 4558*71d10453SEric Joyner * @buf: buffer to element information 4559*71d10453SEric Joyner * 4560*71d10453SEric Joyner * This function queries HW element information 4561*71d10453SEric Joyner */ 4562*71d10453SEric Joyner enum ice_status 4563*71d10453SEric Joyner ice_sched_query_elem(struct ice_hw *hw, u32 node_teid, 4564*71d10453SEric Joyner struct ice_aqc_get_elem *buf) 4565*71d10453SEric Joyner { 4566*71d10453SEric Joyner u16 buf_size, num_elem_ret = 0; 4567*71d10453SEric Joyner enum ice_status status; 4568*71d10453SEric Joyner 4569*71d10453SEric Joyner buf_size = sizeof(*buf); 4570*71d10453SEric Joyner ice_memset(buf, 0, buf_size, ICE_NONDMA_MEM); 4571*71d10453SEric Joyner buf->generic[0].node_teid = CPU_TO_LE32(node_teid); 4572*71d10453SEric Joyner status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret, 4573*71d10453SEric Joyner NULL); 4574*71d10453SEric Joyner if (status != ICE_SUCCESS || num_elem_ret != 1) 4575*71d10453SEric Joyner ice_debug(hw, ICE_DBG_SCHED, "query element failed\n"); 4576*71d10453SEric Joyner return status; 4577*71d10453SEric Joyner } 4578*71d10453SEric Joyner 4579*71d10453SEric Joyner /** 4580*71d10453SEric Joyner * ice_get_fw_mode - returns FW mode 4581*71d10453SEric Joyner * @hw: pointer to the HW struct 4582*71d10453SEric Joyner */ 4583*71d10453SEric Joyner enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw) 4584*71d10453SEric Joyner { 4585*71d10453SEric Joyner #define ICE_FW_MODE_DBG_M BIT(0) 4586*71d10453SEric Joyner #define ICE_FW_MODE_REC_M BIT(1) 4587*71d10453SEric Joyner #define ICE_FW_MODE_ROLLBACK_M BIT(2) 4588*71d10453SEric Joyner u32 fw_mode; 4589*71d10453SEric Joyner 4590*71d10453SEric Joyner /* check the current FW mode */ 4591*71d10453SEric Joyner fw_mode = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_MODES_M; 4592*71d10453SEric Joyner 4593*71d10453SEric Joyner if (fw_mode & ICE_FW_MODE_DBG_M) 4594*71d10453SEric Joyner return ICE_FW_MODE_DBG; 4595*71d10453SEric Joyner else if (fw_mode & ICE_FW_MODE_REC_M) 4596*71d10453SEric Joyner return ICE_FW_MODE_REC; 4597*71d10453SEric Joyner else if (fw_mode & ICE_FW_MODE_ROLLBACK_M) 4598*71d10453SEric Joyner return ICE_FW_MODE_ROLLBACK; 4599*71d10453SEric Joyner else 4600*71d10453SEric Joyner return ICE_FW_MODE_NORMAL; 4601*71d10453SEric Joyner } 4602*71d10453SEric Joyner 4603*71d10453SEric Joyner /** 4604*71d10453SEric Joyner * ice_cfg_get_cur_lldp_persist_status 4605*71d10453SEric Joyner * @hw: pointer to the HW struct 4606*71d10453SEric Joyner * @lldp_status: return value of LLDP persistent status 4607*71d10453SEric Joyner * 4608*71d10453SEric Joyner * Get the current status of LLDP persistent 4609*71d10453SEric Joyner */ 4610*71d10453SEric Joyner enum ice_status 4611*71d10453SEric Joyner ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status) 4612*71d10453SEric Joyner { 4613*71d10453SEric Joyner struct ice_port_info *pi = hw->port_info; 4614*71d10453SEric Joyner enum ice_status ret; 4615*71d10453SEric Joyner __le32 raw_data; 4616*71d10453SEric Joyner u32 data, mask; 4617*71d10453SEric Joyner 4618*71d10453SEric Joyner if (!lldp_status) 4619*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 4620*71d10453SEric Joyner 4621*71d10453SEric Joyner ret = ice_acquire_nvm(hw, ICE_RES_READ); 4622*71d10453SEric Joyner if (ret) 4623*71d10453SEric Joyner return ret; 4624*71d10453SEric Joyner 4625*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LLDP_PRESERVED_MOD_ID, 4626*71d10453SEric Joyner ICE_AQC_NVM_CUR_LLDP_PERSIST_RD_OFFSET, 4627*71d10453SEric Joyner ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data, 4628*71d10453SEric Joyner false, true, NULL); 4629*71d10453SEric Joyner if (!ret) { 4630*71d10453SEric Joyner data = LE32_TO_CPU(raw_data); 4631*71d10453SEric Joyner mask = ICE_AQC_NVM_LLDP_STATUS_M << 4632*71d10453SEric Joyner (ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport); 4633*71d10453SEric Joyner data = data & mask; 4634*71d10453SEric Joyner *lldp_status = data >> 4635*71d10453SEric Joyner (ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport); 4636*71d10453SEric Joyner } 4637*71d10453SEric Joyner 4638*71d10453SEric Joyner ice_release_nvm(hw); 4639*71d10453SEric Joyner 4640*71d10453SEric Joyner return ret; 4641*71d10453SEric Joyner } 4642*71d10453SEric Joyner 4643*71d10453SEric Joyner /** 4644*71d10453SEric Joyner * ice_get_dflt_lldp_persist_status 4645*71d10453SEric Joyner * @hw: pointer to the HW struct 4646*71d10453SEric Joyner * @lldp_status: return value of LLDP persistent status 4647*71d10453SEric Joyner * 4648*71d10453SEric Joyner * Get the default status of LLDP persistent 4649*71d10453SEric Joyner */ 4650*71d10453SEric Joyner enum ice_status 4651*71d10453SEric Joyner ice_get_dflt_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status) 4652*71d10453SEric Joyner { 4653*71d10453SEric Joyner struct ice_port_info *pi = hw->port_info; 4654*71d10453SEric Joyner u32 data, mask, loc_data, loc_data_tmp; 4655*71d10453SEric Joyner enum ice_status ret; 4656*71d10453SEric Joyner __le16 loc_raw_data; 4657*71d10453SEric Joyner __le32 raw_data; 4658*71d10453SEric Joyner 4659*71d10453SEric Joyner if (!lldp_status) 4660*71d10453SEric Joyner return ICE_ERR_BAD_PTR; 4661*71d10453SEric Joyner 4662*71d10453SEric Joyner ret = ice_acquire_nvm(hw, ICE_RES_READ); 4663*71d10453SEric Joyner if (ret) 4664*71d10453SEric Joyner return ret; 4665*71d10453SEric Joyner 4666*71d10453SEric Joyner /* Read the offset of EMP_SR_PTR */ 4667*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, 4668*71d10453SEric Joyner ICE_AQC_NVM_EMP_SR_PTR_OFFSET, 4669*71d10453SEric Joyner ICE_AQC_NVM_EMP_SR_PTR_RD_LEN, 4670*71d10453SEric Joyner &loc_raw_data, false, true, NULL); 4671*71d10453SEric Joyner if (ret) 4672*71d10453SEric Joyner goto exit; 4673*71d10453SEric Joyner 4674*71d10453SEric Joyner loc_data = LE16_TO_CPU(loc_raw_data); 4675*71d10453SEric Joyner if (loc_data & ICE_AQC_NVM_EMP_SR_PTR_TYPE_M) { 4676*71d10453SEric Joyner loc_data &= ICE_AQC_NVM_EMP_SR_PTR_M; 4677*71d10453SEric Joyner loc_data *= ICE_AQC_NVM_SECTOR_UNIT; 4678*71d10453SEric Joyner } else { 4679*71d10453SEric Joyner loc_data *= ICE_AQC_NVM_WORD_UNIT; 4680*71d10453SEric Joyner } 4681*71d10453SEric Joyner 4682*71d10453SEric Joyner /* Read the offset of LLDP configuration pointer */ 4683*71d10453SEric Joyner loc_data += ICE_AQC_NVM_LLDP_CFG_PTR_OFFSET; 4684*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data, 4685*71d10453SEric Joyner ICE_AQC_NVM_LLDP_CFG_PTR_RD_LEN, &loc_raw_data, 4686*71d10453SEric Joyner false, true, NULL); 4687*71d10453SEric Joyner if (ret) 4688*71d10453SEric Joyner goto exit; 4689*71d10453SEric Joyner 4690*71d10453SEric Joyner loc_data_tmp = LE16_TO_CPU(loc_raw_data); 4691*71d10453SEric Joyner loc_data_tmp *= ICE_AQC_NVM_WORD_UNIT; 4692*71d10453SEric Joyner loc_data += loc_data_tmp; 4693*71d10453SEric Joyner 4694*71d10453SEric Joyner /* We need to skip LLDP configuration section length (2 bytes)*/ 4695*71d10453SEric Joyner loc_data += ICE_AQC_NVM_LLDP_CFG_HEADER_LEN; 4696*71d10453SEric Joyner 4697*71d10453SEric Joyner /* Read the LLDP Default Configure */ 4698*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data, 4699*71d10453SEric Joyner ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data, false, 4700*71d10453SEric Joyner true, NULL); 4701*71d10453SEric Joyner if (!ret) { 4702*71d10453SEric Joyner data = LE32_TO_CPU(raw_data); 4703*71d10453SEric Joyner mask = ICE_AQC_NVM_LLDP_STATUS_M << 4704*71d10453SEric Joyner (ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport); 4705*71d10453SEric Joyner data = data & mask; 4706*71d10453SEric Joyner *lldp_status = data >> 4707*71d10453SEric Joyner (ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport); 4708*71d10453SEric Joyner } 4709*71d10453SEric Joyner 4710*71d10453SEric Joyner exit: 4711*71d10453SEric Joyner ice_release_nvm(hw); 4712*71d10453SEric Joyner 4713*71d10453SEric Joyner return ret; 4714*71d10453SEric Joyner } 4715*71d10453SEric Joyner 4716*71d10453SEric Joyner /** 4717*71d10453SEric Joyner * ice_get_netlist_ver_info 4718*71d10453SEric Joyner * @hw: pointer to the HW struct 4719*71d10453SEric Joyner * 4720*71d10453SEric Joyner * Get the netlist version information 4721*71d10453SEric Joyner */ 4722*71d10453SEric Joyner enum ice_status 4723*71d10453SEric Joyner ice_get_netlist_ver_info(struct ice_hw *hw) 4724*71d10453SEric Joyner { 4725*71d10453SEric Joyner struct ice_netlist_ver_info *ver = &hw->netlist_ver; 4726*71d10453SEric Joyner enum ice_status ret; 4727*71d10453SEric Joyner u32 id_blk_start; 4728*71d10453SEric Joyner __le16 raw_data; 4729*71d10453SEric Joyner u16 data, i; 4730*71d10453SEric Joyner u16 *buff; 4731*71d10453SEric Joyner 4732*71d10453SEric Joyner ret = ice_acquire_nvm(hw, ICE_RES_READ); 4733*71d10453SEric Joyner if (ret) 4734*71d10453SEric Joyner return ret; 4735*71d10453SEric Joyner buff = (u16 *)ice_calloc(hw, ICE_AQC_NVM_NETLIST_ID_BLK_LEN, 4736*71d10453SEric Joyner sizeof(*buff)); 4737*71d10453SEric Joyner if (!buff) { 4738*71d10453SEric Joyner ret = ICE_ERR_NO_MEMORY; 4739*71d10453SEric Joyner goto exit_no_mem; 4740*71d10453SEric Joyner } 4741*71d10453SEric Joyner 4742*71d10453SEric Joyner /* read module length */ 4743*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID, 4744*71d10453SEric Joyner ICE_AQC_NVM_LINK_TOPO_NETLIST_LEN_OFFSET * 2, 4745*71d10453SEric Joyner ICE_AQC_NVM_LINK_TOPO_NETLIST_LEN, &raw_data, 4746*71d10453SEric Joyner false, false, NULL); 4747*71d10453SEric Joyner if (ret) 4748*71d10453SEric Joyner goto exit_error; 4749*71d10453SEric Joyner 4750*71d10453SEric Joyner data = LE16_TO_CPU(raw_data); 4751*71d10453SEric Joyner /* exit if length is = 0 */ 4752*71d10453SEric Joyner if (!data) 4753*71d10453SEric Joyner goto exit_error; 4754*71d10453SEric Joyner 4755*71d10453SEric Joyner /* read node count */ 4756*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID, 4757*71d10453SEric Joyner ICE_AQC_NVM_NETLIST_NODE_COUNT_OFFSET * 2, 4758*71d10453SEric Joyner ICE_AQC_NVM_NETLIST_NODE_COUNT_LEN, &raw_data, 4759*71d10453SEric Joyner false, false, NULL); 4760*71d10453SEric Joyner if (ret) 4761*71d10453SEric Joyner goto exit_error; 4762*71d10453SEric Joyner data = LE16_TO_CPU(raw_data); 4763*71d10453SEric Joyner 4764*71d10453SEric Joyner /* netlist ID block starts from offset 4 + node count * 2 */ 4765*71d10453SEric Joyner id_blk_start = ICE_AQC_NVM_NETLIST_ID_BLK_START_OFFSET + data * 2; 4766*71d10453SEric Joyner 4767*71d10453SEric Joyner /* read the entire netlist ID block */ 4768*71d10453SEric Joyner ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID, 4769*71d10453SEric Joyner id_blk_start * 2, 4770*71d10453SEric Joyner ICE_AQC_NVM_NETLIST_ID_BLK_LEN * 2, buff, false, 4771*71d10453SEric Joyner false, NULL); 4772*71d10453SEric Joyner if (ret) 4773*71d10453SEric Joyner goto exit_error; 4774*71d10453SEric Joyner 4775*71d10453SEric Joyner for (i = 0; i < ICE_AQC_NVM_NETLIST_ID_BLK_LEN; i++) 4776*71d10453SEric Joyner buff[i] = LE16_TO_CPU(((_FORCE_ __le16 *)buff)[i]); 4777*71d10453SEric Joyner 4778*71d10453SEric Joyner ver->major = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_MAJOR_VER_HIGH] << 16) | 4779*71d10453SEric Joyner buff[ICE_AQC_NVM_NETLIST_ID_BLK_MAJOR_VER_LOW]; 4780*71d10453SEric Joyner ver->minor = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_MINOR_VER_HIGH] << 16) | 4781*71d10453SEric Joyner buff[ICE_AQC_NVM_NETLIST_ID_BLK_MINOR_VER_LOW]; 4782*71d10453SEric Joyner ver->type = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_TYPE_HIGH] << 16) | 4783*71d10453SEric Joyner buff[ICE_AQC_NVM_NETLIST_ID_BLK_TYPE_LOW]; 4784*71d10453SEric Joyner ver->rev = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_REV_HIGH] << 16) | 4785*71d10453SEric Joyner buff[ICE_AQC_NVM_NETLIST_ID_BLK_REV_LOW]; 4786*71d10453SEric Joyner ver->cust_ver = buff[ICE_AQC_NVM_NETLIST_ID_BLK_CUST_VER]; 4787*71d10453SEric Joyner /* Read the left most 4 bytes of SHA */ 4788*71d10453SEric Joyner ver->hash = buff[ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH + 15] << 16 | 4789*71d10453SEric Joyner buff[ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH + 14]; 4790*71d10453SEric Joyner 4791*71d10453SEric Joyner exit_error: 4792*71d10453SEric Joyner ice_free(hw, buff); 4793*71d10453SEric Joyner exit_no_mem: 4794*71d10453SEric Joyner ice_release_nvm(hw); 4795*71d10453SEric Joyner return ret; 4796*71d10453SEric Joyner } 4797*71d10453SEric Joyner 4798*71d10453SEric Joyner /** 4799*71d10453SEric Joyner * ice_fw_supports_link_override 4800*71d10453SEric Joyner * @hw: pointer to the hardware structure 4801*71d10453SEric Joyner * 4802*71d10453SEric Joyner * Checks if the firmware supports link override 4803*71d10453SEric Joyner */ 4804*71d10453SEric Joyner bool ice_fw_supports_link_override(struct ice_hw *hw) 4805*71d10453SEric Joyner { 4806*71d10453SEric Joyner if (hw->api_maj_ver == ICE_FW_API_LINK_OVERRIDE_MAJ) { 4807*71d10453SEric Joyner if (hw->api_min_ver > ICE_FW_API_LINK_OVERRIDE_MIN) 4808*71d10453SEric Joyner return true; 4809*71d10453SEric Joyner if (hw->api_min_ver == ICE_FW_API_LINK_OVERRIDE_MIN && 4810*71d10453SEric Joyner hw->api_patch >= ICE_FW_API_LINK_OVERRIDE_PATCH) 4811*71d10453SEric Joyner return true; 4812*71d10453SEric Joyner } else if (hw->api_maj_ver > ICE_FW_API_LINK_OVERRIDE_MAJ) { 4813*71d10453SEric Joyner return true; 4814*71d10453SEric Joyner } 4815*71d10453SEric Joyner 4816*71d10453SEric Joyner return false; 4817*71d10453SEric Joyner } 4818*71d10453SEric Joyner 4819*71d10453SEric Joyner /** 4820*71d10453SEric Joyner * ice_get_link_default_override 4821*71d10453SEric Joyner * @ldo: pointer to the link default override struct 4822*71d10453SEric Joyner * @pi: pointer to the port info struct 4823*71d10453SEric Joyner * 4824*71d10453SEric Joyner * Gets the link default override for a port 4825*71d10453SEric Joyner */ 4826*71d10453SEric Joyner enum ice_status 4827*71d10453SEric Joyner ice_get_link_default_override(struct ice_link_default_override_tlv *ldo, 4828*71d10453SEric Joyner struct ice_port_info *pi) 4829*71d10453SEric Joyner { 4830*71d10453SEric Joyner u16 i, tlv, tlv_len, tlv_start, buf, offset; 4831*71d10453SEric Joyner struct ice_hw *hw = pi->hw; 4832*71d10453SEric Joyner enum ice_status status; 4833*71d10453SEric Joyner 4834*71d10453SEric Joyner status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len, 4835*71d10453SEric Joyner ICE_SR_LINK_DEFAULT_OVERRIDE_PTR); 4836*71d10453SEric Joyner if (status) { 4837*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 4838*71d10453SEric Joyner "Failed to read link override TLV.\n"); 4839*71d10453SEric Joyner return status; 4840*71d10453SEric Joyner } 4841*71d10453SEric Joyner 4842*71d10453SEric Joyner /* Each port has its own config; calculate for our port */ 4843*71d10453SEric Joyner tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS + 4844*71d10453SEric Joyner ICE_SR_PFA_LINK_OVERRIDE_OFFSET; 4845*71d10453SEric Joyner 4846*71d10453SEric Joyner /* link options first */ 4847*71d10453SEric Joyner status = ice_read_sr_word(hw, tlv_start, &buf); 4848*71d10453SEric Joyner if (status) { 4849*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 4850*71d10453SEric Joyner "Failed to read override link options.\n"); 4851*71d10453SEric Joyner return status; 4852*71d10453SEric Joyner } 4853*71d10453SEric Joyner ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M; 4854*71d10453SEric Joyner ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >> 4855*71d10453SEric Joyner ICE_LINK_OVERRIDE_PHY_CFG_S; 4856*71d10453SEric Joyner 4857*71d10453SEric Joyner /* link PHY config */ 4858*71d10453SEric Joyner offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET; 4859*71d10453SEric Joyner status = ice_read_sr_word(hw, offset, &buf); 4860*71d10453SEric Joyner if (status) { 4861*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 4862*71d10453SEric Joyner "Failed to read override phy config.\n"); 4863*71d10453SEric Joyner return status; 4864*71d10453SEric Joyner } 4865*71d10453SEric Joyner ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M; 4866*71d10453SEric Joyner 4867*71d10453SEric Joyner /* PHY types low */ 4868*71d10453SEric Joyner offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET; 4869*71d10453SEric Joyner for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) { 4870*71d10453SEric Joyner status = ice_read_sr_word(hw, (offset + i), &buf); 4871*71d10453SEric Joyner if (status) { 4872*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 4873*71d10453SEric Joyner "Failed to read override link options.\n"); 4874*71d10453SEric Joyner return status; 4875*71d10453SEric Joyner } 4876*71d10453SEric Joyner /* shift 16 bits at a time to fill 64 bits */ 4877*71d10453SEric Joyner ldo->phy_type_low |= ((u64)buf << (i * 16)); 4878*71d10453SEric Joyner } 4879*71d10453SEric Joyner 4880*71d10453SEric Joyner /* PHY types high */ 4881*71d10453SEric Joyner offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET + 4882*71d10453SEric Joyner ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; 4883*71d10453SEric Joyner for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) { 4884*71d10453SEric Joyner status = ice_read_sr_word(hw, (offset + i), &buf); 4885*71d10453SEric Joyner if (status) { 4886*71d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, 4887*71d10453SEric Joyner "Failed to read override link options.\n"); 4888*71d10453SEric Joyner return status; 4889*71d10453SEric Joyner } 4890*71d10453SEric Joyner /* shift 16 bits at a time to fill 64 bits */ 4891*71d10453SEric Joyner ldo->phy_type_high |= ((u64)buf << (i * 16)); 4892*71d10453SEric Joyner } 4893*71d10453SEric Joyner 4894*71d10453SEric Joyner return status; 4895*71d10453SEric Joyner } 4896