xref: /freebsd/sys/dev/ice/ice_common.c (revision 7d7af7f85b88e052fe78321090283dfe903d25f4)
171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
271d10453SEric Joyner /*  Copyright (c) 2020, Intel Corporation
371d10453SEric Joyner  *  All rights reserved.
471d10453SEric Joyner  *
571d10453SEric Joyner  *  Redistribution and use in source and binary forms, with or without
671d10453SEric Joyner  *  modification, are permitted provided that the following conditions are met:
771d10453SEric Joyner  *
871d10453SEric Joyner  *   1. Redistributions of source code must retain the above copyright notice,
971d10453SEric Joyner  *      this list of conditions and the following disclaimer.
1071d10453SEric Joyner  *
1171d10453SEric Joyner  *   2. Redistributions in binary form must reproduce the above copyright
1271d10453SEric Joyner  *      notice, this list of conditions and the following disclaimer in the
1371d10453SEric Joyner  *      documentation and/or other materials provided with the distribution.
1471d10453SEric Joyner  *
1571d10453SEric Joyner  *   3. Neither the name of the Intel Corporation nor the names of its
1671d10453SEric Joyner  *      contributors may be used to endorse or promote products derived from
1771d10453SEric Joyner  *      this software without specific prior written permission.
1871d10453SEric Joyner  *
1971d10453SEric Joyner  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2071d10453SEric Joyner  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2171d10453SEric Joyner  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2271d10453SEric Joyner  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2371d10453SEric Joyner  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2471d10453SEric Joyner  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2571d10453SEric Joyner  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2671d10453SEric Joyner  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2771d10453SEric Joyner  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2871d10453SEric Joyner  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2971d10453SEric Joyner  *  POSSIBILITY OF SUCH DAMAGE.
3071d10453SEric Joyner  */
3171d10453SEric Joyner /*$FreeBSD$*/
3271d10453SEric Joyner 
3371d10453SEric Joyner #include "ice_common.h"
3471d10453SEric Joyner #include "ice_sched.h"
3571d10453SEric Joyner #include "ice_adminq_cmd.h"
3671d10453SEric Joyner 
3771d10453SEric Joyner #include "ice_flow.h"
3871d10453SEric Joyner #include "ice_switch.h"
3971d10453SEric Joyner 
4071d10453SEric Joyner #define ICE_PF_RESET_WAIT_COUNT	300
4171d10453SEric Joyner 
4271d10453SEric Joyner /**
4371d10453SEric Joyner  * ice_set_mac_type - Sets MAC type
4471d10453SEric Joyner  * @hw: pointer to the HW structure
4571d10453SEric Joyner  *
4671d10453SEric Joyner  * This function sets the MAC type of the adapter based on the
4771d10453SEric Joyner  * vendor ID and device ID stored in the HW structure.
4871d10453SEric Joyner  */
4971d10453SEric Joyner enum ice_status ice_set_mac_type(struct ice_hw *hw)
5071d10453SEric Joyner {
5171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
5271d10453SEric Joyner 
5371d10453SEric Joyner 	if (hw->vendor_id != ICE_INTEL_VENDOR_ID)
5471d10453SEric Joyner 		return ICE_ERR_DEVICE_NOT_SUPPORTED;
5571d10453SEric Joyner 
5671d10453SEric Joyner 	switch (hw->device_id) {
5771d10453SEric Joyner 	case ICE_DEV_ID_E810C_BACKPLANE:
5871d10453SEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
5971d10453SEric Joyner 	case ICE_DEV_ID_E810C_SFP:
6071d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_BACKPLANE:
6171d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_QSFP:
6271d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_SFP:
6371d10453SEric Joyner 		hw->mac_type = ICE_MAC_E810;
6471d10453SEric Joyner 		break;
6571d10453SEric Joyner 	case ICE_DEV_ID_E822C_10G_BASE_T:
6671d10453SEric Joyner 	case ICE_DEV_ID_E822C_BACKPLANE:
6771d10453SEric Joyner 	case ICE_DEV_ID_E822C_QSFP:
6871d10453SEric Joyner 	case ICE_DEV_ID_E822C_SFP:
6971d10453SEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
7071d10453SEric Joyner 	case ICE_DEV_ID_E822L_10G_BASE_T:
7171d10453SEric Joyner 	case ICE_DEV_ID_E822L_BACKPLANE:
7271d10453SEric Joyner 	case ICE_DEV_ID_E822L_SFP:
7371d10453SEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
7471d10453SEric Joyner 	case ICE_DEV_ID_E823L_10G_BASE_T:
7571d10453SEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
7671d10453SEric Joyner 	case ICE_DEV_ID_E823L_BACKPLANE:
7771d10453SEric Joyner 	case ICE_DEV_ID_E823L_QSFP:
7871d10453SEric Joyner 	case ICE_DEV_ID_E823L_SFP:
7971d10453SEric Joyner 		hw->mac_type = ICE_MAC_GENERIC;
8071d10453SEric Joyner 		break;
8171d10453SEric Joyner 	default:
8271d10453SEric Joyner 		hw->mac_type = ICE_MAC_UNKNOWN;
8371d10453SEric Joyner 		break;
8471d10453SEric Joyner 	}
8571d10453SEric Joyner 
8671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
8771d10453SEric Joyner 	return ICE_SUCCESS;
8871d10453SEric Joyner }
8971d10453SEric Joyner 
9071d10453SEric Joyner /**
9171d10453SEric Joyner  * ice_clear_pf_cfg - Clear PF configuration
9271d10453SEric Joyner  * @hw: pointer to the hardware structure
9371d10453SEric Joyner  *
9471d10453SEric Joyner  * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
9571d10453SEric Joyner  * configuration, flow director filters, etc.).
9671d10453SEric Joyner  */
9771d10453SEric Joyner enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
9871d10453SEric Joyner {
9971d10453SEric Joyner 	struct ice_aq_desc desc;
10071d10453SEric Joyner 
10171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
10271d10453SEric Joyner 
10371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
10471d10453SEric Joyner }
10571d10453SEric Joyner 
10671d10453SEric Joyner /**
10771d10453SEric Joyner  * ice_aq_manage_mac_read - manage MAC address read command
10871d10453SEric Joyner  * @hw: pointer to the HW struct
10971d10453SEric Joyner  * @buf: a virtual buffer to hold the manage MAC read response
11071d10453SEric Joyner  * @buf_size: Size of the virtual buffer
11171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
11271d10453SEric Joyner  *
11371d10453SEric Joyner  * This function is used to return per PF station MAC address (0x0107).
11471d10453SEric Joyner  * NOTE: Upon successful completion of this command, MAC address information
11571d10453SEric Joyner  * is returned in user specified buffer. Please interpret user specified
11671d10453SEric Joyner  * buffer as "manage_mac_read" response.
11771d10453SEric Joyner  * Response such as various MAC addresses are stored in HW struct (port.mac)
118*7d7af7f8SEric Joyner  * ice_discover_dev_caps is expected to be called before this function is
119*7d7af7f8SEric Joyner  * called.
12071d10453SEric Joyner  */
12171d10453SEric Joyner enum ice_status
12271d10453SEric Joyner ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
12371d10453SEric Joyner 		       struct ice_sq_cd *cd)
12471d10453SEric Joyner {
12571d10453SEric Joyner 	struct ice_aqc_manage_mac_read_resp *resp;
12671d10453SEric Joyner 	struct ice_aqc_manage_mac_read *cmd;
12771d10453SEric Joyner 	struct ice_aq_desc desc;
12871d10453SEric Joyner 	enum ice_status status;
12971d10453SEric Joyner 	u16 flags;
13071d10453SEric Joyner 	u8 i;
13171d10453SEric Joyner 
13271d10453SEric Joyner 	cmd = &desc.params.mac_read;
13371d10453SEric Joyner 
13471d10453SEric Joyner 	if (buf_size < sizeof(*resp))
13571d10453SEric Joyner 		return ICE_ERR_BUF_TOO_SHORT;
13671d10453SEric Joyner 
13771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
13871d10453SEric Joyner 
13971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
14071d10453SEric Joyner 	if (status)
14171d10453SEric Joyner 		return status;
14271d10453SEric Joyner 
14371d10453SEric Joyner 	resp = (struct ice_aqc_manage_mac_read_resp *)buf;
14471d10453SEric Joyner 	flags = LE16_TO_CPU(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
14571d10453SEric Joyner 
14671d10453SEric Joyner 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
14771d10453SEric Joyner 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
14871d10453SEric Joyner 		return ICE_ERR_CFG;
14971d10453SEric Joyner 	}
15071d10453SEric Joyner 
15171d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
15271d10453SEric Joyner 	for (i = 0; i < cmd->num_addr; i++)
15371d10453SEric Joyner 		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
15471d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.lan_addr,
15571d10453SEric Joyner 				   resp[i].mac_addr, ETH_ALEN,
15671d10453SEric Joyner 				   ICE_DMA_TO_NONDMA);
15771d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.perm_addr,
15871d10453SEric Joyner 				   resp[i].mac_addr,
15971d10453SEric Joyner 				   ETH_ALEN, ICE_DMA_TO_NONDMA);
16071d10453SEric Joyner 			break;
16171d10453SEric Joyner 		}
16271d10453SEric Joyner 	return ICE_SUCCESS;
16371d10453SEric Joyner }
16471d10453SEric Joyner 
16571d10453SEric Joyner /**
16671d10453SEric Joyner  * ice_aq_get_phy_caps - returns PHY capabilities
16771d10453SEric Joyner  * @pi: port information structure
16871d10453SEric Joyner  * @qual_mods: report qualified modules
16971d10453SEric Joyner  * @report_mode: report mode capabilities
17071d10453SEric Joyner  * @pcaps: structure for PHY capabilities to be filled
17171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
17271d10453SEric Joyner  *
17371d10453SEric Joyner  * Returns the various PHY capabilities supported on the Port (0x0600)
17471d10453SEric Joyner  */
17571d10453SEric Joyner enum ice_status
17671d10453SEric Joyner ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
17771d10453SEric Joyner 		    struct ice_aqc_get_phy_caps_data *pcaps,
17871d10453SEric Joyner 		    struct ice_sq_cd *cd)
17971d10453SEric Joyner {
18071d10453SEric Joyner 	struct ice_aqc_get_phy_caps *cmd;
18171d10453SEric Joyner 	u16 pcaps_size = sizeof(*pcaps);
18271d10453SEric Joyner 	struct ice_aq_desc desc;
18371d10453SEric Joyner 	enum ice_status status;
184*7d7af7f8SEric Joyner 	struct ice_hw *hw;
18571d10453SEric Joyner 
18671d10453SEric Joyner 	cmd = &desc.params.get_phy;
18771d10453SEric Joyner 
18871d10453SEric Joyner 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
18971d10453SEric Joyner 		return ICE_ERR_PARAM;
190*7d7af7f8SEric Joyner 	hw = pi->hw;
19171d10453SEric Joyner 
19271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
19371d10453SEric Joyner 
19471d10453SEric Joyner 	if (qual_mods)
19571d10453SEric Joyner 		cmd->param0 |= CPU_TO_LE16(ICE_AQC_GET_PHY_RQM);
19671d10453SEric Joyner 
19771d10453SEric Joyner 	cmd->param0 |= CPU_TO_LE16(report_mode);
198*7d7af7f8SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
199*7d7af7f8SEric Joyner 
200*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get phy caps - report_mode = 0x%x\n",
201*7d7af7f8SEric Joyner 		  report_mode);
202*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
203*7d7af7f8SEric Joyner 		  (unsigned long long)LE64_TO_CPU(pcaps->phy_type_low));
204*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
205*7d7af7f8SEric Joyner 		  (unsigned long long)LE64_TO_CPU(pcaps->phy_type_high));
206*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", pcaps->caps);
207*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
208*7d7af7f8SEric Joyner 		  pcaps->low_power_ctrl_an);
209*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", pcaps->eee_cap);
210*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n",
211*7d7af7f8SEric Joyner 		  pcaps->eeer_value);
212*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_fec_options = 0x%x\n",
213*7d7af7f8SEric Joyner 		  pcaps->link_fec_options);
214*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	module_compliance_enforcement = 0x%x\n",
215*7d7af7f8SEric Joyner 		  pcaps->module_compliance_enforcement);
216*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "   extended_compliance_code = 0x%x\n",
217*7d7af7f8SEric Joyner 		  pcaps->extended_compliance_code);
218*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "   module_type[0] = 0x%x\n",
219*7d7af7f8SEric Joyner 		  pcaps->module_type[0]);
220*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "   module_type[1] = 0x%x\n",
221*7d7af7f8SEric Joyner 		  pcaps->module_type[1]);
222*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "   module_type[2] = 0x%x\n",
223*7d7af7f8SEric Joyner 		  pcaps->module_type[2]);
22471d10453SEric Joyner 
22571d10453SEric Joyner 	if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP) {
22671d10453SEric Joyner 		pi->phy.phy_type_low = LE64_TO_CPU(pcaps->phy_type_low);
22771d10453SEric Joyner 		pi->phy.phy_type_high = LE64_TO_CPU(pcaps->phy_type_high);
228*7d7af7f8SEric Joyner 		ice_memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
229*7d7af7f8SEric Joyner 			   sizeof(pi->phy.link_info.module_type),
230*7d7af7f8SEric Joyner 			   ICE_NONDMA_TO_NONDMA);
23171d10453SEric Joyner 	}
23271d10453SEric Joyner 
23371d10453SEric Joyner 	return status;
23471d10453SEric Joyner }
23571d10453SEric Joyner 
23671d10453SEric Joyner /**
23771d10453SEric Joyner  * ice_aq_get_link_topo_handle - get link topology node return status
23871d10453SEric Joyner  * @pi: port information structure
23971d10453SEric Joyner  * @node_type: requested node type
24071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
24171d10453SEric Joyner  *
24271d10453SEric Joyner  * Get link topology node return status for specified node type (0x06E0)
24371d10453SEric Joyner  *
24471d10453SEric Joyner  * Node type cage can be used to determine if cage is present. If AQC
24571d10453SEric Joyner  * returns error (ENOENT), then no cage present. If no cage present, then
24671d10453SEric Joyner  * connection type is backplane or BASE-T.
24771d10453SEric Joyner  */
24871d10453SEric Joyner static enum ice_status
24971d10453SEric Joyner ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
25071d10453SEric Joyner 			    struct ice_sq_cd *cd)
25171d10453SEric Joyner {
25271d10453SEric Joyner 	struct ice_aqc_get_link_topo *cmd;
25371d10453SEric Joyner 	struct ice_aq_desc desc;
25471d10453SEric Joyner 
25571d10453SEric Joyner 	cmd = &desc.params.get_link_topo;
25671d10453SEric Joyner 
25771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
25871d10453SEric Joyner 
25971d10453SEric Joyner 	cmd->addr.node_type_ctx = (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
26071d10453SEric Joyner 				   ICE_AQC_LINK_TOPO_NODE_CTX_S);
26171d10453SEric Joyner 
26271d10453SEric Joyner 	/* set node type */
26371d10453SEric Joyner 	cmd->addr.node_type_ctx |= (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
26471d10453SEric Joyner 
26571d10453SEric Joyner 	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
26671d10453SEric Joyner }
26771d10453SEric Joyner 
26871d10453SEric Joyner /*
26971d10453SEric Joyner  * ice_is_media_cage_present
27071d10453SEric Joyner  * @pi: port information structure
27171d10453SEric Joyner  *
27271d10453SEric Joyner  * Returns true if media cage is present, else false. If no cage, then
27371d10453SEric Joyner  * media type is backplane or BASE-T.
27471d10453SEric Joyner  */
27571d10453SEric Joyner static bool ice_is_media_cage_present(struct ice_port_info *pi)
27671d10453SEric Joyner {
27771d10453SEric Joyner 	/* Node type cage can be used to determine if cage is present. If AQC
27871d10453SEric Joyner 	 * returns error (ENOENT), then no cage present. If no cage present then
27971d10453SEric Joyner 	 * connection type is backplane or BASE-T.
28071d10453SEric Joyner 	 */
28171d10453SEric Joyner 	return !ice_aq_get_link_topo_handle(pi,
28271d10453SEric Joyner 					    ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE,
28371d10453SEric Joyner 					    NULL);
28471d10453SEric Joyner }
28571d10453SEric Joyner 
28671d10453SEric Joyner /**
28771d10453SEric Joyner  * ice_get_media_type - Gets media type
28871d10453SEric Joyner  * @pi: port information structure
28971d10453SEric Joyner  */
29071d10453SEric Joyner static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
29171d10453SEric Joyner {
29271d10453SEric Joyner 	struct ice_link_status *hw_link_info;
29371d10453SEric Joyner 
29471d10453SEric Joyner 	if (!pi)
29571d10453SEric Joyner 		return ICE_MEDIA_UNKNOWN;
29671d10453SEric Joyner 
29771d10453SEric Joyner 	hw_link_info = &pi->phy.link_info;
29871d10453SEric Joyner 	if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
29971d10453SEric Joyner 		/* If more than one media type is selected, report unknown */
30071d10453SEric Joyner 		return ICE_MEDIA_UNKNOWN;
30171d10453SEric Joyner 
30271d10453SEric Joyner 	if (hw_link_info->phy_type_low) {
303*7d7af7f8SEric Joyner 		/* 1G SGMII is a special case where some DA cable PHYs
304*7d7af7f8SEric Joyner 		 * may show this as an option when it really shouldn't
305*7d7af7f8SEric Joyner 		 * be since SGMII is meant to be between a MAC and a PHY
306*7d7af7f8SEric Joyner 		 * in a backplane. Try to detect this case and handle it
307*7d7af7f8SEric Joyner 		 */
308*7d7af7f8SEric Joyner 		if (hw_link_info->phy_type_low == ICE_PHY_TYPE_LOW_1G_SGMII &&
309*7d7af7f8SEric Joyner 		    (hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
310*7d7af7f8SEric Joyner 		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
311*7d7af7f8SEric Joyner 		    hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
312*7d7af7f8SEric Joyner 		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
313*7d7af7f8SEric Joyner 			return ICE_MEDIA_DA;
314*7d7af7f8SEric Joyner 
31571d10453SEric Joyner 		switch (hw_link_info->phy_type_low) {
31671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_SX:
31771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_LX:
31871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_SR:
31971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_LR:
32071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
32171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_SR:
32271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_LR:
32371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_SR4:
32471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_LR4:
32571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_SR2:
32671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_LR2:
32771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_SR:
32871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_FR:
32971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_LR:
33071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_SR4:
33171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_LR4:
33271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_SR2:
33371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_DR:
33471d10453SEric Joyner 			return ICE_MEDIA_FIBER;
335*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
336*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
337*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
338*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
339*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
340*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
341*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
342*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
343*7d7af7f8SEric Joyner 			return ICE_MEDIA_FIBER;
34471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100BASE_TX:
34571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_T:
34671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_2500BASE_T:
34771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_5GBASE_T:
34871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_T:
34971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_T:
35071d10453SEric Joyner 			return ICE_MEDIA_BASET;
35171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10G_SFI_DA:
35271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_CR:
35371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
35471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_CR1:
35571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_CR4:
35671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_CR2:
35771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_CP:
35871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_CR4:
35971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
36071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_CP2:
36171d10453SEric Joyner 			return ICE_MEDIA_DA;
36271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
36371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40G_XLAUI:
36471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_LAUI2:
36571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI2:
36671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI1:
36771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_AUI4:
36871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_CAUI4:
36971d10453SEric Joyner 			if (ice_is_media_cage_present(pi))
370*7d7af7f8SEric Joyner 				return ICE_MEDIA_AUI;
37171d10453SEric Joyner 			/* fall-through */
37271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_KX:
37371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_2500BASE_KX:
37471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_2500BASE_X:
37571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_5GBASE_KR:
37671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
37771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_KR:
37871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_KR1:
37971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
38071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_KR4:
38171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
38271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_KR2:
38371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_KR4:
38471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
38571d10453SEric Joyner 			return ICE_MEDIA_BACKPLANE;
38671d10453SEric Joyner 		}
38771d10453SEric Joyner 	} else {
38871d10453SEric Joyner 		switch (hw_link_info->phy_type_high) {
38971d10453SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_AUI2:
390*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_CAUI2:
39171d10453SEric Joyner 			if (ice_is_media_cage_present(pi))
392*7d7af7f8SEric Joyner 				return ICE_MEDIA_AUI;
39371d10453SEric Joyner 			/* fall-through */
39471d10453SEric Joyner 		case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
39571d10453SEric Joyner 			return ICE_MEDIA_BACKPLANE;
396*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
397*7d7af7f8SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
398*7d7af7f8SEric Joyner 			return ICE_MEDIA_FIBER;
39971d10453SEric Joyner 		}
40071d10453SEric Joyner 	}
40171d10453SEric Joyner 	return ICE_MEDIA_UNKNOWN;
40271d10453SEric Joyner }
40371d10453SEric Joyner 
40471d10453SEric Joyner /**
40571d10453SEric Joyner  * ice_aq_get_link_info
40671d10453SEric Joyner  * @pi: port information structure
40771d10453SEric Joyner  * @ena_lse: enable/disable LinkStatusEvent reporting
40871d10453SEric Joyner  * @link: pointer to link status structure - optional
40971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
41071d10453SEric Joyner  *
41171d10453SEric Joyner  * Get Link Status (0x607). Returns the link status of the adapter.
41271d10453SEric Joyner  */
41371d10453SEric Joyner enum ice_status
41471d10453SEric Joyner ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
41571d10453SEric Joyner 		     struct ice_link_status *link, struct ice_sq_cd *cd)
41671d10453SEric Joyner {
41771d10453SEric Joyner 	struct ice_aqc_get_link_status_data link_data = { 0 };
41871d10453SEric Joyner 	struct ice_aqc_get_link_status *resp;
41971d10453SEric Joyner 	struct ice_link_status *li_old, *li;
42071d10453SEric Joyner 	enum ice_media_type *hw_media_type;
42171d10453SEric Joyner 	struct ice_fc_info *hw_fc_info;
42271d10453SEric Joyner 	bool tx_pause, rx_pause;
42371d10453SEric Joyner 	struct ice_aq_desc desc;
42471d10453SEric Joyner 	enum ice_status status;
42571d10453SEric Joyner 	struct ice_hw *hw;
42671d10453SEric Joyner 	u16 cmd_flags;
42771d10453SEric Joyner 
42871d10453SEric Joyner 	if (!pi)
42971d10453SEric Joyner 		return ICE_ERR_PARAM;
43071d10453SEric Joyner 	hw = pi->hw;
43171d10453SEric Joyner 
43271d10453SEric Joyner 	li_old = &pi->phy.link_info_old;
43371d10453SEric Joyner 	hw_media_type = &pi->phy.media_type;
43471d10453SEric Joyner 	li = &pi->phy.link_info;
43571d10453SEric Joyner 	hw_fc_info = &pi->fc;
43671d10453SEric Joyner 
43771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
43871d10453SEric Joyner 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
43971d10453SEric Joyner 	resp = &desc.params.get_link_status;
44071d10453SEric Joyner 	resp->cmd_flags = CPU_TO_LE16(cmd_flags);
44171d10453SEric Joyner 	resp->lport_num = pi->lport;
44271d10453SEric Joyner 
44371d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);
44471d10453SEric Joyner 
44571d10453SEric Joyner 	if (status != ICE_SUCCESS)
44671d10453SEric Joyner 		return status;
44771d10453SEric Joyner 
44871d10453SEric Joyner 	/* save off old link status information */
44971d10453SEric Joyner 	*li_old = *li;
45071d10453SEric Joyner 
45171d10453SEric Joyner 	/* update current link status information */
45271d10453SEric Joyner 	li->link_speed = LE16_TO_CPU(link_data.link_speed);
45371d10453SEric Joyner 	li->phy_type_low = LE64_TO_CPU(link_data.phy_type_low);
45471d10453SEric Joyner 	li->phy_type_high = LE64_TO_CPU(link_data.phy_type_high);
45571d10453SEric Joyner 	*hw_media_type = ice_get_media_type(pi);
45671d10453SEric Joyner 	li->link_info = link_data.link_info;
45771d10453SEric Joyner 	li->an_info = link_data.an_info;
45871d10453SEric Joyner 	li->ext_info = link_data.ext_info;
45971d10453SEric Joyner 	li->max_frame_size = LE16_TO_CPU(link_data.max_frame_size);
46071d10453SEric Joyner 	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
46171d10453SEric Joyner 	li->topo_media_conflict = link_data.topo_media_conflict;
46271d10453SEric Joyner 	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
46371d10453SEric Joyner 				      ICE_AQ_CFG_PACING_TYPE_M);
46471d10453SEric Joyner 
46571d10453SEric Joyner 	/* update fc info */
46671d10453SEric Joyner 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
46771d10453SEric Joyner 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
46871d10453SEric Joyner 	if (tx_pause && rx_pause)
46971d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_FULL;
47071d10453SEric Joyner 	else if (tx_pause)
47171d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
47271d10453SEric Joyner 	else if (rx_pause)
47371d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
47471d10453SEric Joyner 	else
47571d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_NONE;
47671d10453SEric Joyner 
47771d10453SEric Joyner 	li->lse_ena = !!(resp->cmd_flags & CPU_TO_LE16(ICE_AQ_LSE_IS_ENABLED));
47871d10453SEric Joyner 
479*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get link info\n");
48071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_speed = 0x%x\n", li->link_speed);
48171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
48271d10453SEric Joyner 		  (unsigned long long)li->phy_type_low);
48371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
48471d10453SEric Joyner 		  (unsigned long long)li->phy_type_high);
48571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	media_type = 0x%x\n", *hw_media_type);
48671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_info = 0x%x\n", li->link_info);
48771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	an_info = 0x%x\n", li->an_info);
48871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	ext_info = 0x%x\n", li->ext_info);
489*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	fec_info = 0x%x\n", li->fec_info);
49071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	lse_ena = 0x%x\n", li->lse_ena);
491*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	max_frame = 0x%x\n",
492*7d7af7f8SEric Joyner 		  li->max_frame_size);
49371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	pacing = 0x%x\n", li->pacing);
49471d10453SEric Joyner 
49571d10453SEric Joyner 	/* save link status information */
49671d10453SEric Joyner 	if (link)
49771d10453SEric Joyner 		*link = *li;
49871d10453SEric Joyner 
49971d10453SEric Joyner 	/* flag cleared so calling functions don't call AQ again */
50071d10453SEric Joyner 	pi->phy.get_link_info = false;
50171d10453SEric Joyner 
50271d10453SEric Joyner 	return ICE_SUCCESS;
50371d10453SEric Joyner }
50471d10453SEric Joyner 
50571d10453SEric Joyner /**
506*7d7af7f8SEric Joyner  * ice_fill_tx_timer_and_fc_thresh
50771d10453SEric Joyner  * @hw: pointer to the HW struct
508*7d7af7f8SEric Joyner  * @cmd: pointer to MAC cfg structure
50971d10453SEric Joyner  *
510*7d7af7f8SEric Joyner  * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
511*7d7af7f8SEric Joyner  * descriptor
51271d10453SEric Joyner  */
513*7d7af7f8SEric Joyner static void
514*7d7af7f8SEric Joyner ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
515*7d7af7f8SEric Joyner 				struct ice_aqc_set_mac_cfg *cmd)
51671d10453SEric Joyner {
517*7d7af7f8SEric Joyner 	u16 fc_thres_val, tx_timer_val;
518*7d7af7f8SEric Joyner 	u32 val;
51971d10453SEric Joyner 
52071d10453SEric Joyner 	/* We read back the transmit timer and fc threshold value of
52171d10453SEric Joyner 	 * LFC. Thus, we will use index =
52271d10453SEric Joyner 	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
52371d10453SEric Joyner 	 *
52471d10453SEric Joyner 	 * Also, because we are opearating on transmit timer and fc
52571d10453SEric Joyner 	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
52671d10453SEric Joyner 	 */
52771d10453SEric Joyner #define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
52871d10453SEric Joyner 
52971d10453SEric Joyner 	/* Retrieve the transmit timer */
530*7d7af7f8SEric Joyner 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
531*7d7af7f8SEric Joyner 	tx_timer_val = val &
53271d10453SEric Joyner 		PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
53371d10453SEric Joyner 	cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
53471d10453SEric Joyner 
53571d10453SEric Joyner 	/* Retrieve the fc threshold */
536*7d7af7f8SEric Joyner 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
537*7d7af7f8SEric Joyner 	fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
538*7d7af7f8SEric Joyner 
539*7d7af7f8SEric Joyner 	cmd->fc_refresh_threshold = CPU_TO_LE16(fc_thres_val);
540*7d7af7f8SEric Joyner }
541*7d7af7f8SEric Joyner 
542*7d7af7f8SEric Joyner /**
543*7d7af7f8SEric Joyner  * ice_aq_set_mac_cfg
544*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
545*7d7af7f8SEric Joyner  * @max_frame_size: Maximum Frame Size to be supported
546*7d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
547*7d7af7f8SEric Joyner  *
548*7d7af7f8SEric Joyner  * Set MAC configuration (0x0603)
549*7d7af7f8SEric Joyner  */
550*7d7af7f8SEric Joyner enum ice_status
551*7d7af7f8SEric Joyner ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
552*7d7af7f8SEric Joyner {
553*7d7af7f8SEric Joyner 	struct ice_aqc_set_mac_cfg *cmd;
554*7d7af7f8SEric Joyner 	struct ice_aq_desc desc;
555*7d7af7f8SEric Joyner 
556*7d7af7f8SEric Joyner 	cmd = &desc.params.set_mac_cfg;
557*7d7af7f8SEric Joyner 
558*7d7af7f8SEric Joyner 	if (max_frame_size == 0)
559*7d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
560*7d7af7f8SEric Joyner 
561*7d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
562*7d7af7f8SEric Joyner 
563*7d7af7f8SEric Joyner 	cmd->max_frame_size = CPU_TO_LE16(max_frame_size);
564*7d7af7f8SEric Joyner 
565*7d7af7f8SEric Joyner 	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
56671d10453SEric Joyner 
56771d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
56871d10453SEric Joyner }
56971d10453SEric Joyner 
57071d10453SEric Joyner /**
57171d10453SEric Joyner  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
57271d10453SEric Joyner  * @hw: pointer to the HW struct
57371d10453SEric Joyner  */
57471d10453SEric Joyner static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
57571d10453SEric Joyner {
57671d10453SEric Joyner 	struct ice_switch_info *sw;
577*7d7af7f8SEric Joyner 	enum ice_status status;
57871d10453SEric Joyner 
57971d10453SEric Joyner 	hw->switch_info = (struct ice_switch_info *)
58071d10453SEric Joyner 			  ice_malloc(hw, sizeof(*hw->switch_info));
58171d10453SEric Joyner 
58271d10453SEric Joyner 	sw = hw->switch_info;
58371d10453SEric Joyner 
58471d10453SEric Joyner 	if (!sw)
58571d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
58671d10453SEric Joyner 
58771d10453SEric Joyner 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
588*7d7af7f8SEric Joyner 	sw->prof_res_bm_init = 0;
58971d10453SEric Joyner 
590*7d7af7f8SEric Joyner 	status = ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
591*7d7af7f8SEric Joyner 	if (status) {
592*7d7af7f8SEric Joyner 		ice_free(hw, hw->switch_info);
593*7d7af7f8SEric Joyner 		return status;
594*7d7af7f8SEric Joyner 	}
595*7d7af7f8SEric Joyner 	return ICE_SUCCESS;
59671d10453SEric Joyner }
59771d10453SEric Joyner 
59871d10453SEric Joyner /**
599*7d7af7f8SEric Joyner  * ice_cleanup_fltr_mgmt_single - clears single filter mngt struct
60071d10453SEric Joyner  * @hw: pointer to the HW struct
601*7d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function clears filters
60271d10453SEric Joyner  */
603*7d7af7f8SEric Joyner static void
604*7d7af7f8SEric Joyner ice_cleanup_fltr_mgmt_single(struct ice_hw *hw, struct ice_switch_info *sw)
60571d10453SEric Joyner {
60671d10453SEric Joyner 	struct ice_vsi_list_map_info *v_pos_map;
60771d10453SEric Joyner 	struct ice_vsi_list_map_info *v_tmp_map;
60871d10453SEric Joyner 	struct ice_sw_recipe *recps;
60971d10453SEric Joyner 	u8 i;
61071d10453SEric Joyner 
611*7d7af7f8SEric Joyner 	if (!sw)
612*7d7af7f8SEric Joyner 		return;
613*7d7af7f8SEric Joyner 
61471d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
61571d10453SEric Joyner 				 ice_vsi_list_map_info, list_entry) {
61671d10453SEric Joyner 		LIST_DEL(&v_pos_map->list_entry);
61771d10453SEric Joyner 		ice_free(hw, v_pos_map);
61871d10453SEric Joyner 	}
619*7d7af7f8SEric Joyner 	recps = sw->recp_list;
62071d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
62171d10453SEric Joyner 		struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
62271d10453SEric Joyner 
62371d10453SEric Joyner 		recps[i].root_rid = i;
62471d10453SEric Joyner 		LIST_FOR_EACH_ENTRY_SAFE(rg_entry, tmprg_entry,
62571d10453SEric Joyner 					 &recps[i].rg_list, ice_recp_grp_entry,
62671d10453SEric Joyner 					 l_entry) {
62771d10453SEric Joyner 			LIST_DEL(&rg_entry->l_entry);
62871d10453SEric Joyner 			ice_free(hw, rg_entry);
62971d10453SEric Joyner 		}
63071d10453SEric Joyner 
63171d10453SEric Joyner 		if (recps[i].adv_rule) {
63271d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
63371d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *lst_itr;
63471d10453SEric Joyner 
63571d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
63671d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
63771d10453SEric Joyner 						 &recps[i].filt_rules,
63871d10453SEric Joyner 						 ice_adv_fltr_mgmt_list_entry,
63971d10453SEric Joyner 						 list_entry) {
64071d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
64171d10453SEric Joyner 				ice_free(hw, lst_itr->lkups);
64271d10453SEric Joyner 				ice_free(hw, lst_itr);
64371d10453SEric Joyner 			}
64471d10453SEric Joyner 		} else {
64571d10453SEric Joyner 			struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
64671d10453SEric Joyner 
64771d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
64871d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
64971d10453SEric Joyner 						 &recps[i].filt_rules,
65071d10453SEric Joyner 						 ice_fltr_mgmt_list_entry,
65171d10453SEric Joyner 						 list_entry) {
65271d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
65371d10453SEric Joyner 				ice_free(hw, lst_itr);
65471d10453SEric Joyner 			}
65571d10453SEric Joyner 		}
65671d10453SEric Joyner 		if (recps[i].root_buf)
65771d10453SEric Joyner 			ice_free(hw, recps[i].root_buf);
65871d10453SEric Joyner 	}
659*7d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
66071d10453SEric Joyner 	ice_free(hw, sw->recp_list);
66171d10453SEric Joyner 	ice_free(hw, sw);
66271d10453SEric Joyner }
66371d10453SEric Joyner 
66471d10453SEric Joyner /**
665*7d7af7f8SEric Joyner  * ice_cleanup_all_fltr_mgmt - cleanup filter management list and locks
666*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
667*7d7af7f8SEric Joyner  */
668*7d7af7f8SEric Joyner static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
669*7d7af7f8SEric Joyner {
670*7d7af7f8SEric Joyner 	ice_cleanup_fltr_mgmt_single(hw, hw->switch_info);
671*7d7af7f8SEric Joyner }
672*7d7af7f8SEric Joyner 
673*7d7af7f8SEric Joyner /**
67471d10453SEric Joyner  * ice_get_itr_intrl_gran
67571d10453SEric Joyner  * @hw: pointer to the HW struct
67671d10453SEric Joyner  *
67771d10453SEric Joyner  * Determines the ITR/INTRL granularities based on the maximum aggregate
67871d10453SEric Joyner  * bandwidth according to the device's configuration during power-on.
67971d10453SEric Joyner  */
68071d10453SEric Joyner static void ice_get_itr_intrl_gran(struct ice_hw *hw)
68171d10453SEric Joyner {
68271d10453SEric Joyner 	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
68371d10453SEric Joyner 			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
68471d10453SEric Joyner 			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
68571d10453SEric Joyner 
68671d10453SEric Joyner 	switch (max_agg_bw) {
68771d10453SEric Joyner 	case ICE_MAX_AGG_BW_200G:
68871d10453SEric Joyner 	case ICE_MAX_AGG_BW_100G:
68971d10453SEric Joyner 	case ICE_MAX_AGG_BW_50G:
69071d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
69171d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
69271d10453SEric Joyner 		break;
69371d10453SEric Joyner 	case ICE_MAX_AGG_BW_25G:
69471d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
69571d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
69671d10453SEric Joyner 		break;
69771d10453SEric Joyner 	}
69871d10453SEric Joyner }
69971d10453SEric Joyner 
70071d10453SEric Joyner /**
70171d10453SEric Joyner  * ice_print_rollback_msg - print FW rollback message
70271d10453SEric Joyner  * @hw: pointer to the hardware structure
70371d10453SEric Joyner  */
70471d10453SEric Joyner void ice_print_rollback_msg(struct ice_hw *hw)
70571d10453SEric Joyner {
70671d10453SEric Joyner 	char nvm_str[ICE_NVM_VER_LEN] = { 0 };
70771d10453SEric Joyner 	struct ice_nvm_info *nvm = &hw->nvm;
70871d10453SEric Joyner 	struct ice_orom_info *orom;
70971d10453SEric Joyner 
71071d10453SEric Joyner 	orom = &nvm->orom;
71171d10453SEric Joyner 
71271d10453SEric Joyner 	SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d",
71371d10453SEric Joyner 		 nvm->major_ver, nvm->minor_ver, nvm->eetrack, orom->major,
71471d10453SEric Joyner 		 orom->build, orom->patch);
71571d10453SEric Joyner 	ice_warn(hw,
71671d10453SEric 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",
71771d10453SEric Joyner 		 nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
71871d10453SEric Joyner }
71971d10453SEric Joyner 
72071d10453SEric Joyner /**
72171d10453SEric Joyner  * ice_init_hw - main hardware initialization routine
72271d10453SEric Joyner  * @hw: pointer to the hardware structure
72371d10453SEric Joyner  */
72471d10453SEric Joyner enum ice_status ice_init_hw(struct ice_hw *hw)
72571d10453SEric Joyner {
72671d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
72771d10453SEric Joyner 	enum ice_status status;
72871d10453SEric Joyner 	u16 mac_buf_len;
72971d10453SEric Joyner 	void *mac_buf;
73071d10453SEric Joyner 
73171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
73271d10453SEric Joyner 
73371d10453SEric Joyner 	/* Set MAC type based on DeviceID */
73471d10453SEric Joyner 	status = ice_set_mac_type(hw);
73571d10453SEric Joyner 	if (status)
73671d10453SEric Joyner 		return status;
73771d10453SEric Joyner 
73871d10453SEric Joyner 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
73971d10453SEric Joyner 			 PF_FUNC_RID_FUNCTION_NUMBER_M) >>
74071d10453SEric Joyner 		PF_FUNC_RID_FUNCTION_NUMBER_S;
74171d10453SEric Joyner 
74271d10453SEric Joyner 	status = ice_reset(hw, ICE_RESET_PFR);
74371d10453SEric Joyner 	if (status)
74471d10453SEric Joyner 		return status;
74571d10453SEric Joyner 	ice_get_itr_intrl_gran(hw);
74671d10453SEric Joyner 
74771d10453SEric Joyner 	status = ice_create_all_ctrlq(hw);
74871d10453SEric Joyner 	if (status)
74971d10453SEric Joyner 		goto err_unroll_cqinit;
75071d10453SEric Joyner 
75171d10453SEric Joyner 	status = ice_init_nvm(hw);
75271d10453SEric Joyner 	if (status)
75371d10453SEric Joyner 		goto err_unroll_cqinit;
75471d10453SEric Joyner 
75571d10453SEric Joyner 	if (ice_get_fw_mode(hw) == ICE_FW_MODE_ROLLBACK)
75671d10453SEric Joyner 		ice_print_rollback_msg(hw);
75771d10453SEric Joyner 
75871d10453SEric Joyner 	status = ice_clear_pf_cfg(hw);
75971d10453SEric Joyner 	if (status)
76071d10453SEric Joyner 		goto err_unroll_cqinit;
76171d10453SEric Joyner 
76271d10453SEric Joyner 	ice_clear_pxe_mode(hw);
76371d10453SEric Joyner 
76471d10453SEric Joyner 	status = ice_get_caps(hw);
76571d10453SEric Joyner 	if (status)
76671d10453SEric Joyner 		goto err_unroll_cqinit;
76771d10453SEric Joyner 
76871d10453SEric Joyner 	hw->port_info = (struct ice_port_info *)
76971d10453SEric Joyner 			ice_malloc(hw, sizeof(*hw->port_info));
77071d10453SEric Joyner 	if (!hw->port_info) {
77171d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
77271d10453SEric Joyner 		goto err_unroll_cqinit;
77371d10453SEric Joyner 	}
77471d10453SEric Joyner 
77571d10453SEric Joyner 	/* set the back pointer to HW */
77671d10453SEric Joyner 	hw->port_info->hw = hw;
77771d10453SEric Joyner 
77871d10453SEric Joyner 	/* Initialize port_info struct with switch configuration data */
77971d10453SEric Joyner 	status = ice_get_initial_sw_cfg(hw);
78071d10453SEric Joyner 	if (status)
78171d10453SEric Joyner 		goto err_unroll_alloc;
78271d10453SEric Joyner 
78371d10453SEric Joyner 	hw->evb_veb = true;
78471d10453SEric Joyner 	/* Query the allocated resources for Tx scheduler */
78571d10453SEric Joyner 	status = ice_sched_query_res_alloc(hw);
78671d10453SEric Joyner 	if (status) {
787*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
78871d10453SEric Joyner 		goto err_unroll_alloc;
78971d10453SEric Joyner 	}
79071d10453SEric Joyner 	ice_sched_get_psm_clk_freq(hw);
79171d10453SEric Joyner 
79271d10453SEric Joyner 	/* Initialize port_info struct with scheduler data */
79371d10453SEric Joyner 	status = ice_sched_init_port(hw->port_info);
79471d10453SEric Joyner 	if (status)
79571d10453SEric Joyner 		goto err_unroll_sched;
79671d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
79771d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
79871d10453SEric Joyner 	if (!pcaps) {
79971d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
80071d10453SEric Joyner 		goto err_unroll_sched;
80171d10453SEric Joyner 	}
80271d10453SEric Joyner 
80371d10453SEric Joyner 	/* Initialize port_info struct with PHY capabilities */
80471d10453SEric Joyner 	status = ice_aq_get_phy_caps(hw->port_info, false,
80571d10453SEric Joyner 				     ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL);
80671d10453SEric Joyner 	ice_free(hw, pcaps);
80771d10453SEric Joyner 	if (status)
808*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "%s: Get PHY capabilities failed, continuing anyway\n",
809*7d7af7f8SEric Joyner 			  __func__);
81071d10453SEric Joyner 
81171d10453SEric Joyner 	/* Initialize port_info struct with link information */
81271d10453SEric Joyner 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
81371d10453SEric Joyner 	if (status)
81471d10453SEric Joyner 		goto err_unroll_sched;
81571d10453SEric Joyner 	/* need a valid SW entry point to build a Tx tree */
81671d10453SEric Joyner 	if (!hw->sw_entry_point_layer) {
81771d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
81871d10453SEric Joyner 		status = ICE_ERR_CFG;
81971d10453SEric Joyner 		goto err_unroll_sched;
82071d10453SEric Joyner 	}
82171d10453SEric Joyner 	INIT_LIST_HEAD(&hw->agg_list);
82271d10453SEric Joyner 	/* Initialize max burst size */
82371d10453SEric Joyner 	if (!hw->max_burst_size)
82471d10453SEric Joyner 		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
82571d10453SEric Joyner 	status = ice_init_fltr_mgmt_struct(hw);
82671d10453SEric Joyner 	if (status)
82771d10453SEric Joyner 		goto err_unroll_sched;
82871d10453SEric Joyner 
82971d10453SEric Joyner 	/* Get MAC information */
83071d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
83171d10453SEric Joyner 	mac_buf = ice_calloc(hw, 2,
83271d10453SEric Joyner 			     sizeof(struct ice_aqc_manage_mac_read_resp));
83371d10453SEric Joyner 	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
83471d10453SEric Joyner 
83571d10453SEric Joyner 	if (!mac_buf) {
83671d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
83771d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
83871d10453SEric Joyner 	}
83971d10453SEric Joyner 
84071d10453SEric Joyner 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
84171d10453SEric Joyner 	ice_free(hw, mac_buf);
84271d10453SEric Joyner 
84371d10453SEric Joyner 	if (status)
84471d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
845*7d7af7f8SEric Joyner 	/* enable jumbo frame support at MAC level */
846*7d7af7f8SEric Joyner 	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
847*7d7af7f8SEric Joyner 	if (status)
848*7d7af7f8SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
84971d10453SEric Joyner 	status = ice_init_hw_tbls(hw);
85071d10453SEric Joyner 	if (status)
85171d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
85271d10453SEric Joyner 	ice_init_lock(&hw->tnl_lock);
85371d10453SEric Joyner 	return ICE_SUCCESS;
85471d10453SEric Joyner 
85571d10453SEric Joyner err_unroll_fltr_mgmt_struct:
85671d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
85771d10453SEric Joyner err_unroll_sched:
85871d10453SEric Joyner 	ice_sched_cleanup_all(hw);
85971d10453SEric Joyner err_unroll_alloc:
86071d10453SEric Joyner 	ice_free(hw, hw->port_info);
86171d10453SEric Joyner 	hw->port_info = NULL;
86271d10453SEric Joyner err_unroll_cqinit:
86371d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
86471d10453SEric Joyner 	return status;
86571d10453SEric Joyner }
86671d10453SEric Joyner 
86771d10453SEric Joyner /**
86871d10453SEric Joyner  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
86971d10453SEric Joyner  * @hw: pointer to the hardware structure
87071d10453SEric Joyner  *
87171d10453SEric Joyner  * This should be called only during nominal operation, not as a result of
87271d10453SEric Joyner  * ice_init_hw() failing since ice_init_hw() will take care of unrolling
87371d10453SEric Joyner  * applicable initializations if it fails for any reason.
87471d10453SEric Joyner  */
87571d10453SEric Joyner void ice_deinit_hw(struct ice_hw *hw)
87671d10453SEric Joyner {
87771d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
87871d10453SEric Joyner 
87971d10453SEric Joyner 	ice_sched_cleanup_all(hw);
88071d10453SEric Joyner 	ice_sched_clear_agg(hw);
88171d10453SEric Joyner 	ice_free_seg(hw);
88271d10453SEric Joyner 	ice_free_hw_tbls(hw);
88371d10453SEric Joyner 	ice_destroy_lock(&hw->tnl_lock);
88471d10453SEric Joyner 
88571d10453SEric Joyner 	if (hw->port_info) {
88671d10453SEric Joyner 		ice_free(hw, hw->port_info);
88771d10453SEric Joyner 		hw->port_info = NULL;
88871d10453SEric Joyner 	}
88971d10453SEric Joyner 
89071d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
89171d10453SEric Joyner 
89271d10453SEric Joyner 	/* Clear VSI contexts if not already cleared */
89371d10453SEric Joyner 	ice_clear_all_vsi_ctx(hw);
89471d10453SEric Joyner }
89571d10453SEric Joyner 
89671d10453SEric Joyner /**
89771d10453SEric Joyner  * ice_check_reset - Check to see if a global reset is complete
89871d10453SEric Joyner  * @hw: pointer to the hardware structure
89971d10453SEric Joyner  */
90071d10453SEric Joyner enum ice_status ice_check_reset(struct ice_hw *hw)
90171d10453SEric Joyner {
902*7d7af7f8SEric Joyner 	u32 cnt, reg = 0, grst_timeout, uld_mask;
90371d10453SEric Joyner 
90471d10453SEric Joyner 	/* Poll for Device Active state in case a recent CORER, GLOBR,
90571d10453SEric Joyner 	 * or EMPR has occurred. The grst delay value is in 100ms units.
90671d10453SEric Joyner 	 * Add 1sec for outstanding AQ commands that can take a long time.
90771d10453SEric Joyner 	 */
908*7d7af7f8SEric Joyner 	grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
90971d10453SEric Joyner 			GLGEN_RSTCTL_GRSTDEL_S) + 10;
91071d10453SEric Joyner 
911*7d7af7f8SEric Joyner 	for (cnt = 0; cnt < grst_timeout; cnt++) {
91271d10453SEric Joyner 		ice_msec_delay(100, true);
91371d10453SEric Joyner 		reg = rd32(hw, GLGEN_RSTAT);
91471d10453SEric Joyner 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
91571d10453SEric Joyner 			break;
91671d10453SEric Joyner 	}
91771d10453SEric Joyner 
918*7d7af7f8SEric Joyner 	if (cnt == grst_timeout) {
919*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n");
92071d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
92171d10453SEric Joyner 	}
92271d10453SEric Joyner 
92371d10453SEric Joyner #define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
92471d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_1_M |\
92571d10453SEric Joyner 				 GLNVM_ULD_CORER_DONE_M |\
92671d10453SEric Joyner 				 GLNVM_ULD_GLOBR_DONE_M |\
92771d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_M |\
92871d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_1_M |\
92971d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_2_M)
93071d10453SEric Joyner 
93171d10453SEric Joyner 	uld_mask = ICE_RESET_DONE_MASK;
93271d10453SEric Joyner 
93371d10453SEric Joyner 	/* Device is Active; check Global Reset processes are done */
93471d10453SEric Joyner 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
93571d10453SEric Joyner 		reg = rd32(hw, GLNVM_ULD) & uld_mask;
93671d10453SEric Joyner 		if (reg == uld_mask) {
937*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt);
93871d10453SEric Joyner 			break;
93971d10453SEric Joyner 		}
94071d10453SEric Joyner 		ice_msec_delay(10, true);
94171d10453SEric Joyner 	}
94271d10453SEric Joyner 
94371d10453SEric Joyner 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
944*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
94571d10453SEric Joyner 			  reg);
94671d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
94771d10453SEric Joyner 	}
94871d10453SEric Joyner 
94971d10453SEric Joyner 	return ICE_SUCCESS;
95071d10453SEric Joyner }
95171d10453SEric Joyner 
95271d10453SEric Joyner /**
95371d10453SEric Joyner  * ice_pf_reset - Reset the PF
95471d10453SEric Joyner  * @hw: pointer to the hardware structure
95571d10453SEric Joyner  *
95671d10453SEric Joyner  * If a global reset has been triggered, this function checks
95771d10453SEric Joyner  * for its completion and then issues the PF reset
95871d10453SEric Joyner  */
95971d10453SEric Joyner static enum ice_status ice_pf_reset(struct ice_hw *hw)
96071d10453SEric Joyner {
96171d10453SEric Joyner 	u32 cnt, reg;
96271d10453SEric Joyner 
96371d10453SEric Joyner 	/* If at function entry a global reset was already in progress, i.e.
96471d10453SEric Joyner 	 * state is not 'device active' or any of the reset done bits are not
96571d10453SEric Joyner 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
96671d10453SEric Joyner 	 * global reset is done.
96771d10453SEric Joyner 	 */
96871d10453SEric Joyner 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
96971d10453SEric Joyner 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
97071d10453SEric Joyner 		/* poll on global reset currently in progress until done */
97171d10453SEric Joyner 		if (ice_check_reset(hw))
97271d10453SEric Joyner 			return ICE_ERR_RESET_FAILED;
97371d10453SEric Joyner 
97471d10453SEric Joyner 		return ICE_SUCCESS;
97571d10453SEric Joyner 	}
97671d10453SEric Joyner 
97771d10453SEric Joyner 	/* Reset the PF */
97871d10453SEric Joyner 	reg = rd32(hw, PFGEN_CTRL);
97971d10453SEric Joyner 
98071d10453SEric Joyner 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
98171d10453SEric Joyner 
982*7d7af7f8SEric Joyner 	/* Wait for the PFR to complete. The wait time is the global config lock
983*7d7af7f8SEric Joyner 	 * timeout plus the PFR timeout which will account for a possible reset
984*7d7af7f8SEric Joyner 	 * that is occurring during a download package operation.
985*7d7af7f8SEric Joyner 	 */
986*7d7af7f8SEric Joyner 	for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT +
987*7d7af7f8SEric Joyner 	     ICE_PF_RESET_WAIT_COUNT; cnt++) {
98871d10453SEric Joyner 		reg = rd32(hw, PFGEN_CTRL);
98971d10453SEric Joyner 		if (!(reg & PFGEN_CTRL_PFSWR_M))
99071d10453SEric Joyner 			break;
99171d10453SEric Joyner 
99271d10453SEric Joyner 		ice_msec_delay(1, true);
99371d10453SEric Joyner 	}
99471d10453SEric Joyner 
99571d10453SEric Joyner 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
996*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n");
99771d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
99871d10453SEric Joyner 	}
99971d10453SEric Joyner 
100071d10453SEric Joyner 	return ICE_SUCCESS;
100171d10453SEric Joyner }
100271d10453SEric Joyner 
100371d10453SEric Joyner /**
100471d10453SEric Joyner  * ice_reset - Perform different types of reset
100571d10453SEric Joyner  * @hw: pointer to the hardware structure
100671d10453SEric Joyner  * @req: reset request
100771d10453SEric Joyner  *
100871d10453SEric Joyner  * This function triggers a reset as specified by the req parameter.
100971d10453SEric Joyner  *
101071d10453SEric Joyner  * Note:
101171d10453SEric Joyner  * If anything other than a PF reset is triggered, PXE mode is restored.
101271d10453SEric Joyner  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
101371d10453SEric Joyner  * interface has been restored in the rebuild flow.
101471d10453SEric Joyner  */
101571d10453SEric Joyner enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
101671d10453SEric Joyner {
101771d10453SEric Joyner 	u32 val = 0;
101871d10453SEric Joyner 
101971d10453SEric Joyner 	switch (req) {
102071d10453SEric Joyner 	case ICE_RESET_PFR:
102171d10453SEric Joyner 		return ice_pf_reset(hw);
102271d10453SEric Joyner 	case ICE_RESET_CORER:
102371d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
102471d10453SEric Joyner 		val = GLGEN_RTRIG_CORER_M;
102571d10453SEric Joyner 		break;
102671d10453SEric Joyner 	case ICE_RESET_GLOBR:
102771d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
102871d10453SEric Joyner 		val = GLGEN_RTRIG_GLOBR_M;
102971d10453SEric Joyner 		break;
103071d10453SEric Joyner 	default:
103171d10453SEric Joyner 		return ICE_ERR_PARAM;
103271d10453SEric Joyner 	}
103371d10453SEric Joyner 
103471d10453SEric Joyner 	val |= rd32(hw, GLGEN_RTRIG);
103571d10453SEric Joyner 	wr32(hw, GLGEN_RTRIG, val);
103671d10453SEric Joyner 	ice_flush(hw);
103771d10453SEric Joyner 
103871d10453SEric Joyner 	/* wait for the FW to be ready */
103971d10453SEric Joyner 	return ice_check_reset(hw);
104071d10453SEric Joyner }
104171d10453SEric Joyner 
104271d10453SEric Joyner /**
104371d10453SEric Joyner  * ice_copy_rxq_ctx_to_hw
104471d10453SEric Joyner  * @hw: pointer to the hardware structure
104571d10453SEric Joyner  * @ice_rxq_ctx: pointer to the rxq context
104671d10453SEric Joyner  * @rxq_index: the index of the Rx queue
104771d10453SEric Joyner  *
104871d10453SEric Joyner  * Copies rxq context from dense structure to HW register space
104971d10453SEric Joyner  */
105071d10453SEric Joyner static enum ice_status
105171d10453SEric Joyner ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
105271d10453SEric Joyner {
105371d10453SEric Joyner 	u8 i;
105471d10453SEric Joyner 
105571d10453SEric Joyner 	if (!ice_rxq_ctx)
105671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
105771d10453SEric Joyner 
105871d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
105971d10453SEric Joyner 		return ICE_ERR_PARAM;
106071d10453SEric Joyner 
106171d10453SEric Joyner 	/* Copy each dword separately to HW */
106271d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
106371d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index),
106471d10453SEric Joyner 		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
106571d10453SEric Joyner 
106671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
106771d10453SEric Joyner 			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
106871d10453SEric Joyner 	}
106971d10453SEric Joyner 
107071d10453SEric Joyner 	return ICE_SUCCESS;
107171d10453SEric Joyner }
107271d10453SEric Joyner 
107371d10453SEric Joyner /* LAN Rx Queue Context */
107471d10453SEric Joyner static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
107571d10453SEric Joyner 	/* Field		Width	LSB */
107671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
107771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
107871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
107971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
108071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
108171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
108271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
108371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
108471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
108571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
108671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
108771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
108871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
108971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
109071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
109171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
109271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
109371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
109471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
109571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
109671d10453SEric Joyner 	{ 0 }
109771d10453SEric Joyner };
109871d10453SEric Joyner 
109971d10453SEric Joyner /**
110071d10453SEric Joyner  * ice_write_rxq_ctx
110171d10453SEric Joyner  * @hw: pointer to the hardware structure
110271d10453SEric Joyner  * @rlan_ctx: pointer to the rxq context
110371d10453SEric Joyner  * @rxq_index: the index of the Rx queue
110471d10453SEric Joyner  *
110571d10453SEric Joyner  * Converts rxq context from sparse to dense structure and then writes
110671d10453SEric Joyner  * it to HW register space and enables the hardware to prefetch descriptors
110771d10453SEric Joyner  * instead of only fetching them on demand
110871d10453SEric Joyner  */
110971d10453SEric Joyner enum ice_status
111071d10453SEric Joyner ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
111171d10453SEric Joyner 		  u32 rxq_index)
111271d10453SEric Joyner {
111371d10453SEric Joyner 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
111471d10453SEric Joyner 
111571d10453SEric Joyner 	if (!rlan_ctx)
111671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
111771d10453SEric Joyner 
111871d10453SEric Joyner 	rlan_ctx->prefena = 1;
111971d10453SEric Joyner 
1120*7d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
112171d10453SEric Joyner 	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
112271d10453SEric Joyner }
112371d10453SEric Joyner 
112471d10453SEric Joyner /**
112571d10453SEric Joyner  * ice_clear_rxq_ctx
112671d10453SEric Joyner  * @hw: pointer to the hardware structure
112771d10453SEric Joyner  * @rxq_index: the index of the Rx queue to clear
112871d10453SEric Joyner  *
112971d10453SEric Joyner  * Clears rxq context in HW register space
113071d10453SEric Joyner  */
113171d10453SEric Joyner enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index)
113271d10453SEric Joyner {
113371d10453SEric Joyner 	u8 i;
113471d10453SEric Joyner 
113571d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
113671d10453SEric Joyner 		return ICE_ERR_PARAM;
113771d10453SEric Joyner 
113871d10453SEric Joyner 	/* Clear each dword register separately */
113971d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++)
114071d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index), 0);
114171d10453SEric Joyner 
114271d10453SEric Joyner 	return ICE_SUCCESS;
114371d10453SEric Joyner }
114471d10453SEric Joyner 
114571d10453SEric Joyner /* LAN Tx Queue Context */
114671d10453SEric Joyner const struct ice_ctx_ele ice_tlan_ctx_info[] = {
114771d10453SEric Joyner 				    /* Field			Width	LSB */
114871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
114971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
115071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
115171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
115271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
115371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
115471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
115571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
115671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
115771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
115871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
115971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
116071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
116171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
116271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
116371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
116471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
116571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
116671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
116771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
116871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
116971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
117071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
117171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
117271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
117371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
117471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
117571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
117671d10453SEric Joyner 	{ 0 }
117771d10453SEric Joyner };
117871d10453SEric Joyner 
117971d10453SEric Joyner /**
118071d10453SEric Joyner  * ice_copy_tx_cmpltnq_ctx_to_hw
118171d10453SEric Joyner  * @hw: pointer to the hardware structure
118271d10453SEric Joyner  * @ice_tx_cmpltnq_ctx: pointer to the Tx completion queue context
118371d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
118471d10453SEric Joyner  *
118571d10453SEric Joyner  * Copies Tx completion queue context from dense structure to HW register space
118671d10453SEric Joyner  */
118771d10453SEric Joyner static enum ice_status
118871d10453SEric Joyner ice_copy_tx_cmpltnq_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_cmpltnq_ctx,
118971d10453SEric Joyner 			      u32 tx_cmpltnq_index)
119071d10453SEric Joyner {
119171d10453SEric Joyner 	u8 i;
119271d10453SEric Joyner 
119371d10453SEric Joyner 	if (!ice_tx_cmpltnq_ctx)
119471d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
119571d10453SEric Joyner 
119671d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
119771d10453SEric Joyner 		return ICE_ERR_PARAM;
119871d10453SEric Joyner 
119971d10453SEric Joyner 	/* Copy each dword separately to HW */
120071d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++) {
120171d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index),
120271d10453SEric Joyner 		     *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
120371d10453SEric Joyner 
120471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "cmpltnqdata[%d]: %08X\n", i,
120571d10453SEric Joyner 			  *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
120671d10453SEric Joyner 	}
120771d10453SEric Joyner 
120871d10453SEric Joyner 	return ICE_SUCCESS;
120971d10453SEric Joyner }
121071d10453SEric Joyner 
121171d10453SEric Joyner /* LAN Tx Completion Queue Context */
121271d10453SEric Joyner static const struct ice_ctx_ele ice_tx_cmpltnq_ctx_info[] = {
121371d10453SEric Joyner 				       /* Field			Width   LSB */
121471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, base,			57,	0),
121571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, q_len,		18,	64),
121671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, generation,		1,	96),
121771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, wrt_ptr,		22,	97),
121871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, pf_num,		3,	128),
121971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_num,		10,	131),
122071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_type,		2,	141),
122171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, tph_desc_wr,		1,	160),
122271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cpuid,		8,	161),
122371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cmpltn_cache,		512,	192),
122471d10453SEric Joyner 	{ 0 }
122571d10453SEric Joyner };
122671d10453SEric Joyner 
122771d10453SEric Joyner /**
122871d10453SEric Joyner  * ice_write_tx_cmpltnq_ctx
122971d10453SEric Joyner  * @hw: pointer to the hardware structure
123071d10453SEric Joyner  * @tx_cmpltnq_ctx: pointer to the completion queue context
123171d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
123271d10453SEric Joyner  *
123371d10453SEric Joyner  * Converts completion queue context from sparse to dense structure and then
123471d10453SEric Joyner  * writes it to HW register space
123571d10453SEric Joyner  */
123671d10453SEric Joyner enum ice_status
123771d10453SEric Joyner ice_write_tx_cmpltnq_ctx(struct ice_hw *hw,
123871d10453SEric Joyner 			 struct ice_tx_cmpltnq_ctx *tx_cmpltnq_ctx,
123971d10453SEric Joyner 			 u32 tx_cmpltnq_index)
124071d10453SEric Joyner {
124171d10453SEric Joyner 	u8 ctx_buf[ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
124271d10453SEric Joyner 
1243*7d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info);
124471d10453SEric Joyner 	return ice_copy_tx_cmpltnq_ctx_to_hw(hw, ctx_buf, tx_cmpltnq_index);
124571d10453SEric Joyner }
124671d10453SEric Joyner 
124771d10453SEric Joyner /**
124871d10453SEric Joyner  * ice_clear_tx_cmpltnq_ctx
124971d10453SEric Joyner  * @hw: pointer to the hardware structure
125071d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue to clear
125171d10453SEric Joyner  *
125271d10453SEric Joyner  * Clears Tx completion queue context in HW register space
125371d10453SEric Joyner  */
125471d10453SEric Joyner enum ice_status
125571d10453SEric Joyner ice_clear_tx_cmpltnq_ctx(struct ice_hw *hw, u32 tx_cmpltnq_index)
125671d10453SEric Joyner {
125771d10453SEric Joyner 	u8 i;
125871d10453SEric Joyner 
125971d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
126071d10453SEric Joyner 		return ICE_ERR_PARAM;
126171d10453SEric Joyner 
126271d10453SEric Joyner 	/* Clear each dword register separately */
126371d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++)
126471d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index), 0);
126571d10453SEric Joyner 
126671d10453SEric Joyner 	return ICE_SUCCESS;
126771d10453SEric Joyner }
126871d10453SEric Joyner 
126971d10453SEric Joyner /**
127071d10453SEric Joyner  * ice_copy_tx_drbell_q_ctx_to_hw
127171d10453SEric Joyner  * @hw: pointer to the hardware structure
127271d10453SEric Joyner  * @ice_tx_drbell_q_ctx: pointer to the doorbell queue context
127371d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
127471d10453SEric Joyner  *
127571d10453SEric Joyner  * Copies doorbell queue context from dense structure to HW register space
127671d10453SEric Joyner  */
127771d10453SEric Joyner static enum ice_status
127871d10453SEric Joyner ice_copy_tx_drbell_q_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_drbell_q_ctx,
127971d10453SEric Joyner 			       u32 tx_drbell_q_index)
128071d10453SEric Joyner {
128171d10453SEric Joyner 	u8 i;
128271d10453SEric Joyner 
128371d10453SEric Joyner 	if (!ice_tx_drbell_q_ctx)
128471d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
128571d10453SEric Joyner 
128671d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
128771d10453SEric Joyner 		return ICE_ERR_PARAM;
128871d10453SEric Joyner 
128971d10453SEric Joyner 	/* Copy each dword separately to HW */
129071d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++) {
129171d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index),
129271d10453SEric Joyner 		     *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
129371d10453SEric Joyner 
129471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "tx_drbell_qdata[%d]: %08X\n", i,
129571d10453SEric Joyner 			  *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
129671d10453SEric Joyner 	}
129771d10453SEric Joyner 
129871d10453SEric Joyner 	return ICE_SUCCESS;
129971d10453SEric Joyner }
130071d10453SEric Joyner 
130171d10453SEric Joyner /* LAN Tx Doorbell Queue Context info */
130271d10453SEric Joyner static const struct ice_ctx_ele ice_tx_drbell_q_ctx_info[] = {
130371d10453SEric Joyner 					/* Field		Width   LSB */
130471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, base,		57,	0),
130571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, ring_len,		13,	64),
130671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, pf_num,		3,	80),
130771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vf_num,		8,	84),
130871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vmvf_type,		2,	94),
130971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, cpuid,		8,	96),
131071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_rd,		1,	104),
131171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_wr,		1,	108),
131271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, db_q_en,		1,	112),
131371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_head,		13,	128),
131471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_tail,		13,	144),
131571d10453SEric Joyner 	{ 0 }
131671d10453SEric Joyner };
131771d10453SEric Joyner 
131871d10453SEric Joyner /**
131971d10453SEric Joyner  * ice_write_tx_drbell_q_ctx
132071d10453SEric Joyner  * @hw: pointer to the hardware structure
132171d10453SEric Joyner  * @tx_drbell_q_ctx: pointer to the doorbell queue context
132271d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
132371d10453SEric Joyner  *
132471d10453SEric Joyner  * Converts doorbell queue context from sparse to dense structure and then
132571d10453SEric Joyner  * writes it to HW register space
132671d10453SEric Joyner  */
132771d10453SEric Joyner enum ice_status
132871d10453SEric Joyner ice_write_tx_drbell_q_ctx(struct ice_hw *hw,
132971d10453SEric Joyner 			  struct ice_tx_drbell_q_ctx *tx_drbell_q_ctx,
133071d10453SEric Joyner 			  u32 tx_drbell_q_index)
133171d10453SEric Joyner {
133271d10453SEric Joyner 	u8 ctx_buf[ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
133371d10453SEric Joyner 
1334*7d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_drbell_q_ctx, ctx_buf,
1335*7d7af7f8SEric Joyner 		    ice_tx_drbell_q_ctx_info);
133671d10453SEric Joyner 	return ice_copy_tx_drbell_q_ctx_to_hw(hw, ctx_buf, tx_drbell_q_index);
133771d10453SEric Joyner }
133871d10453SEric Joyner 
133971d10453SEric Joyner /**
134071d10453SEric Joyner  * ice_clear_tx_drbell_q_ctx
134171d10453SEric Joyner  * @hw: pointer to the hardware structure
134271d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue to clear
134371d10453SEric Joyner  *
134471d10453SEric Joyner  * Clears doorbell queue context in HW register space
134571d10453SEric Joyner  */
134671d10453SEric Joyner enum ice_status
134771d10453SEric Joyner ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index)
134871d10453SEric Joyner {
134971d10453SEric Joyner 	u8 i;
135071d10453SEric Joyner 
135171d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
135271d10453SEric Joyner 		return ICE_ERR_PARAM;
135371d10453SEric Joyner 
135471d10453SEric Joyner 	/* Clear each dword register separately */
135571d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++)
135671d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index), 0);
135771d10453SEric Joyner 
135871d10453SEric Joyner 	return ICE_SUCCESS;
135971d10453SEric Joyner }
136071d10453SEric Joyner 
136171d10453SEric Joyner /* FW Admin Queue command wrappers */
136271d10453SEric Joyner 
136371d10453SEric Joyner /**
136471d10453SEric Joyner  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
136571d10453SEric Joyner  * @hw: pointer to the HW struct
136671d10453SEric Joyner  * @desc: descriptor describing the command
136771d10453SEric Joyner  * @buf: buffer to use for indirect commands (NULL for direct commands)
136871d10453SEric Joyner  * @buf_size: size of buffer for indirect commands (0 for direct commands)
136971d10453SEric Joyner  * @cd: pointer to command details structure
137071d10453SEric Joyner  *
137171d10453SEric Joyner  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
137271d10453SEric Joyner  */
137371d10453SEric Joyner enum ice_status
137471d10453SEric Joyner ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
137571d10453SEric Joyner 		u16 buf_size, struct ice_sq_cd *cd)
137671d10453SEric Joyner {
137771d10453SEric Joyner 	return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
137871d10453SEric Joyner }
137971d10453SEric Joyner 
138071d10453SEric Joyner /**
138171d10453SEric Joyner  * ice_aq_get_fw_ver
138271d10453SEric Joyner  * @hw: pointer to the HW struct
138371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
138471d10453SEric Joyner  *
138571d10453SEric Joyner  * Get the firmware version (0x0001) from the admin queue commands
138671d10453SEric Joyner  */
138771d10453SEric Joyner enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
138871d10453SEric Joyner {
138971d10453SEric Joyner 	struct ice_aqc_get_ver *resp;
139071d10453SEric Joyner 	struct ice_aq_desc desc;
139171d10453SEric Joyner 	enum ice_status status;
139271d10453SEric Joyner 
139371d10453SEric Joyner 	resp = &desc.params.get_ver;
139471d10453SEric Joyner 
139571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
139671d10453SEric Joyner 
139771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
139871d10453SEric Joyner 
139971d10453SEric Joyner 	if (!status) {
140071d10453SEric Joyner 		hw->fw_branch = resp->fw_branch;
140171d10453SEric Joyner 		hw->fw_maj_ver = resp->fw_major;
140271d10453SEric Joyner 		hw->fw_min_ver = resp->fw_minor;
140371d10453SEric Joyner 		hw->fw_patch = resp->fw_patch;
140471d10453SEric Joyner 		hw->fw_build = LE32_TO_CPU(resp->fw_build);
140571d10453SEric Joyner 		hw->api_branch = resp->api_branch;
140671d10453SEric Joyner 		hw->api_maj_ver = resp->api_major;
140771d10453SEric Joyner 		hw->api_min_ver = resp->api_minor;
140871d10453SEric Joyner 		hw->api_patch = resp->api_patch;
140971d10453SEric Joyner 	}
141071d10453SEric Joyner 
141171d10453SEric Joyner 	return status;
141271d10453SEric Joyner }
141371d10453SEric Joyner 
141471d10453SEric Joyner /**
141571d10453SEric Joyner  * ice_aq_send_driver_ver
141671d10453SEric Joyner  * @hw: pointer to the HW struct
141771d10453SEric Joyner  * @dv: driver's major, minor version
141871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
141971d10453SEric Joyner  *
142071d10453SEric Joyner  * Send the driver version (0x0002) to the firmware
142171d10453SEric Joyner  */
142271d10453SEric Joyner enum ice_status
142371d10453SEric Joyner ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
142471d10453SEric Joyner 		       struct ice_sq_cd *cd)
142571d10453SEric Joyner {
142671d10453SEric Joyner 	struct ice_aqc_driver_ver *cmd;
142771d10453SEric Joyner 	struct ice_aq_desc desc;
142871d10453SEric Joyner 	u16 len;
142971d10453SEric Joyner 
143071d10453SEric Joyner 	cmd = &desc.params.driver_ver;
143171d10453SEric Joyner 
143271d10453SEric Joyner 	if (!dv)
143371d10453SEric Joyner 		return ICE_ERR_PARAM;
143471d10453SEric Joyner 
143571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
143671d10453SEric Joyner 
143771d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
143871d10453SEric Joyner 	cmd->major_ver = dv->major_ver;
143971d10453SEric Joyner 	cmd->minor_ver = dv->minor_ver;
144071d10453SEric Joyner 	cmd->build_ver = dv->build_ver;
144171d10453SEric Joyner 	cmd->subbuild_ver = dv->subbuild_ver;
144271d10453SEric Joyner 
144371d10453SEric Joyner 	len = 0;
144471d10453SEric Joyner 	while (len < sizeof(dv->driver_string) &&
144571d10453SEric Joyner 	       IS_ASCII(dv->driver_string[len]) && dv->driver_string[len])
144671d10453SEric Joyner 		len++;
144771d10453SEric Joyner 
144871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
144971d10453SEric Joyner }
145071d10453SEric Joyner 
145171d10453SEric Joyner /**
145271d10453SEric Joyner  * ice_aq_q_shutdown
145371d10453SEric Joyner  * @hw: pointer to the HW struct
145471d10453SEric Joyner  * @unloading: is the driver unloading itself
145571d10453SEric Joyner  *
145671d10453SEric Joyner  * Tell the Firmware that we're shutting down the AdminQ and whether
145771d10453SEric Joyner  * or not the driver is unloading as well (0x0003).
145871d10453SEric Joyner  */
145971d10453SEric Joyner enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
146071d10453SEric Joyner {
146171d10453SEric Joyner 	struct ice_aqc_q_shutdown *cmd;
146271d10453SEric Joyner 	struct ice_aq_desc desc;
146371d10453SEric Joyner 
146471d10453SEric Joyner 	cmd = &desc.params.q_shutdown;
146571d10453SEric Joyner 
146671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
146771d10453SEric Joyner 
146871d10453SEric Joyner 	if (unloading)
146971d10453SEric Joyner 		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
147071d10453SEric Joyner 
147171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
147271d10453SEric Joyner }
147371d10453SEric Joyner 
147471d10453SEric Joyner /**
147571d10453SEric Joyner  * ice_aq_req_res
147671d10453SEric Joyner  * @hw: pointer to the HW struct
147771d10453SEric Joyner  * @res: resource ID
147871d10453SEric Joyner  * @access: access type
147971d10453SEric Joyner  * @sdp_number: resource number
148071d10453SEric Joyner  * @timeout: the maximum time in ms that the driver may hold the resource
148171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
148271d10453SEric Joyner  *
148371d10453SEric Joyner  * Requests common resource using the admin queue commands (0x0008).
148471d10453SEric Joyner  * When attempting to acquire the Global Config Lock, the driver can
148571d10453SEric Joyner  * learn of three states:
148671d10453SEric Joyner  *  1) ICE_SUCCESS -        acquired lock, and can perform download package
148771d10453SEric Joyner  *  2) ICE_ERR_AQ_ERROR -   did not get lock, driver should fail to load
148871d10453SEric Joyner  *  3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
148971d10453SEric Joyner  *                          successfully downloaded the package; the driver does
149071d10453SEric Joyner  *                          not have to download the package and can continue
149171d10453SEric Joyner  *                          loading
149271d10453SEric Joyner  *
149371d10453SEric Joyner  * Note that if the caller is in an acquire lock, perform action, release lock
149471d10453SEric Joyner  * phase of operation, it is possible that the FW may detect a timeout and issue
149571d10453SEric Joyner  * a CORER. In this case, the driver will receive a CORER interrupt and will
149671d10453SEric Joyner  * have to determine its cause. The calling thread that is handling this flow
149771d10453SEric Joyner  * will likely get an error propagated back to it indicating the Download
149871d10453SEric Joyner  * Package, Update Package or the Release Resource AQ commands timed out.
149971d10453SEric Joyner  */
150071d10453SEric Joyner static enum ice_status
150171d10453SEric Joyner ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
150271d10453SEric Joyner 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
150371d10453SEric Joyner 	       struct ice_sq_cd *cd)
150471d10453SEric Joyner {
150571d10453SEric Joyner 	struct ice_aqc_req_res *cmd_resp;
150671d10453SEric Joyner 	struct ice_aq_desc desc;
150771d10453SEric Joyner 	enum ice_status status;
150871d10453SEric Joyner 
150971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
151071d10453SEric Joyner 
151171d10453SEric Joyner 	cmd_resp = &desc.params.res_owner;
151271d10453SEric Joyner 
151371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
151471d10453SEric Joyner 
151571d10453SEric Joyner 	cmd_resp->res_id = CPU_TO_LE16(res);
151671d10453SEric Joyner 	cmd_resp->access_type = CPU_TO_LE16(access);
151771d10453SEric Joyner 	cmd_resp->res_number = CPU_TO_LE32(sdp_number);
151871d10453SEric Joyner 	cmd_resp->timeout = CPU_TO_LE32(*timeout);
151971d10453SEric Joyner 	*timeout = 0;
152071d10453SEric Joyner 
152171d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
152271d10453SEric Joyner 
152371d10453SEric Joyner 	/* The completion specifies the maximum time in ms that the driver
152471d10453SEric Joyner 	 * may hold the resource in the Timeout field.
152571d10453SEric Joyner 	 */
152671d10453SEric Joyner 
152771d10453SEric Joyner 	/* Global config lock response utilizes an additional status field.
152871d10453SEric Joyner 	 *
152971d10453SEric Joyner 	 * If the Global config lock resource is held by some other driver, the
153071d10453SEric Joyner 	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
153171d10453SEric Joyner 	 * and the timeout field indicates the maximum time the current owner
153271d10453SEric Joyner 	 * of the resource has to free it.
153371d10453SEric Joyner 	 */
153471d10453SEric Joyner 	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
153571d10453SEric Joyner 		if (LE16_TO_CPU(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
153671d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
153771d10453SEric Joyner 			return ICE_SUCCESS;
153871d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
153971d10453SEric Joyner 			   ICE_AQ_RES_GLBL_IN_PROG) {
154071d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
154171d10453SEric Joyner 			return ICE_ERR_AQ_ERROR;
154271d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
154371d10453SEric Joyner 			   ICE_AQ_RES_GLBL_DONE) {
154471d10453SEric Joyner 			return ICE_ERR_AQ_NO_WORK;
154571d10453SEric Joyner 		}
154671d10453SEric Joyner 
154771d10453SEric Joyner 		/* invalid FW response, force a timeout immediately */
154871d10453SEric Joyner 		*timeout = 0;
154971d10453SEric Joyner 		return ICE_ERR_AQ_ERROR;
155071d10453SEric Joyner 	}
155171d10453SEric Joyner 
155271d10453SEric Joyner 	/* If the resource is held by some other driver, the command completes
155371d10453SEric Joyner 	 * with a busy return value and the timeout field indicates the maximum
155471d10453SEric Joyner 	 * time the current owner of the resource has to free it.
155571d10453SEric Joyner 	 */
155671d10453SEric Joyner 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
155771d10453SEric Joyner 		*timeout = LE32_TO_CPU(cmd_resp->timeout);
155871d10453SEric Joyner 
155971d10453SEric Joyner 	return status;
156071d10453SEric Joyner }
156171d10453SEric Joyner 
156271d10453SEric Joyner /**
156371d10453SEric Joyner  * ice_aq_release_res
156471d10453SEric Joyner  * @hw: pointer to the HW struct
156571d10453SEric Joyner  * @res: resource ID
156671d10453SEric Joyner  * @sdp_number: resource number
156771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
156871d10453SEric Joyner  *
156971d10453SEric Joyner  * release common resource using the admin queue commands (0x0009)
157071d10453SEric Joyner  */
157171d10453SEric Joyner static enum ice_status
157271d10453SEric Joyner ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
157371d10453SEric Joyner 		   struct ice_sq_cd *cd)
157471d10453SEric Joyner {
157571d10453SEric Joyner 	struct ice_aqc_req_res *cmd;
157671d10453SEric Joyner 	struct ice_aq_desc desc;
157771d10453SEric Joyner 
157871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
157971d10453SEric Joyner 
158071d10453SEric Joyner 	cmd = &desc.params.res_owner;
158171d10453SEric Joyner 
158271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
158371d10453SEric Joyner 
158471d10453SEric Joyner 	cmd->res_id = CPU_TO_LE16(res);
158571d10453SEric Joyner 	cmd->res_number = CPU_TO_LE32(sdp_number);
158671d10453SEric Joyner 
158771d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
158871d10453SEric Joyner }
158971d10453SEric Joyner 
159071d10453SEric Joyner /**
159171d10453SEric Joyner  * ice_acquire_res
159271d10453SEric Joyner  * @hw: pointer to the HW structure
159371d10453SEric Joyner  * @res: resource ID
159471d10453SEric Joyner  * @access: access type (read or write)
159571d10453SEric Joyner  * @timeout: timeout in milliseconds
159671d10453SEric Joyner  *
159771d10453SEric Joyner  * This function will attempt to acquire the ownership of a resource.
159871d10453SEric Joyner  */
159971d10453SEric Joyner enum ice_status
160071d10453SEric Joyner ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
160171d10453SEric Joyner 		enum ice_aq_res_access_type access, u32 timeout)
160271d10453SEric Joyner {
160371d10453SEric Joyner #define ICE_RES_POLLING_DELAY_MS	10
160471d10453SEric Joyner 	u32 delay = ICE_RES_POLLING_DELAY_MS;
160571d10453SEric Joyner 	u32 time_left = timeout;
160671d10453SEric Joyner 	enum ice_status status;
160771d10453SEric Joyner 
160871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
160971d10453SEric Joyner 
161071d10453SEric Joyner 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
161171d10453SEric Joyner 
161271d10453SEric Joyner 	/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
161371d10453SEric Joyner 	 * previously acquired the resource and performed any necessary updates;
161471d10453SEric Joyner 	 * in this case the caller does not obtain the resource and has no
161571d10453SEric Joyner 	 * further work to do.
161671d10453SEric Joyner 	 */
161771d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK)
161871d10453SEric Joyner 		goto ice_acquire_res_exit;
161971d10453SEric Joyner 
162071d10453SEric Joyner 	if (status)
1621*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access);
162271d10453SEric Joyner 
162371d10453SEric Joyner 	/* If necessary, poll until the current lock owner timeouts */
162471d10453SEric Joyner 	timeout = time_left;
162571d10453SEric Joyner 	while (status && timeout && time_left) {
162671d10453SEric Joyner 		ice_msec_delay(delay, true);
162771d10453SEric Joyner 		timeout = (timeout > delay) ? timeout - delay : 0;
162871d10453SEric Joyner 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
162971d10453SEric Joyner 
163071d10453SEric Joyner 		if (status == ICE_ERR_AQ_NO_WORK)
163171d10453SEric Joyner 			/* lock free, but no work to do */
163271d10453SEric Joyner 			break;
163371d10453SEric Joyner 
163471d10453SEric Joyner 		if (!status)
163571d10453SEric Joyner 			/* lock acquired */
163671d10453SEric Joyner 			break;
163771d10453SEric Joyner 	}
163871d10453SEric Joyner 	if (status && status != ICE_ERR_AQ_NO_WORK)
163971d10453SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
164071d10453SEric Joyner 
164171d10453SEric Joyner ice_acquire_res_exit:
164271d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK) {
164371d10453SEric Joyner 		if (access == ICE_RES_WRITE)
1644*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n");
164571d10453SEric Joyner 		else
1646*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "Warning: ICE_ERR_AQ_NO_WORK not expected\n");
164771d10453SEric Joyner 	}
164871d10453SEric Joyner 	return status;
164971d10453SEric Joyner }
165071d10453SEric Joyner 
165171d10453SEric Joyner /**
165271d10453SEric Joyner  * ice_release_res
165371d10453SEric Joyner  * @hw: pointer to the HW structure
165471d10453SEric Joyner  * @res: resource ID
165571d10453SEric Joyner  *
165671d10453SEric Joyner  * This function will release a resource using the proper Admin Command.
165771d10453SEric Joyner  */
165871d10453SEric Joyner void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
165971d10453SEric Joyner {
166071d10453SEric Joyner 	enum ice_status status;
166171d10453SEric Joyner 	u32 total_delay = 0;
166271d10453SEric Joyner 
166371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
166471d10453SEric Joyner 
166571d10453SEric Joyner 	status = ice_aq_release_res(hw, res, 0, NULL);
166671d10453SEric Joyner 
166771d10453SEric Joyner 	/* there are some rare cases when trying to release the resource
166871d10453SEric Joyner 	 * results in an admin queue timeout, so handle them correctly
166971d10453SEric Joyner 	 */
167071d10453SEric Joyner 	while ((status == ICE_ERR_AQ_TIMEOUT) &&
167171d10453SEric Joyner 	       (total_delay < hw->adminq.sq_cmd_timeout)) {
167271d10453SEric Joyner 		ice_msec_delay(1, true);
167371d10453SEric Joyner 		status = ice_aq_release_res(hw, res, 0, NULL);
167471d10453SEric Joyner 		total_delay++;
167571d10453SEric Joyner 	}
167671d10453SEric Joyner }
167771d10453SEric Joyner 
167871d10453SEric Joyner /**
167971d10453SEric Joyner  * ice_aq_alloc_free_res - command to allocate/free resources
168071d10453SEric Joyner  * @hw: pointer to the HW struct
168171d10453SEric Joyner  * @num_entries: number of resource entries in buffer
168271d10453SEric Joyner  * @buf: Indirect buffer to hold data parameters and response
168371d10453SEric Joyner  * @buf_size: size of buffer for indirect commands
168471d10453SEric Joyner  * @opc: pass in the command opcode
168571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
168671d10453SEric Joyner  *
168771d10453SEric Joyner  * Helper function to allocate/free resources using the admin queue commands
168871d10453SEric Joyner  */
168971d10453SEric Joyner enum ice_status
169071d10453SEric Joyner ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
169171d10453SEric Joyner 		      struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
169271d10453SEric Joyner 		      enum ice_adminq_opc opc, struct ice_sq_cd *cd)
169371d10453SEric Joyner {
169471d10453SEric Joyner 	struct ice_aqc_alloc_free_res_cmd *cmd;
169571d10453SEric Joyner 	struct ice_aq_desc desc;
169671d10453SEric Joyner 
169771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
169871d10453SEric Joyner 
169971d10453SEric Joyner 	cmd = &desc.params.sw_res_ctrl;
170071d10453SEric Joyner 
170171d10453SEric Joyner 	if (!buf)
170271d10453SEric Joyner 		return ICE_ERR_PARAM;
170371d10453SEric Joyner 
170471d10453SEric Joyner 	if (buf_size < (num_entries * sizeof(buf->elem[0])))
170571d10453SEric Joyner 		return ICE_ERR_PARAM;
170671d10453SEric Joyner 
170771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
170871d10453SEric Joyner 
170971d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
171071d10453SEric Joyner 
171171d10453SEric Joyner 	cmd->num_entries = CPU_TO_LE16(num_entries);
171271d10453SEric Joyner 
171371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
171471d10453SEric Joyner }
171571d10453SEric Joyner 
171671d10453SEric Joyner /**
171771d10453SEric Joyner  * ice_alloc_hw_res - allocate resource
171871d10453SEric Joyner  * @hw: pointer to the HW struct
171971d10453SEric Joyner  * @type: type of resource
172071d10453SEric Joyner  * @num: number of resources to allocate
172171d10453SEric Joyner  * @btm: allocate from bottom
172271d10453SEric Joyner  * @res: pointer to array that will receive the resources
172371d10453SEric Joyner  */
172471d10453SEric Joyner enum ice_status
172571d10453SEric Joyner ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
172671d10453SEric Joyner {
172771d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
172871d10453SEric Joyner 	enum ice_status status;
172971d10453SEric Joyner 	u16 buf_len;
173071d10453SEric Joyner 
1731*7d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
1732*7d7af7f8SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
173371d10453SEric Joyner 	if (!buf)
173471d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
173571d10453SEric Joyner 
173671d10453SEric Joyner 	/* Prepare buffer to allocate resource. */
173771d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
173871d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
173971d10453SEric Joyner 				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
174071d10453SEric Joyner 	if (btm)
174171d10453SEric Joyner 		buf->res_type |= CPU_TO_LE16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
174271d10453SEric Joyner 
174371d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
174471d10453SEric Joyner 				       ice_aqc_opc_alloc_res, NULL);
174571d10453SEric Joyner 	if (status)
174671d10453SEric Joyner 		goto ice_alloc_res_exit;
174771d10453SEric Joyner 
1748*7d7af7f8SEric Joyner 	ice_memcpy(res, buf->elem, sizeof(*buf->elem) * num,
174971d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
175071d10453SEric Joyner 
175171d10453SEric Joyner ice_alloc_res_exit:
175271d10453SEric Joyner 	ice_free(hw, buf);
175371d10453SEric Joyner 	return status;
175471d10453SEric Joyner }
175571d10453SEric Joyner 
175671d10453SEric Joyner /**
175771d10453SEric Joyner  * ice_free_hw_res - free allocated HW resource
175871d10453SEric Joyner  * @hw: pointer to the HW struct
175971d10453SEric Joyner  * @type: type of resource to free
176071d10453SEric Joyner  * @num: number of resources
176171d10453SEric Joyner  * @res: pointer to array that contains the resources to free
176271d10453SEric Joyner  */
1763*7d7af7f8SEric Joyner enum ice_status ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
176471d10453SEric Joyner {
176571d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
176671d10453SEric Joyner 	enum ice_status status;
176771d10453SEric Joyner 	u16 buf_len;
176871d10453SEric Joyner 
1769*7d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
177071d10453SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
177171d10453SEric Joyner 	if (!buf)
177271d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
177371d10453SEric Joyner 
177471d10453SEric Joyner 	/* Prepare buffer to free resource. */
177571d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
177671d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type);
1777*7d7af7f8SEric Joyner 	ice_memcpy(buf->elem, res, sizeof(*buf->elem) * num,
177871d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
177971d10453SEric Joyner 
178071d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, num, buf, buf_len,
178171d10453SEric Joyner 				       ice_aqc_opc_free_res, NULL);
178271d10453SEric Joyner 	if (status)
178371d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
178471d10453SEric Joyner 
178571d10453SEric Joyner 	ice_free(hw, buf);
178671d10453SEric Joyner 	return status;
178771d10453SEric Joyner }
178871d10453SEric Joyner 
178971d10453SEric Joyner /**
179071d10453SEric Joyner  * ice_get_num_per_func - determine number of resources per PF
179171d10453SEric Joyner  * @hw: pointer to the HW structure
179271d10453SEric Joyner  * @max: value to be evenly split between each PF
179371d10453SEric Joyner  *
179471d10453SEric Joyner  * Determine the number of valid functions by going through the bitmap returned
179571d10453SEric Joyner  * from parsing capabilities and use this to calculate the number of resources
179671d10453SEric Joyner  * per PF based on the max value passed in.
179771d10453SEric Joyner  */
179871d10453SEric Joyner static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
179971d10453SEric Joyner {
180071d10453SEric Joyner 	u8 funcs;
180171d10453SEric Joyner 
180271d10453SEric Joyner #define ICE_CAPS_VALID_FUNCS_M	0xFF
180371d10453SEric Joyner 	funcs = ice_hweight8(hw->dev_caps.common_cap.valid_functions &
180471d10453SEric Joyner 			     ICE_CAPS_VALID_FUNCS_M);
180571d10453SEric Joyner 
180671d10453SEric Joyner 	if (!funcs)
180771d10453SEric Joyner 		return 0;
180871d10453SEric Joyner 
180971d10453SEric Joyner 	return max / funcs;
181071d10453SEric Joyner }
181171d10453SEric Joyner 
181271d10453SEric Joyner /**
181371d10453SEric Joyner  * ice_print_led_caps - print LED capabilities
181471d10453SEric Joyner  * @hw: pointer to the ice_hw instance
181571d10453SEric Joyner  * @caps: pointer to common caps instance
181671d10453SEric Joyner  * @prefix: string to prefix when printing
181771d10453SEric Joyner  * @debug: set to indicate debug print
181871d10453SEric Joyner  */
181971d10453SEric Joyner static void
182071d10453SEric Joyner ice_print_led_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
182171d10453SEric Joyner 		   char const *prefix, bool debug)
182271d10453SEric Joyner {
182371d10453SEric Joyner 	u8 i;
182471d10453SEric Joyner 
182571d10453SEric Joyner 	if (debug)
182671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: led_pin_num = %d\n", prefix,
182771d10453SEric Joyner 			  caps->led_pin_num);
182871d10453SEric Joyner 	else
182971d10453SEric Joyner 		ice_info(hw, "%s: led_pin_num = %d\n", prefix,
183071d10453SEric Joyner 			 caps->led_pin_num);
183171d10453SEric Joyner 
183271d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_LED; i++) {
183371d10453SEric Joyner 		if (!caps->led[i])
183471d10453SEric Joyner 			continue;
183571d10453SEric Joyner 
183671d10453SEric Joyner 		if (debug)
183771d10453SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = %d\n",
183871d10453SEric Joyner 				  prefix, i, caps->led[i]);
183971d10453SEric Joyner 		else
184071d10453SEric Joyner 			ice_info(hw, "%s: led[%d] = %d\n", prefix, i,
184171d10453SEric Joyner 				 caps->led[i]);
184271d10453SEric Joyner 	}
184371d10453SEric Joyner }
184471d10453SEric Joyner 
184571d10453SEric Joyner /**
184671d10453SEric Joyner  * ice_print_sdp_caps - print SDP capabilities
184771d10453SEric Joyner  * @hw: pointer to the ice_hw instance
184871d10453SEric Joyner  * @caps: pointer to common caps instance
184971d10453SEric Joyner  * @prefix: string to prefix when printing
185071d10453SEric Joyner  * @debug: set to indicate debug print
185171d10453SEric Joyner  */
185271d10453SEric Joyner static void
185371d10453SEric Joyner ice_print_sdp_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
185471d10453SEric Joyner 		   char const *prefix, bool debug)
185571d10453SEric Joyner {
185671d10453SEric Joyner 	u8 i;
185771d10453SEric Joyner 
185871d10453SEric Joyner 	if (debug)
185971d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sdp_pin_num = %d\n", prefix,
186071d10453SEric Joyner 			  caps->sdp_pin_num);
186171d10453SEric Joyner 	else
186271d10453SEric Joyner 		ice_info(hw, "%s: sdp_pin_num = %d\n", prefix,
186371d10453SEric Joyner 			 caps->sdp_pin_num);
186471d10453SEric Joyner 
186571d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_SDP; i++) {
186671d10453SEric Joyner 		if (!caps->sdp[i])
186771d10453SEric Joyner 			continue;
186871d10453SEric Joyner 
186971d10453SEric Joyner 		if (debug)
187071d10453SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = %d\n",
187171d10453SEric Joyner 				  prefix, i, caps->sdp[i]);
187271d10453SEric Joyner 		else
187371d10453SEric Joyner 			ice_info(hw, "%s: sdp[%d] = %d\n", prefix,
187471d10453SEric Joyner 				 i, caps->sdp[i]);
187571d10453SEric Joyner 	}
187671d10453SEric Joyner }
187771d10453SEric Joyner 
187871d10453SEric Joyner /**
1879*7d7af7f8SEric Joyner  * ice_parse_common_caps - parse common device/function capabilities
188071d10453SEric Joyner  * @hw: pointer to the HW struct
1881*7d7af7f8SEric Joyner  * @caps: pointer to common capabilities structure
1882*7d7af7f8SEric Joyner  * @elem: the capability element to parse
1883*7d7af7f8SEric Joyner  * @prefix: message prefix for tracing capabilities
188471d10453SEric Joyner  *
1885*7d7af7f8SEric Joyner  * Given a capability element, extract relevant details into the common
1886*7d7af7f8SEric Joyner  * capability structure.
1887*7d7af7f8SEric Joyner  *
1888*7d7af7f8SEric Joyner  * Returns: true if the capability matches one of the common capability ids,
1889*7d7af7f8SEric Joyner  * false otherwise.
189071d10453SEric Joyner  */
1891*7d7af7f8SEric Joyner static bool
1892*7d7af7f8SEric Joyner ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
1893*7d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
189471d10453SEric Joyner {
1895*7d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(elem->logical_id);
1896*7d7af7f8SEric Joyner 	u32 phys_id = LE32_TO_CPU(elem->phys_id);
1897*7d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(elem->number);
1898*7d7af7f8SEric Joyner 	u16 cap = LE16_TO_CPU(elem->cap);
1899*7d7af7f8SEric Joyner 	bool found = true;
190071d10453SEric Joyner 
190171d10453SEric Joyner 	switch (cap) {
190271d10453SEric Joyner 	case ICE_AQC_CAPS_SWITCHING_MODE:
190371d10453SEric Joyner 		caps->switching_mode = number;
1904*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: switching_mode = %d\n", prefix,
190571d10453SEric Joyner 			  caps->switching_mode);
190671d10453SEric Joyner 		break;
190771d10453SEric Joyner 	case ICE_AQC_CAPS_MANAGEABILITY_MODE:
190871d10453SEric Joyner 		caps->mgmt_mode = number;
190971d10453SEric Joyner 		caps->mgmt_protocols_mctp = logical_id;
1910*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_mode = %d\n", prefix,
191171d10453SEric Joyner 			  caps->mgmt_mode);
1912*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_protocols_mctp = %d\n", prefix,
191371d10453SEric Joyner 			  caps->mgmt_protocols_mctp);
191471d10453SEric Joyner 		break;
191571d10453SEric Joyner 	case ICE_AQC_CAPS_OS2BMC:
191671d10453SEric Joyner 		caps->os2bmc = number;
1917*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: os2bmc = %d\n", prefix, caps->os2bmc);
191871d10453SEric Joyner 		break;
191971d10453SEric Joyner 	case ICE_AQC_CAPS_VALID_FUNCTIONS:
192071d10453SEric Joyner 		caps->valid_functions = number;
1921*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix,
192271d10453SEric Joyner 			  caps->valid_functions);
192371d10453SEric Joyner 		break;
192471d10453SEric Joyner 	case ICE_AQC_CAPS_SRIOV:
192571d10453SEric Joyner 		caps->sr_iov_1_1 = (number == 1);
1926*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix,
192771d10453SEric Joyner 			  caps->sr_iov_1_1);
192871d10453SEric Joyner 		break;
192971d10453SEric Joyner 	case ICE_AQC_CAPS_802_1QBG:
193071d10453SEric Joyner 		caps->evb_802_1_qbg = (number == 1);
1931*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbg = %d\n", prefix, number);
193271d10453SEric Joyner 		break;
193371d10453SEric Joyner 	case ICE_AQC_CAPS_802_1BR:
193471d10453SEric Joyner 		caps->evb_802_1_qbh = (number == 1);
1935*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbh = %d\n", prefix, number);
193671d10453SEric Joyner 		break;
193771d10453SEric Joyner 	case ICE_AQC_CAPS_DCB:
193871d10453SEric Joyner 		caps->dcb = (number == 1);
193971d10453SEric Joyner 		caps->active_tc_bitmap = logical_id;
194071d10453SEric Joyner 		caps->maxtc = phys_id;
1941*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb);
1942*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix,
194371d10453SEric Joyner 			  caps->active_tc_bitmap);
1944*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc);
194571d10453SEric Joyner 		break;
194671d10453SEric Joyner 	case ICE_AQC_CAPS_ISCSI:
194771d10453SEric Joyner 		caps->iscsi = (number == 1);
1948*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: iscsi = %d\n", prefix, caps->iscsi);
194971d10453SEric Joyner 		break;
195071d10453SEric Joyner 	case ICE_AQC_CAPS_RSS:
195171d10453SEric Joyner 		caps->rss_table_size = number;
195271d10453SEric Joyner 		caps->rss_table_entry_width = logical_id;
1953*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix,
195471d10453SEric Joyner 			  caps->rss_table_size);
1955*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix,
195671d10453SEric Joyner 			  caps->rss_table_entry_width);
195771d10453SEric Joyner 		break;
195871d10453SEric Joyner 	case ICE_AQC_CAPS_RXQS:
195971d10453SEric Joyner 		caps->num_rxq = number;
196071d10453SEric Joyner 		caps->rxq_first_id = phys_id;
1961*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix,
196271d10453SEric Joyner 			  caps->num_rxq);
1963*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix,
196471d10453SEric Joyner 			  caps->rxq_first_id);
196571d10453SEric Joyner 		break;
196671d10453SEric Joyner 	case ICE_AQC_CAPS_TXQS:
196771d10453SEric Joyner 		caps->num_txq = number;
196871d10453SEric Joyner 		caps->txq_first_id = phys_id;
1969*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix,
197071d10453SEric Joyner 			  caps->num_txq);
1971*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix,
197271d10453SEric Joyner 			  caps->txq_first_id);
197371d10453SEric Joyner 		break;
197471d10453SEric Joyner 	case ICE_AQC_CAPS_MSIX:
197571d10453SEric Joyner 		caps->num_msix_vectors = number;
197671d10453SEric Joyner 		caps->msix_vector_first_id = phys_id;
1977*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix,
197871d10453SEric Joyner 			  caps->num_msix_vectors);
1979*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
198071d10453SEric Joyner 			  caps->msix_vector_first_id);
198171d10453SEric Joyner 		break;
198271d10453SEric Joyner 	case ICE_AQC_CAPS_NVM_VER:
198371d10453SEric Joyner 		break;
198471d10453SEric Joyner 	case ICE_AQC_CAPS_NVM_MGMT:
198571d10453SEric Joyner 		caps->nvm_unified_update =
198671d10453SEric Joyner 			(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
198771d10453SEric Joyner 			true : false;
1988*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
198971d10453SEric Joyner 			  caps->nvm_unified_update);
199071d10453SEric Joyner 		break;
199171d10453SEric Joyner 	case ICE_AQC_CAPS_CEM:
199271d10453SEric Joyner 		caps->mgmt_cem = (number == 1);
1993*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_cem = %d\n", prefix,
199471d10453SEric Joyner 			  caps->mgmt_cem);
199571d10453SEric Joyner 		break;
199671d10453SEric Joyner 	case ICE_AQC_CAPS_LED:
199771d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_LED) {
199871d10453SEric Joyner 			caps->led[phys_id] = true;
199971d10453SEric Joyner 			caps->led_pin_num++;
2000*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = 1\n", prefix, phys_id);
200171d10453SEric Joyner 		}
200271d10453SEric Joyner 		break;
200371d10453SEric Joyner 	case ICE_AQC_CAPS_SDP:
200471d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_SDP) {
200571d10453SEric Joyner 			caps->sdp[phys_id] = true;
200671d10453SEric Joyner 			caps->sdp_pin_num++;
2007*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = 1\n", prefix, phys_id);
200871d10453SEric Joyner 		}
200971d10453SEric Joyner 		break;
201071d10453SEric Joyner 	case ICE_AQC_CAPS_WR_CSR_PROT:
201171d10453SEric Joyner 		caps->wr_csr_prot = number;
201271d10453SEric Joyner 		caps->wr_csr_prot |= (u64)logical_id << 32;
2013*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wr_csr_prot = 0x%llX\n", prefix,
201471d10453SEric Joyner 			  (unsigned long long)caps->wr_csr_prot);
201571d10453SEric Joyner 		break;
201671d10453SEric Joyner 	case ICE_AQC_CAPS_WOL_PROXY:
201771d10453SEric Joyner 		caps->num_wol_proxy_fltr = number;
201871d10453SEric Joyner 		caps->wol_proxy_vsi_seid = logical_id;
201971d10453SEric Joyner 		caps->apm_wol_support = !!(phys_id & ICE_WOL_SUPPORT_M);
202071d10453SEric Joyner 		caps->acpi_prog_mthd = !!(phys_id &
202171d10453SEric Joyner 					  ICE_ACPI_PROG_MTHD_M);
202271d10453SEric Joyner 		caps->proxy_support = !!(phys_id & ICE_PROXY_SUPPORT_M);
2023*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_wol_proxy_fltr = %d\n", prefix,
202471d10453SEric Joyner 			  caps->num_wol_proxy_fltr);
2025*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wol_proxy_vsi_seid = %d\n", prefix,
202671d10453SEric Joyner 			  caps->wol_proxy_vsi_seid);
202771d10453SEric Joyner 		break;
202871d10453SEric Joyner 	case ICE_AQC_CAPS_MAX_MTU:
202971d10453SEric Joyner 		caps->max_mtu = number;
203071d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
203171d10453SEric Joyner 			  prefix, caps->max_mtu);
203271d10453SEric Joyner 		break;
203371d10453SEric Joyner 	default:
2034*7d7af7f8SEric Joyner 		/* Not one of the recognized common capabilities */
2035*7d7af7f8SEric Joyner 		found = false;
203671d10453SEric Joyner 	}
203771d10453SEric Joyner 
2038*7d7af7f8SEric Joyner 	return found;
2039*7d7af7f8SEric Joyner }
204071d10453SEric Joyner 
2041*7d7af7f8SEric Joyner /**
2042*7d7af7f8SEric Joyner  * ice_recalc_port_limited_caps - Recalculate port limited capabilities
2043*7d7af7f8SEric Joyner  * @hw: pointer to the HW structure
2044*7d7af7f8SEric Joyner  * @caps: pointer to capabilities structure to fix
2045*7d7af7f8SEric Joyner  *
2046*7d7af7f8SEric Joyner  * Re-calculate the capabilities that are dependent on the number of physical
2047*7d7af7f8SEric Joyner  * ports; i.e. some features are not supported or function differently on
2048*7d7af7f8SEric Joyner  * devices with more than 4 ports.
2049*7d7af7f8SEric Joyner  */
2050*7d7af7f8SEric Joyner static void
2051*7d7af7f8SEric Joyner ice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
2052*7d7af7f8SEric Joyner {
2053*7d7af7f8SEric Joyner 	/* This assumes device capabilities are always scanned before function
2054*7d7af7f8SEric Joyner 	 * capabilities during the initialization flow.
205571d10453SEric Joyner 	 */
205671d10453SEric Joyner 	if (hw->dev_caps.num_funcs > 4) {
205771d10453SEric Joyner 		/* Max 4 TCs per port */
205871d10453SEric Joyner 		caps->maxtc = 4;
2059*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %d (based on #ports)\n",
206071d10453SEric Joyner 			  caps->maxtc);
206171d10453SEric Joyner 	}
206271d10453SEric Joyner }
206371d10453SEric Joyner 
206471d10453SEric Joyner /**
2065*7d7af7f8SEric Joyner  * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
206671d10453SEric Joyner  * @hw: pointer to the HW struct
2067*7d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
2068*7d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
2069*7d7af7f8SEric Joyner  *
2070*7d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VF.
2071*7d7af7f8SEric Joyner  */
2072*7d7af7f8SEric Joyner static void
2073*7d7af7f8SEric Joyner ice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
2074*7d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
2075*7d7af7f8SEric Joyner {
2076*7d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
2077*7d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(cap->logical_id);
2078*7d7af7f8SEric Joyner 
2079*7d7af7f8SEric Joyner 	func_p->num_allocd_vfs = number;
2080*7d7af7f8SEric Joyner 	func_p->vf_base_id = logical_id;
2081*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n",
2082*7d7af7f8SEric Joyner 		  func_p->num_allocd_vfs);
2083*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n",
2084*7d7af7f8SEric Joyner 		  func_p->vf_base_id);
2085*7d7af7f8SEric Joyner }
2086*7d7af7f8SEric Joyner 
2087*7d7af7f8SEric Joyner /**
2088*7d7af7f8SEric Joyner  * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
2089*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2090*7d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
2091*7d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
2092*7d7af7f8SEric Joyner  *
2093*7d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VSI.
2094*7d7af7f8SEric Joyner  */
2095*7d7af7f8SEric Joyner static void
2096*7d7af7f8SEric Joyner ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
2097*7d7af7f8SEric Joyner 			struct ice_aqc_list_caps_elem *cap)
2098*7d7af7f8SEric Joyner {
2099*7d7af7f8SEric Joyner 	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
2100*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n",
2101*7d7af7f8SEric Joyner 		  LE32_TO_CPU(cap->number));
2102*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n",
2103*7d7af7f8SEric Joyner 		  func_p->guar_num_vsi);
2104*7d7af7f8SEric Joyner }
2105*7d7af7f8SEric Joyner 
2106*7d7af7f8SEric Joyner /**
2107*7d7af7f8SEric Joyner  * ice_parse_func_caps - Parse function capabilities
2108*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2109*7d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
2110*7d7af7f8SEric Joyner  * @buf: buffer containing the function capability records
2111*7d7af7f8SEric Joyner  * @cap_count: the number of capabilities
2112*7d7af7f8SEric Joyner  *
2113*7d7af7f8SEric Joyner  * Helper function to parse function (0x000A) capabilities list. For
2114*7d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
2115*7d7af7f8SEric Joyner  * ice_parse_common_caps.
2116*7d7af7f8SEric Joyner  *
2117*7d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
2118*7d7af7f8SEric Joyner  * data into the function capabilities structured.
2119*7d7af7f8SEric Joyner  */
2120*7d7af7f8SEric Joyner static void
2121*7d7af7f8SEric Joyner ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
2122*7d7af7f8SEric Joyner 		    void *buf, u32 cap_count)
2123*7d7af7f8SEric Joyner {
2124*7d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
2125*7d7af7f8SEric Joyner 	u32 i;
2126*7d7af7f8SEric Joyner 
2127*7d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
2128*7d7af7f8SEric Joyner 
2129*7d7af7f8SEric Joyner 	ice_memset(func_p, 0, sizeof(*func_p), ICE_NONDMA_MEM);
2130*7d7af7f8SEric Joyner 
2131*7d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
2132*7d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
2133*7d7af7f8SEric Joyner 		bool found;
2134*7d7af7f8SEric Joyner 
2135*7d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &func_p->common_cap,
2136*7d7af7f8SEric Joyner 					      &cap_resp[i], "func caps");
2137*7d7af7f8SEric Joyner 
2138*7d7af7f8SEric Joyner 		switch (cap) {
2139*7d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
2140*7d7af7f8SEric Joyner 			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
2141*7d7af7f8SEric Joyner 			break;
2142*7d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
2143*7d7af7f8SEric Joyner 			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
2144*7d7af7f8SEric Joyner 			break;
2145*7d7af7f8SEric Joyner 		default:
2146*7d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
2147*7d7af7f8SEric Joyner 			if (!found)
2148*7d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n",
2149*7d7af7f8SEric Joyner 					  i, cap);
2150*7d7af7f8SEric Joyner 			break;
2151*7d7af7f8SEric Joyner 		}
2152*7d7af7f8SEric Joyner 	}
2153*7d7af7f8SEric Joyner 
2154*7d7af7f8SEric Joyner 	ice_print_led_caps(hw, &func_p->common_cap, "func caps", true);
2155*7d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &func_p->common_cap, "func caps", true);
2156*7d7af7f8SEric Joyner 
2157*7d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
2158*7d7af7f8SEric Joyner }
2159*7d7af7f8SEric Joyner 
2160*7d7af7f8SEric Joyner /**
2161*7d7af7f8SEric Joyner  * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
2162*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2163*7d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
2164*7d7af7f8SEric Joyner  * @cap: capability element to parse
2165*7d7af7f8SEric Joyner  *
2166*7d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
2167*7d7af7f8SEric Joyner  */
2168*7d7af7f8SEric Joyner static void
2169*7d7af7f8SEric Joyner ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2170*7d7af7f8SEric Joyner 			      struct ice_aqc_list_caps_elem *cap)
2171*7d7af7f8SEric Joyner {
2172*7d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
2173*7d7af7f8SEric Joyner 
2174*7d7af7f8SEric Joyner 	dev_p->num_funcs = ice_hweight32(number);
2175*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
2176*7d7af7f8SEric Joyner 		  dev_p->num_funcs);
2177*7d7af7f8SEric Joyner }
2178*7d7af7f8SEric Joyner 
2179*7d7af7f8SEric Joyner /**
2180*7d7af7f8SEric Joyner  * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
2181*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2182*7d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
2183*7d7af7f8SEric Joyner  * @cap: capability element to parse
2184*7d7af7f8SEric Joyner  *
2185*7d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VF for device capabilities.
2186*7d7af7f8SEric Joyner  */
2187*7d7af7f8SEric Joyner static void
2188*7d7af7f8SEric Joyner ice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2189*7d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *cap)
2190*7d7af7f8SEric Joyner {
2191*7d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
2192*7d7af7f8SEric Joyner 
2193*7d7af7f8SEric Joyner 	dev_p->num_vfs_exposed = number;
2194*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n",
2195*7d7af7f8SEric Joyner 		  dev_p->num_vfs_exposed);
2196*7d7af7f8SEric Joyner }
2197*7d7af7f8SEric Joyner 
2198*7d7af7f8SEric Joyner /**
2199*7d7af7f8SEric Joyner  * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
2200*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2201*7d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
2202*7d7af7f8SEric Joyner  * @cap: capability element to parse
2203*7d7af7f8SEric Joyner  *
2204*7d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VSI for device capabilities.
2205*7d7af7f8SEric Joyner  */
2206*7d7af7f8SEric Joyner static void
2207*7d7af7f8SEric Joyner ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2208*7d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
2209*7d7af7f8SEric Joyner {
2210*7d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
2211*7d7af7f8SEric Joyner 
2212*7d7af7f8SEric Joyner 	dev_p->num_vsi_allocd_to_host = number;
2213*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n",
2214*7d7af7f8SEric Joyner 		  dev_p->num_vsi_allocd_to_host);
2215*7d7af7f8SEric Joyner }
2216*7d7af7f8SEric Joyner 
2217*7d7af7f8SEric Joyner /**
2218*7d7af7f8SEric Joyner  * ice_parse_dev_caps - Parse device capabilities
2219*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2220*7d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
2221*7d7af7f8SEric Joyner  * @buf: buffer containing the device capability records
2222*7d7af7f8SEric Joyner  * @cap_count: the number of capabilities
2223*7d7af7f8SEric Joyner  *
2224*7d7af7f8SEric Joyner  * Helper device to parse device (0x000B) capabilities list. For
2225*7d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
2226*7d7af7f8SEric Joyner  * ice_parse_common_caps.
2227*7d7af7f8SEric Joyner  *
2228*7d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
2229*7d7af7f8SEric Joyner  * data into the device capabilities structured.
2230*7d7af7f8SEric Joyner  */
2231*7d7af7f8SEric Joyner static void
2232*7d7af7f8SEric Joyner ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2233*7d7af7f8SEric Joyner 		   void *buf, u32 cap_count)
2234*7d7af7f8SEric Joyner {
2235*7d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
2236*7d7af7f8SEric Joyner 	u32 i;
2237*7d7af7f8SEric Joyner 
2238*7d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
2239*7d7af7f8SEric Joyner 
2240*7d7af7f8SEric Joyner 	ice_memset(dev_p, 0, sizeof(*dev_p), ICE_NONDMA_MEM);
2241*7d7af7f8SEric Joyner 
2242*7d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
2243*7d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
2244*7d7af7f8SEric Joyner 		bool found;
2245*7d7af7f8SEric Joyner 
2246*7d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &dev_p->common_cap,
2247*7d7af7f8SEric Joyner 					      &cap_resp[i], "dev caps");
2248*7d7af7f8SEric Joyner 
2249*7d7af7f8SEric Joyner 		switch (cap) {
2250*7d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VALID_FUNCTIONS:
2251*7d7af7f8SEric Joyner 			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
2252*7d7af7f8SEric Joyner 			break;
2253*7d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
2254*7d7af7f8SEric Joyner 			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
2255*7d7af7f8SEric Joyner 			break;
2256*7d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
2257*7d7af7f8SEric Joyner 			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
2258*7d7af7f8SEric Joyner 			break;
2259*7d7af7f8SEric Joyner 		default:
2260*7d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
2261*7d7af7f8SEric Joyner 			if (!found)
2262*7d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%d]: 0x%x\n",
2263*7d7af7f8SEric Joyner 					  i, cap);
2264*7d7af7f8SEric Joyner 			break;
2265*7d7af7f8SEric Joyner 		}
2266*7d7af7f8SEric Joyner 	}
2267*7d7af7f8SEric Joyner 
2268*7d7af7f8SEric Joyner 	ice_print_led_caps(hw, &dev_p->common_cap, "dev caps", true);
2269*7d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &dev_p->common_cap, "dev caps", true);
2270*7d7af7f8SEric Joyner 
2271*7d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
2272*7d7af7f8SEric Joyner }
2273*7d7af7f8SEric Joyner 
2274*7d7af7f8SEric Joyner /**
2275*7d7af7f8SEric Joyner  * ice_aq_list_caps - query function/device capabilities
2276*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
2277*7d7af7f8SEric Joyner  * @buf: a buffer to hold the capabilities
2278*7d7af7f8SEric Joyner  * @buf_size: size of the buffer
2279*7d7af7f8SEric Joyner  * @cap_count: if not NULL, set to the number of capabilities reported
2280*7d7af7f8SEric Joyner  * @opc: capabilities type to discover, device or function
228171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
228271d10453SEric Joyner  *
2283*7d7af7f8SEric Joyner  * Get the function (0x000A) or device (0x000B) capabilities description from
2284*7d7af7f8SEric Joyner  * firmware and store it in the buffer.
2285*7d7af7f8SEric Joyner  *
2286*7d7af7f8SEric Joyner  * If the cap_count pointer is not NULL, then it is set to the number of
2287*7d7af7f8SEric Joyner  * capabilities firmware will report. Note that if the buffer size is too
2288*7d7af7f8SEric Joyner  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
2289*7d7af7f8SEric Joyner  * cap_count will still be updated in this case. It is recommended that the
2290*7d7af7f8SEric Joyner  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
2291*7d7af7f8SEric Joyner  * firmware could return) to avoid this.
229271d10453SEric Joyner  */
2293*7d7af7f8SEric Joyner static enum ice_status
2294*7d7af7f8SEric Joyner ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
229571d10453SEric Joyner 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
229671d10453SEric Joyner {
229771d10453SEric Joyner 	struct ice_aqc_list_caps *cmd;
229871d10453SEric Joyner 	struct ice_aq_desc desc;
229971d10453SEric Joyner 	enum ice_status status;
230071d10453SEric Joyner 
230171d10453SEric Joyner 	cmd = &desc.params.get_cap;
230271d10453SEric Joyner 
230371d10453SEric Joyner 	if (opc != ice_aqc_opc_list_func_caps &&
230471d10453SEric Joyner 	    opc != ice_aqc_opc_list_dev_caps)
230571d10453SEric Joyner 		return ICE_ERR_PARAM;
230671d10453SEric Joyner 
230771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
230871d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2309*7d7af7f8SEric Joyner 
2310*7d7af7f8SEric Joyner 	if (cap_count)
231171d10453SEric Joyner 		*cap_count = LE32_TO_CPU(cmd->count);
2312*7d7af7f8SEric Joyner 
231371d10453SEric Joyner 	return status;
231471d10453SEric Joyner }
231571d10453SEric Joyner 
231671d10453SEric Joyner /**
2317*7d7af7f8SEric Joyner  * ice_discover_dev_caps - Read and extract device capabilities
231871d10453SEric Joyner  * @hw: pointer to the hardware structure
2319*7d7af7f8SEric Joyner  * @dev_caps: pointer to device capabilities structure
2320*7d7af7f8SEric Joyner  *
2321*7d7af7f8SEric Joyner  * Read the device capabilities and extract them into the dev_caps structure
2322*7d7af7f8SEric Joyner  * for later use.
232371d10453SEric Joyner  */
232471d10453SEric Joyner static enum ice_status
2325*7d7af7f8SEric Joyner ice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
232671d10453SEric Joyner {
232771d10453SEric Joyner 	enum ice_status status;
2328*7d7af7f8SEric Joyner 	u32 cap_count = 0;
232971d10453SEric Joyner 	void *cbuf;
233071d10453SEric Joyner 
2331*7d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
233271d10453SEric Joyner 	if (!cbuf)
233371d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
233471d10453SEric Joyner 
2335*7d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
2336*7d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
2337*7d7af7f8SEric Joyner 	 * possible size that firmware can return.
2338*7d7af7f8SEric Joyner 	 */
2339*7d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
2340*7d7af7f8SEric Joyner 
2341*7d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
2342*7d7af7f8SEric Joyner 				  ice_aqc_opc_list_dev_caps, NULL);
2343*7d7af7f8SEric Joyner 	if (!status)
2344*7d7af7f8SEric Joyner 		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
234571d10453SEric Joyner 	ice_free(hw, cbuf);
234671d10453SEric Joyner 
2347*7d7af7f8SEric Joyner 	return status;
2348*7d7af7f8SEric Joyner }
234971d10453SEric Joyner 
2350*7d7af7f8SEric Joyner /**
2351*7d7af7f8SEric Joyner  * ice_discover_func_caps - Read and extract function capabilities
2352*7d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
2353*7d7af7f8SEric Joyner  * @func_caps: pointer to function capabilities structure
2354*7d7af7f8SEric Joyner  *
2355*7d7af7f8SEric Joyner  * Read the function capabilities and extract them into the func_caps structure
2356*7d7af7f8SEric Joyner  * for later use.
2357*7d7af7f8SEric Joyner  */
2358*7d7af7f8SEric Joyner static enum ice_status
2359*7d7af7f8SEric Joyner ice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
2360*7d7af7f8SEric Joyner {
2361*7d7af7f8SEric Joyner 	enum ice_status status;
2362*7d7af7f8SEric Joyner 	u32 cap_count = 0;
2363*7d7af7f8SEric Joyner 	void *cbuf;
2364*7d7af7f8SEric Joyner 
2365*7d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
2366*7d7af7f8SEric Joyner 	if (!cbuf)
2367*7d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
2368*7d7af7f8SEric Joyner 
2369*7d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
2370*7d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
2371*7d7af7f8SEric Joyner 	 * possible size that firmware can return.
2372*7d7af7f8SEric Joyner 	 */
2373*7d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
2374*7d7af7f8SEric Joyner 
2375*7d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
2376*7d7af7f8SEric Joyner 				  ice_aqc_opc_list_func_caps, NULL);
2377*7d7af7f8SEric Joyner 	if (!status)
2378*7d7af7f8SEric Joyner 		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
2379*7d7af7f8SEric Joyner 	ice_free(hw, cbuf);
238071d10453SEric Joyner 
238171d10453SEric Joyner 	return status;
238271d10453SEric Joyner }
238371d10453SEric Joyner 
238471d10453SEric Joyner /**
238571d10453SEric Joyner  * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
238671d10453SEric Joyner  * @hw: pointer to the hardware structure
238771d10453SEric Joyner  */
238871d10453SEric Joyner void ice_set_safe_mode_caps(struct ice_hw *hw)
238971d10453SEric Joyner {
239071d10453SEric Joyner 	struct ice_hw_func_caps *func_caps = &hw->func_caps;
239171d10453SEric Joyner 	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
239271d10453SEric Joyner 	u32 valid_func, rxq_first_id, txq_first_id;
239371d10453SEric Joyner 	u32 msix_vector_first_id, max_mtu;
239471d10453SEric Joyner 	u32 num_funcs;
239571d10453SEric Joyner 
239671d10453SEric Joyner 	/* cache some func_caps values that should be restored after memset */
239771d10453SEric Joyner 	valid_func = func_caps->common_cap.valid_functions;
239871d10453SEric Joyner 	txq_first_id = func_caps->common_cap.txq_first_id;
239971d10453SEric Joyner 	rxq_first_id = func_caps->common_cap.rxq_first_id;
240071d10453SEric Joyner 	msix_vector_first_id = func_caps->common_cap.msix_vector_first_id;
240171d10453SEric Joyner 	max_mtu = func_caps->common_cap.max_mtu;
240271d10453SEric Joyner 
240371d10453SEric Joyner 	/* unset func capabilities */
240471d10453SEric Joyner 	memset(func_caps, 0, sizeof(*func_caps));
240571d10453SEric Joyner 
240671d10453SEric Joyner 	/* restore cached values */
240771d10453SEric Joyner 	func_caps->common_cap.valid_functions = valid_func;
240871d10453SEric Joyner 	func_caps->common_cap.txq_first_id = txq_first_id;
240971d10453SEric Joyner 	func_caps->common_cap.rxq_first_id = rxq_first_id;
241071d10453SEric Joyner 	func_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
241171d10453SEric Joyner 	func_caps->common_cap.max_mtu = max_mtu;
241271d10453SEric Joyner 
241371d10453SEric Joyner 	/* one Tx and one Rx queue in safe mode */
241471d10453SEric Joyner 	func_caps->common_cap.num_rxq = 1;
241571d10453SEric Joyner 	func_caps->common_cap.num_txq = 1;
241671d10453SEric Joyner 
241771d10453SEric Joyner 	/* two MSIX vectors, one for traffic and one for misc causes */
241871d10453SEric Joyner 	func_caps->common_cap.num_msix_vectors = 2;
241971d10453SEric Joyner 	func_caps->guar_num_vsi = 1;
242071d10453SEric Joyner 
242171d10453SEric Joyner 	/* cache some dev_caps values that should be restored after memset */
242271d10453SEric Joyner 	valid_func = dev_caps->common_cap.valid_functions;
242371d10453SEric Joyner 	txq_first_id = dev_caps->common_cap.txq_first_id;
242471d10453SEric Joyner 	rxq_first_id = dev_caps->common_cap.rxq_first_id;
242571d10453SEric Joyner 	msix_vector_first_id = dev_caps->common_cap.msix_vector_first_id;
242671d10453SEric Joyner 	max_mtu = dev_caps->common_cap.max_mtu;
242771d10453SEric Joyner 	num_funcs = dev_caps->num_funcs;
242871d10453SEric Joyner 
242971d10453SEric Joyner 	/* unset dev capabilities */
243071d10453SEric Joyner 	memset(dev_caps, 0, sizeof(*dev_caps));
243171d10453SEric Joyner 
243271d10453SEric Joyner 	/* restore cached values */
243371d10453SEric Joyner 	dev_caps->common_cap.valid_functions = valid_func;
243471d10453SEric Joyner 	dev_caps->common_cap.txq_first_id = txq_first_id;
243571d10453SEric Joyner 	dev_caps->common_cap.rxq_first_id = rxq_first_id;
243671d10453SEric Joyner 	dev_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
243771d10453SEric Joyner 	dev_caps->common_cap.max_mtu = max_mtu;
243871d10453SEric Joyner 	dev_caps->num_funcs = num_funcs;
243971d10453SEric Joyner 
244071d10453SEric Joyner 	/* one Tx and one Rx queue per function in safe mode */
244171d10453SEric Joyner 	dev_caps->common_cap.num_rxq = num_funcs;
244271d10453SEric Joyner 	dev_caps->common_cap.num_txq = num_funcs;
244371d10453SEric Joyner 
244471d10453SEric Joyner 	/* two MSIX vectors per function */
244571d10453SEric Joyner 	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
244671d10453SEric Joyner }
244771d10453SEric Joyner 
244871d10453SEric Joyner /**
244971d10453SEric Joyner  * ice_get_caps - get info about the HW
245071d10453SEric Joyner  * @hw: pointer to the hardware structure
245171d10453SEric Joyner  */
245271d10453SEric Joyner enum ice_status ice_get_caps(struct ice_hw *hw)
245371d10453SEric Joyner {
245471d10453SEric Joyner 	enum ice_status status;
245571d10453SEric Joyner 
2456*7d7af7f8SEric Joyner 	status = ice_discover_dev_caps(hw, &hw->dev_caps);
2457*7d7af7f8SEric Joyner 	if (status)
245871d10453SEric Joyner 		return status;
2459*7d7af7f8SEric Joyner 
2460*7d7af7f8SEric Joyner 	return ice_discover_func_caps(hw, &hw->func_caps);
246171d10453SEric Joyner }
246271d10453SEric Joyner 
246371d10453SEric Joyner /**
246471d10453SEric Joyner  * ice_aq_manage_mac_write - manage MAC address write command
246571d10453SEric Joyner  * @hw: pointer to the HW struct
246671d10453SEric Joyner  * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
246771d10453SEric Joyner  * @flags: flags to control write behavior
246871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
246971d10453SEric Joyner  *
247071d10453SEric Joyner  * This function is used to write MAC address to the NVM (0x0108).
247171d10453SEric Joyner  */
247271d10453SEric Joyner enum ice_status
247371d10453SEric Joyner ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
247471d10453SEric Joyner 			struct ice_sq_cd *cd)
247571d10453SEric Joyner {
247671d10453SEric Joyner 	struct ice_aqc_manage_mac_write *cmd;
247771d10453SEric Joyner 	struct ice_aq_desc desc;
247871d10453SEric Joyner 
247971d10453SEric Joyner 	cmd = &desc.params.mac_write;
248071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
248171d10453SEric Joyner 
248271d10453SEric Joyner 	cmd->flags = flags;
248371d10453SEric Joyner 	ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_DMA);
248471d10453SEric Joyner 
248571d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
248671d10453SEric Joyner }
248771d10453SEric Joyner 
248871d10453SEric Joyner /**
248971d10453SEric Joyner  * ice_aq_clear_pxe_mode
249071d10453SEric Joyner  * @hw: pointer to the HW struct
249171d10453SEric Joyner  *
249271d10453SEric Joyner  * Tell the firmware that the driver is taking over from PXE (0x0110).
249371d10453SEric Joyner  */
249471d10453SEric Joyner static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw)
249571d10453SEric Joyner {
249671d10453SEric Joyner 	struct ice_aq_desc desc;
249771d10453SEric Joyner 
249871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
249971d10453SEric Joyner 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
250071d10453SEric Joyner 
250171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
250271d10453SEric Joyner }
250371d10453SEric Joyner 
250471d10453SEric Joyner /**
250571d10453SEric Joyner  * ice_clear_pxe_mode - clear pxe operations mode
250671d10453SEric Joyner  * @hw: pointer to the HW struct
250771d10453SEric Joyner  *
250871d10453SEric Joyner  * Make sure all PXE mode settings are cleared, including things
250971d10453SEric Joyner  * like descriptor fetch/write-back mode.
251071d10453SEric Joyner  */
251171d10453SEric Joyner void ice_clear_pxe_mode(struct ice_hw *hw)
251271d10453SEric Joyner {
251371d10453SEric Joyner 	if (ice_check_sq_alive(hw, &hw->adminq))
251471d10453SEric Joyner 		ice_aq_clear_pxe_mode(hw);
251571d10453SEric Joyner }
251671d10453SEric Joyner 
251771d10453SEric Joyner /**
251871d10453SEric Joyner  * ice_aq_set_port_params - set physical port parameters.
251971d10453SEric Joyner  * @pi: pointer to the port info struct
252071d10453SEric Joyner  * @bad_frame_vsi: defines the VSI to which bad frames are forwarded
252171d10453SEric Joyner  * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI
252271d10453SEric Joyner  * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded
252371d10453SEric Joyner  * @double_vlan: if set double VLAN is enabled
252471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
252571d10453SEric Joyner  *
252671d10453SEric Joyner  * Set Physical port parameters (0x0203)
252771d10453SEric Joyner  */
252871d10453SEric Joyner enum ice_status
252971d10453SEric Joyner ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
253071d10453SEric Joyner 		       bool save_bad_pac, bool pad_short_pac, bool double_vlan,
253171d10453SEric Joyner 		       struct ice_sq_cd *cd)
253271d10453SEric Joyner 
253371d10453SEric Joyner {
253471d10453SEric Joyner 	struct ice_aqc_set_port_params *cmd;
253571d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
253671d10453SEric Joyner 	struct ice_aq_desc desc;
253771d10453SEric Joyner 	u16 cmd_flags = 0;
253871d10453SEric Joyner 
253971d10453SEric Joyner 	cmd = &desc.params.set_port_params;
254071d10453SEric Joyner 
254171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
254271d10453SEric Joyner 	cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi);
254371d10453SEric Joyner 	if (save_bad_pac)
254471d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS;
254571d10453SEric Joyner 	if (pad_short_pac)
254671d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS;
254771d10453SEric Joyner 	if (double_vlan)
254871d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
254971d10453SEric Joyner 	cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
255071d10453SEric Joyner 
255171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
255271d10453SEric Joyner }
255371d10453SEric Joyner 
255471d10453SEric Joyner /**
255571d10453SEric Joyner  * ice_get_link_speed_based_on_phy_type - returns link speed
255671d10453SEric Joyner  * @phy_type_low: lower part of phy_type
255771d10453SEric Joyner  * @phy_type_high: higher part of phy_type
255871d10453SEric Joyner  *
255971d10453SEric Joyner  * This helper function will convert an entry in PHY type structure
256071d10453SEric Joyner  * [phy_type_low, phy_type_high] to its corresponding link speed.
256171d10453SEric Joyner  * Note: In the structure of [phy_type_low, phy_type_high], there should
256271d10453SEric Joyner  * be one bit set, as this function will convert one PHY type to its
256371d10453SEric Joyner  * speed.
256471d10453SEric Joyner  * If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
256571d10453SEric Joyner  * If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
256671d10453SEric Joyner  */
256771d10453SEric Joyner static u16
256871d10453SEric Joyner ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
256971d10453SEric Joyner {
257071d10453SEric Joyner 	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
257171d10453SEric Joyner 	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
257271d10453SEric Joyner 
257371d10453SEric Joyner 	switch (phy_type_low) {
257471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100BASE_TX:
257571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100M_SGMII:
257671d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
257771d10453SEric Joyner 		break;
257871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_T:
257971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_SX:
258071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_LX:
258171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_KX:
258271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1G_SGMII:
258371d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
258471d10453SEric Joyner 		break;
258571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_T:
258671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_X:
258771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_KX:
258871d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
258971d10453SEric Joyner 		break;
259071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_T:
259171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_KR:
259271d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
259371d10453SEric Joyner 		break;
259471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_T:
259571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
259671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_SR:
259771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_LR:
259871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
259971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
260071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
260171d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
260271d10453SEric Joyner 		break;
260371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_T:
260471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR:
260571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
260671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
260771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_SR:
260871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_LR:
260971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR:
261071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
261171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
261271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
261371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
261471d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
261571d10453SEric Joyner 		break;
261671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
261771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
261871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
261971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
262071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
262171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI:
262271d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
262371d10453SEric Joyner 		break;
262471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
262571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
262671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
262771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
262871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
262971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2:
263071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
263171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2:
263271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CP:
263371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR:
263471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_FR:
263571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR:
263671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
263771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
263871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1:
263971d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
264071d10453SEric Joyner 		break;
264171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
264271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
264371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
264471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
264571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
264671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4:
264771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
264871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4:
264971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
265071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
265171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
265271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
265371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_DR:
265471d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
265571d10453SEric Joyner 		break;
265671d10453SEric Joyner 	default:
265771d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
265871d10453SEric Joyner 		break;
265971d10453SEric Joyner 	}
266071d10453SEric Joyner 
266171d10453SEric Joyner 	switch (phy_type_high) {
266271d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
266371d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
266471d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
266571d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
266671d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2:
266771d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
266871d10453SEric Joyner 		break;
266971d10453SEric Joyner 	default:
267071d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
267171d10453SEric Joyner 		break;
267271d10453SEric Joyner 	}
267371d10453SEric Joyner 
267471d10453SEric Joyner 	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
267571d10453SEric Joyner 	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
267671d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
267771d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
267871d10453SEric Joyner 		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
267971d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
268071d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
268171d10453SEric Joyner 		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
268271d10453SEric Joyner 		return speed_phy_type_low;
268371d10453SEric Joyner 	else
268471d10453SEric Joyner 		return speed_phy_type_high;
268571d10453SEric Joyner }
268671d10453SEric Joyner 
268771d10453SEric Joyner /**
268871d10453SEric Joyner  * ice_update_phy_type
268971d10453SEric Joyner  * @phy_type_low: pointer to the lower part of phy_type
269071d10453SEric Joyner  * @phy_type_high: pointer to the higher part of phy_type
269171d10453SEric Joyner  * @link_speeds_bitmap: targeted link speeds bitmap
269271d10453SEric Joyner  *
269371d10453SEric Joyner  * Note: For the link_speeds_bitmap structure, you can check it at
269471d10453SEric Joyner  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
269571d10453SEric Joyner  * link_speeds_bitmap include multiple speeds.
269671d10453SEric Joyner  *
269771d10453SEric Joyner  * Each entry in this [phy_type_low, phy_type_high] structure will
269871d10453SEric Joyner  * present a certain link speed. This helper function will turn on bits
269971d10453SEric Joyner  * in [phy_type_low, phy_type_high] structure based on the value of
270071d10453SEric Joyner  * link_speeds_bitmap input parameter.
270171d10453SEric Joyner  */
270271d10453SEric Joyner void
270371d10453SEric Joyner ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
270471d10453SEric Joyner 		    u16 link_speeds_bitmap)
270571d10453SEric Joyner {
270671d10453SEric Joyner 	u64 pt_high;
270771d10453SEric Joyner 	u64 pt_low;
270871d10453SEric Joyner 	int index;
270971d10453SEric Joyner 	u16 speed;
271071d10453SEric Joyner 
271171d10453SEric Joyner 	/* We first check with low part of phy_type */
271271d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
271371d10453SEric Joyner 		pt_low = BIT_ULL(index);
271471d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
271571d10453SEric Joyner 
271671d10453SEric Joyner 		if (link_speeds_bitmap & speed)
271771d10453SEric Joyner 			*phy_type_low |= BIT_ULL(index);
271871d10453SEric Joyner 	}
271971d10453SEric Joyner 
272071d10453SEric Joyner 	/* We then check with high part of phy_type */
272171d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
272271d10453SEric Joyner 		pt_high = BIT_ULL(index);
272371d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
272471d10453SEric Joyner 
272571d10453SEric Joyner 		if (link_speeds_bitmap & speed)
272671d10453SEric Joyner 			*phy_type_high |= BIT_ULL(index);
272771d10453SEric Joyner 	}
272871d10453SEric Joyner }
272971d10453SEric Joyner 
273071d10453SEric Joyner /**
273171d10453SEric Joyner  * ice_aq_set_phy_cfg
273271d10453SEric Joyner  * @hw: pointer to the HW struct
273371d10453SEric Joyner  * @pi: port info structure of the interested logical port
273471d10453SEric Joyner  * @cfg: structure with PHY configuration data to be set
273571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
273671d10453SEric Joyner  *
273771d10453SEric Joyner  * Set the various PHY configuration parameters supported on the Port.
273871d10453SEric Joyner  * One or more of the Set PHY config parameters may be ignored in an MFP
273971d10453SEric Joyner  * mode as the PF may not have the privilege to set some of the PHY Config
274071d10453SEric Joyner  * parameters. This status will be indicated by the command response (0x0601).
274171d10453SEric Joyner  */
274271d10453SEric Joyner enum ice_status
274371d10453SEric Joyner ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
274471d10453SEric Joyner 		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
274571d10453SEric Joyner {
274671d10453SEric Joyner 	struct ice_aq_desc desc;
274771d10453SEric Joyner 	enum ice_status status;
274871d10453SEric Joyner 
274971d10453SEric Joyner 	if (!cfg)
275071d10453SEric Joyner 		return ICE_ERR_PARAM;
275171d10453SEric Joyner 
275271d10453SEric Joyner 	/* Ensure that only valid bits of cfg->caps can be turned on. */
275371d10453SEric Joyner 	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
2754*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
275571d10453SEric Joyner 			  cfg->caps);
275671d10453SEric Joyner 
275771d10453SEric Joyner 		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
275871d10453SEric Joyner 	}
275971d10453SEric Joyner 
276071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
276171d10453SEric Joyner 	desc.params.set_phy.lport_num = pi->lport;
276271d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
276371d10453SEric Joyner 
2764*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
276571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
276671d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_low));
276771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
276871d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_high));
276971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", cfg->caps);
277071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
277171d10453SEric Joyner 		  cfg->low_power_ctrl_an);
277271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", cfg->eee_cap);
277371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n", cfg->eeer_value);
2774*7d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_fec_opt = 0x%x\n",
2775*7d7af7f8SEric Joyner 		  cfg->link_fec_opt);
277671d10453SEric Joyner 
277771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
277871d10453SEric Joyner 
2779*7d7af7f8SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
2780*7d7af7f8SEric Joyner 		status = ICE_SUCCESS;
2781*7d7af7f8SEric Joyner 
278271d10453SEric Joyner 	if (!status)
278371d10453SEric Joyner 		pi->phy.curr_user_phy_cfg = *cfg;
278471d10453SEric Joyner 
278571d10453SEric Joyner 	return status;
278671d10453SEric Joyner }
278771d10453SEric Joyner 
278871d10453SEric Joyner /**
278971d10453SEric Joyner  * ice_update_link_info - update status of the HW network link
279071d10453SEric Joyner  * @pi: port info structure of the interested logical port
279171d10453SEric Joyner  */
279271d10453SEric Joyner enum ice_status ice_update_link_info(struct ice_port_info *pi)
279371d10453SEric Joyner {
279471d10453SEric Joyner 	struct ice_link_status *li;
279571d10453SEric Joyner 	enum ice_status status;
279671d10453SEric Joyner 
279771d10453SEric Joyner 	if (!pi)
279871d10453SEric Joyner 		return ICE_ERR_PARAM;
279971d10453SEric Joyner 
280071d10453SEric Joyner 	li = &pi->phy.link_info;
280171d10453SEric Joyner 
280271d10453SEric Joyner 	status = ice_aq_get_link_info(pi, true, NULL, NULL);
280371d10453SEric Joyner 	if (status)
280471d10453SEric Joyner 		return status;
280571d10453SEric Joyner 
280671d10453SEric Joyner 	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
280771d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
280871d10453SEric Joyner 		struct ice_hw *hw;
280971d10453SEric Joyner 
281071d10453SEric Joyner 		hw = pi->hw;
281171d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
281271d10453SEric Joyner 			ice_malloc(hw, sizeof(*pcaps));
281371d10453SEric Joyner 		if (!pcaps)
281471d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
281571d10453SEric Joyner 
281671d10453SEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
281771d10453SEric Joyner 					     pcaps, NULL);
281871d10453SEric Joyner 
281971d10453SEric Joyner 		ice_free(hw, pcaps);
282071d10453SEric Joyner 	}
282171d10453SEric Joyner 
282271d10453SEric Joyner 	return status;
282371d10453SEric Joyner }
282471d10453SEric Joyner 
282571d10453SEric Joyner /**
282671d10453SEric Joyner  * ice_cache_phy_user_req
282771d10453SEric Joyner  * @pi: port information structure
282871d10453SEric Joyner  * @cache_data: PHY logging data
282971d10453SEric Joyner  * @cache_mode: PHY logging mode
283071d10453SEric Joyner  *
283171d10453SEric Joyner  * Log the user request on (FC, FEC, SPEED) for later user.
283271d10453SEric Joyner  */
283371d10453SEric Joyner static void
283471d10453SEric Joyner ice_cache_phy_user_req(struct ice_port_info *pi,
283571d10453SEric Joyner 		       struct ice_phy_cache_mode_data cache_data,
283671d10453SEric Joyner 		       enum ice_phy_cache_mode cache_mode)
283771d10453SEric Joyner {
283871d10453SEric Joyner 	if (!pi)
283971d10453SEric Joyner 		return;
284071d10453SEric Joyner 
284171d10453SEric Joyner 	switch (cache_mode) {
284271d10453SEric Joyner 	case ICE_FC_MODE:
284371d10453SEric Joyner 		pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
284471d10453SEric Joyner 		break;
284571d10453SEric Joyner 	case ICE_SPEED_MODE:
284671d10453SEric Joyner 		pi->phy.curr_user_speed_req =
284771d10453SEric Joyner 			cache_data.data.curr_user_speed_req;
284871d10453SEric Joyner 		break;
284971d10453SEric Joyner 	case ICE_FEC_MODE:
285071d10453SEric Joyner 		pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
285171d10453SEric Joyner 		break;
285271d10453SEric Joyner 	default:
285371d10453SEric Joyner 		break;
285471d10453SEric Joyner 	}
285571d10453SEric Joyner }
285671d10453SEric Joyner 
285771d10453SEric Joyner /**
285871d10453SEric Joyner  * ice_caps_to_fc_mode
285971d10453SEric Joyner  * @caps: PHY capabilities
286071d10453SEric Joyner  *
286171d10453SEric Joyner  * Convert PHY FC capabilities to ice FC mode
286271d10453SEric Joyner  */
286371d10453SEric Joyner enum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
286471d10453SEric Joyner {
286571d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
286671d10453SEric Joyner 	    caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
286771d10453SEric Joyner 		return ICE_FC_FULL;
286871d10453SEric Joyner 
286971d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
287071d10453SEric Joyner 		return ICE_FC_TX_PAUSE;
287171d10453SEric Joyner 
287271d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
287371d10453SEric Joyner 		return ICE_FC_RX_PAUSE;
287471d10453SEric Joyner 
287571d10453SEric Joyner 	return ICE_FC_NONE;
287671d10453SEric Joyner }
287771d10453SEric Joyner 
287871d10453SEric Joyner /**
287971d10453SEric Joyner  * ice_caps_to_fec_mode
288071d10453SEric Joyner  * @caps: PHY capabilities
288171d10453SEric Joyner  * @fec_options: Link FEC options
288271d10453SEric Joyner  *
288371d10453SEric Joyner  * Convert PHY FEC capabilities to ice FEC mode
288471d10453SEric Joyner  */
288571d10453SEric Joyner enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
288671d10453SEric Joyner {
288771d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_AUTO_FEC)
288871d10453SEric Joyner 		return ICE_FEC_AUTO;
288971d10453SEric Joyner 
289071d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
289171d10453SEric Joyner 			   ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
289271d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
289371d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_REQ))
289471d10453SEric Joyner 		return ICE_FEC_BASER;
289571d10453SEric Joyner 
289671d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
289771d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_544_REQ |
289871d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
289971d10453SEric Joyner 		return ICE_FEC_RS;
290071d10453SEric Joyner 
290171d10453SEric Joyner 	return ICE_FEC_NONE;
290271d10453SEric Joyner }
290371d10453SEric Joyner 
290471d10453SEric Joyner /**
2905*7d7af7f8SEric Joyner  * ice_cfg_phy_fc - Configure PHY FC data based on FC mode
290671d10453SEric Joyner  * @pi: port information structure
2907*7d7af7f8SEric Joyner  * @cfg: PHY configuration data to set FC mode
2908*7d7af7f8SEric Joyner  * @req_mode: FC mode to configure
290971d10453SEric Joyner  */
2910*7d7af7f8SEric Joyner static enum ice_status
2911*7d7af7f8SEric Joyner ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
2912*7d7af7f8SEric Joyner 	       enum ice_fc_mode req_mode)
291371d10453SEric Joyner {
291471d10453SEric Joyner 	struct ice_phy_cache_mode_data cache_data;
2915*7d7af7f8SEric Joyner 	u8 pause_mask = 0x0;
2916*7d7af7f8SEric Joyner 
2917*7d7af7f8SEric Joyner 	if (!pi || !cfg)
2918*7d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
2919*7d7af7f8SEric Joyner 
2920*7d7af7f8SEric Joyner 	switch (req_mode) {
2921*7d7af7f8SEric Joyner 	case ICE_FC_AUTO:
2922*7d7af7f8SEric Joyner 	{
292371d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
292471d10453SEric Joyner 		enum ice_status status;
292571d10453SEric Joyner 
292671d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
2927*7d7af7f8SEric Joyner 			ice_malloc(pi->hw, sizeof(*pcaps));
292871d10453SEric Joyner 		if (!pcaps)
292971d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
293071d10453SEric Joyner 
293171d10453SEric Joyner 		/* Query the value of FC that both the NIC and attached media
293271d10453SEric Joyner 		 * can do.
293371d10453SEric Joyner 		 */
293471d10453SEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
293571d10453SEric Joyner 					     pcaps, NULL);
293671d10453SEric Joyner 		if (status) {
2937*7d7af7f8SEric Joyner 			ice_free(pi->hw, pcaps);
2938*7d7af7f8SEric Joyner 			return status;
293971d10453SEric Joyner 		}
294071d10453SEric Joyner 
294171d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE;
294271d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE;
2943*7d7af7f8SEric Joyner 
2944*7d7af7f8SEric Joyner 		ice_free(pi->hw, pcaps);
294571d10453SEric Joyner 		break;
2946*7d7af7f8SEric Joyner 	}
294771d10453SEric Joyner 	case ICE_FC_FULL:
294871d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
294971d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
295071d10453SEric Joyner 		break;
295171d10453SEric Joyner 	case ICE_FC_RX_PAUSE:
295271d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
295371d10453SEric Joyner 		break;
295471d10453SEric Joyner 	case ICE_FC_TX_PAUSE:
295571d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
295671d10453SEric Joyner 		break;
295771d10453SEric Joyner 	default:
295871d10453SEric Joyner 		break;
295971d10453SEric Joyner 	}
296071d10453SEric Joyner 
2961*7d7af7f8SEric Joyner 	/* clear the old pause settings */
2962*7d7af7f8SEric Joyner 	cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
2963*7d7af7f8SEric Joyner 		ICE_AQC_PHY_EN_RX_LINK_PAUSE);
2964*7d7af7f8SEric Joyner 
2965*7d7af7f8SEric Joyner 	/* set the new capabilities */
2966*7d7af7f8SEric Joyner 	cfg->caps |= pause_mask;
2967*7d7af7f8SEric Joyner 
2968*7d7af7f8SEric Joyner 	/* Cache user FC request */
2969*7d7af7f8SEric Joyner 	cache_data.data.curr_user_fc_req = req_mode;
2970*7d7af7f8SEric Joyner 	ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
2971*7d7af7f8SEric Joyner 
2972*7d7af7f8SEric Joyner 	return ICE_SUCCESS;
2973*7d7af7f8SEric Joyner }
2974*7d7af7f8SEric Joyner 
2975*7d7af7f8SEric Joyner /**
2976*7d7af7f8SEric Joyner  * ice_set_fc
2977*7d7af7f8SEric Joyner  * @pi: port information structure
2978*7d7af7f8SEric Joyner  * @aq_failures: pointer to status code, specific to ice_set_fc routine
2979*7d7af7f8SEric Joyner  * @ena_auto_link_update: enable automatic link update
2980*7d7af7f8SEric Joyner  *
2981*7d7af7f8SEric Joyner  * Set the requested flow control mode.
2982*7d7af7f8SEric Joyner  */
2983*7d7af7f8SEric Joyner enum ice_status
2984*7d7af7f8SEric Joyner ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
2985*7d7af7f8SEric Joyner {
2986*7d7af7f8SEric Joyner 	struct ice_aqc_set_phy_cfg_data  cfg = { 0 };
2987*7d7af7f8SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
2988*7d7af7f8SEric Joyner 	enum ice_status status;
2989*7d7af7f8SEric Joyner 	struct ice_hw *hw;
2990*7d7af7f8SEric Joyner 
2991*7d7af7f8SEric Joyner 	if (!pi || !aq_failures)
2992*7d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
2993*7d7af7f8SEric Joyner 
2994*7d7af7f8SEric Joyner 	*aq_failures = 0;
2995*7d7af7f8SEric Joyner 	hw = pi->hw;
2996*7d7af7f8SEric Joyner 
2997*7d7af7f8SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
2998*7d7af7f8SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
2999*7d7af7f8SEric Joyner 	if (!pcaps)
3000*7d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
3001*7d7af7f8SEric Joyner 
300271d10453SEric Joyner 	/* Get the current PHY config */
300371d10453SEric Joyner 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
300471d10453SEric Joyner 				     NULL);
300571d10453SEric Joyner 	if (status) {
300671d10453SEric Joyner 		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
300771d10453SEric Joyner 		goto out;
300871d10453SEric Joyner 	}
300971d10453SEric Joyner 
301071d10453SEric Joyner 	ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
301171d10453SEric Joyner 
3012*7d7af7f8SEric Joyner 	/* Configure the set PHY data */
3013*7d7af7f8SEric Joyner 	status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
3014*7d7af7f8SEric Joyner 	if (status) {
3015*7d7af7f8SEric Joyner 		if (status != ICE_ERR_BAD_PTR)
3016*7d7af7f8SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
301771d10453SEric Joyner 
3018*7d7af7f8SEric Joyner 		goto out;
3019*7d7af7f8SEric Joyner 	}
302071d10453SEric Joyner 
302171d10453SEric Joyner 	/* If the capabilities have changed, then set the new config */
302271d10453SEric Joyner 	if (cfg.caps != pcaps->caps) {
302371d10453SEric Joyner 		int retry_count, retry_max = 10;
302471d10453SEric Joyner 
302571d10453SEric Joyner 		/* Auto restart link so settings take effect */
302671d10453SEric Joyner 		if (ena_auto_link_update)
302771d10453SEric Joyner 			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
302871d10453SEric Joyner 
302971d10453SEric Joyner 		status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
303071d10453SEric Joyner 		if (status) {
303171d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
303271d10453SEric Joyner 			goto out;
303371d10453SEric Joyner 		}
303471d10453SEric Joyner 
303571d10453SEric Joyner 		/* Update the link info
303671d10453SEric Joyner 		 * It sometimes takes a really long time for link to
303771d10453SEric Joyner 		 * come back from the atomic reset. Thus, we wait a
303871d10453SEric Joyner 		 * little bit.
303971d10453SEric Joyner 		 */
304071d10453SEric Joyner 		for (retry_count = 0; retry_count < retry_max; retry_count++) {
304171d10453SEric Joyner 			status = ice_update_link_info(pi);
304271d10453SEric Joyner 
304371d10453SEric Joyner 			if (status == ICE_SUCCESS)
304471d10453SEric Joyner 				break;
304571d10453SEric Joyner 
304671d10453SEric Joyner 			ice_msec_delay(100, true);
304771d10453SEric Joyner 		}
304871d10453SEric Joyner 
304971d10453SEric Joyner 		if (status)
305071d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
305171d10453SEric Joyner 	}
305271d10453SEric Joyner 
305371d10453SEric Joyner out:
305471d10453SEric Joyner 	ice_free(hw, pcaps);
305571d10453SEric Joyner 	return status;
305671d10453SEric Joyner }
305771d10453SEric Joyner 
305871d10453SEric Joyner /**
305971d10453SEric Joyner  * ice_phy_caps_equals_cfg
306071d10453SEric Joyner  * @phy_caps: PHY capabilities
306171d10453SEric Joyner  * @phy_cfg: PHY configuration
306271d10453SEric Joyner  *
306371d10453SEric Joyner  * Helper function to determine if PHY capabilities matches PHY
306471d10453SEric Joyner  * configuration
306571d10453SEric Joyner  */
306671d10453SEric Joyner bool
306771d10453SEric Joyner ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
306871d10453SEric Joyner 			struct ice_aqc_set_phy_cfg_data *phy_cfg)
306971d10453SEric Joyner {
307071d10453SEric Joyner 	u8 caps_mask, cfg_mask;
307171d10453SEric Joyner 
307271d10453SEric Joyner 	if (!phy_caps || !phy_cfg)
307371d10453SEric Joyner 		return false;
307471d10453SEric Joyner 
307571d10453SEric Joyner 	/* These bits are not common between capabilities and configuration.
307671d10453SEric Joyner 	 * Do not use them to determine equality.
307771d10453SEric Joyner 	 */
307871d10453SEric Joyner 	caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
307971d10453SEric Joyner 					      ICE_AQC_PHY_EN_MOD_QUAL);
308071d10453SEric Joyner 	cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
308171d10453SEric Joyner 
308271d10453SEric Joyner 	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
308371d10453SEric Joyner 	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
308471d10453SEric Joyner 	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
308571d10453SEric Joyner 	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
308671d10453SEric Joyner 	    phy_caps->eee_cap != phy_cfg->eee_cap ||
308771d10453SEric Joyner 	    phy_caps->eeer_value != phy_cfg->eeer_value ||
308871d10453SEric Joyner 	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
308971d10453SEric Joyner 		return false;
309071d10453SEric Joyner 
309171d10453SEric Joyner 	return true;
309271d10453SEric Joyner }
309371d10453SEric Joyner 
309471d10453SEric Joyner /**
309571d10453SEric Joyner  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
309671d10453SEric Joyner  * @pi: port information structure
309771d10453SEric Joyner  * @caps: PHY ability structure to copy date from
309871d10453SEric Joyner  * @cfg: PHY configuration structure to copy data to
309971d10453SEric Joyner  *
310071d10453SEric Joyner  * Helper function to copy AQC PHY get ability data to PHY set configuration
310171d10453SEric Joyner  * data structure
310271d10453SEric Joyner  */
310371d10453SEric Joyner void
310471d10453SEric Joyner ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
310571d10453SEric Joyner 			 struct ice_aqc_get_phy_caps_data *caps,
310671d10453SEric Joyner 			 struct ice_aqc_set_phy_cfg_data *cfg)
310771d10453SEric Joyner {
310871d10453SEric Joyner 	if (!pi || !caps || !cfg)
310971d10453SEric Joyner 		return;
311071d10453SEric Joyner 
311171d10453SEric Joyner 	ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
311271d10453SEric Joyner 	cfg->phy_type_low = caps->phy_type_low;
311371d10453SEric Joyner 	cfg->phy_type_high = caps->phy_type_high;
311471d10453SEric Joyner 	cfg->caps = caps->caps;
311571d10453SEric Joyner 	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
311671d10453SEric Joyner 	cfg->eee_cap = caps->eee_cap;
311771d10453SEric Joyner 	cfg->eeer_value = caps->eeer_value;
311871d10453SEric Joyner 	cfg->link_fec_opt = caps->link_fec_options;
311971d10453SEric Joyner 	cfg->module_compliance_enforcement =
312071d10453SEric Joyner 		caps->module_compliance_enforcement;
312171d10453SEric Joyner 
312271d10453SEric Joyner 	if (ice_fw_supports_link_override(pi->hw)) {
312371d10453SEric Joyner 		struct ice_link_default_override_tlv tlv;
312471d10453SEric Joyner 
312571d10453SEric Joyner 		if (ice_get_link_default_override(&tlv, pi))
312671d10453SEric Joyner 			return;
312771d10453SEric Joyner 
312871d10453SEric Joyner 		if (tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE)
312971d10453SEric Joyner 			cfg->module_compliance_enforcement |=
313071d10453SEric Joyner 				ICE_LINK_OVERRIDE_STRICT_MODE;
313171d10453SEric Joyner 	}
313271d10453SEric Joyner }
313371d10453SEric Joyner 
313471d10453SEric Joyner /**
313571d10453SEric Joyner  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
313671d10453SEric Joyner  * @pi: port information structure
313771d10453SEric Joyner  * @cfg: PHY configuration data to set FEC mode
313871d10453SEric Joyner  * @fec: FEC mode to configure
313971d10453SEric Joyner  */
314071d10453SEric Joyner enum ice_status
314171d10453SEric Joyner ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
314271d10453SEric Joyner 		enum ice_fec_mode fec)
314371d10453SEric Joyner {
314471d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
314571d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
314671d10453SEric Joyner 	struct ice_hw *hw;
314771d10453SEric Joyner 
314871d10453SEric Joyner 	if (!pi || !cfg)
314971d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
315071d10453SEric Joyner 
315171d10453SEric Joyner 	hw = pi->hw;
315271d10453SEric Joyner 
315371d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
315471d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
315571d10453SEric Joyner 	if (!pcaps)
315671d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
315771d10453SEric Joyner 
315871d10453SEric Joyner 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps,
315971d10453SEric Joyner 				     NULL);
316071d10453SEric Joyner 	if (status)
316171d10453SEric Joyner 		goto out;
316271d10453SEric Joyner 
3163*7d7af7f8SEric Joyner 	cfg->caps |= (pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC);
3164*7d7af7f8SEric Joyner 	cfg->link_fec_opt = pcaps->link_fec_options;
3165*7d7af7f8SEric Joyner 
316671d10453SEric Joyner 	switch (fec) {
316771d10453SEric Joyner 	case ICE_FEC_BASER:
316871d10453SEric Joyner 		/* Clear RS bits, and AND BASE-R ability
316971d10453SEric Joyner 		 * bits and OR request bits.
317071d10453SEric Joyner 		 */
317171d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
317271d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
317371d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
317471d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_REQ;
317571d10453SEric Joyner 		break;
317671d10453SEric Joyner 	case ICE_FEC_RS:
317771d10453SEric Joyner 		/* Clear BASE-R bits, and AND RS ability
317871d10453SEric Joyner 		 * bits and OR request bits.
317971d10453SEric Joyner 		 */
318071d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
318171d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
318271d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_RS_544_REQ;
318371d10453SEric Joyner 		break;
318471d10453SEric Joyner 	case ICE_FEC_NONE:
318571d10453SEric Joyner 		/* Clear all FEC option bits. */
318671d10453SEric Joyner 		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
318771d10453SEric Joyner 		break;
318871d10453SEric Joyner 	case ICE_FEC_AUTO:
318971d10453SEric Joyner 		/* AND auto FEC bit, and all caps bits. */
319071d10453SEric Joyner 		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
319171d10453SEric Joyner 		cfg->link_fec_opt |= pcaps->link_fec_options;
319271d10453SEric Joyner 		break;
319371d10453SEric Joyner 	default:
319471d10453SEric Joyner 		status = ICE_ERR_PARAM;
319571d10453SEric Joyner 		break;
319671d10453SEric Joyner 	}
319771d10453SEric Joyner 
319871d10453SEric Joyner 	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw)) {
319971d10453SEric Joyner 		struct ice_link_default_override_tlv tlv;
320071d10453SEric Joyner 
320171d10453SEric Joyner 		if (ice_get_link_default_override(&tlv, pi))
320271d10453SEric Joyner 			goto out;
320371d10453SEric Joyner 
320471d10453SEric Joyner 		if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
320571d10453SEric Joyner 		    (tlv.options & ICE_LINK_OVERRIDE_EN))
320671d10453SEric Joyner 			cfg->link_fec_opt = tlv.fec_options;
320771d10453SEric Joyner 	}
320871d10453SEric Joyner 
320971d10453SEric Joyner out:
321071d10453SEric Joyner 	ice_free(hw, pcaps);
321171d10453SEric Joyner 
321271d10453SEric Joyner 	return status;
321371d10453SEric Joyner }
321471d10453SEric Joyner 
321571d10453SEric Joyner /**
321671d10453SEric Joyner  * ice_get_link_status - get status of the HW network link
321771d10453SEric Joyner  * @pi: port information structure
321871d10453SEric Joyner  * @link_up: pointer to bool (true/false = linkup/linkdown)
321971d10453SEric Joyner  *
322071d10453SEric Joyner  * Variable link_up is true if link is up, false if link is down.
322171d10453SEric Joyner  * The variable link_up is invalid if status is non zero. As a
322271d10453SEric Joyner  * result of this call, link status reporting becomes enabled
322371d10453SEric Joyner  */
322471d10453SEric Joyner enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up)
322571d10453SEric Joyner {
322671d10453SEric Joyner 	struct ice_phy_info *phy_info;
322771d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
322871d10453SEric Joyner 
322971d10453SEric Joyner 	if (!pi || !link_up)
323071d10453SEric Joyner 		return ICE_ERR_PARAM;
323171d10453SEric Joyner 
323271d10453SEric Joyner 	phy_info = &pi->phy;
323371d10453SEric Joyner 
323471d10453SEric Joyner 	if (phy_info->get_link_info) {
323571d10453SEric Joyner 		status = ice_update_link_info(pi);
323671d10453SEric Joyner 
323771d10453SEric Joyner 		if (status)
3238*7d7af7f8SEric Joyner 			ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n",
323971d10453SEric Joyner 				  status);
324071d10453SEric Joyner 	}
324171d10453SEric Joyner 
324271d10453SEric Joyner 	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
324371d10453SEric Joyner 
324471d10453SEric Joyner 	return status;
324571d10453SEric Joyner }
324671d10453SEric Joyner 
324771d10453SEric Joyner /**
324871d10453SEric Joyner  * ice_aq_set_link_restart_an
324971d10453SEric Joyner  * @pi: pointer to the port information structure
325071d10453SEric Joyner  * @ena_link: if true: enable link, if false: disable link
325171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
325271d10453SEric Joyner  *
325371d10453SEric Joyner  * Sets up the link and restarts the Auto-Negotiation over the link.
325471d10453SEric Joyner  */
325571d10453SEric Joyner enum ice_status
325671d10453SEric Joyner ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
325771d10453SEric Joyner 			   struct ice_sq_cd *cd)
325871d10453SEric Joyner {
325971d10453SEric Joyner 	struct ice_aqc_restart_an *cmd;
326071d10453SEric Joyner 	struct ice_aq_desc desc;
326171d10453SEric Joyner 
326271d10453SEric Joyner 	cmd = &desc.params.restart_an;
326371d10453SEric Joyner 
326471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
326571d10453SEric Joyner 
326671d10453SEric Joyner 	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
326771d10453SEric Joyner 	cmd->lport_num = pi->lport;
326871d10453SEric Joyner 	if (ena_link)
326971d10453SEric Joyner 		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
327071d10453SEric Joyner 	else
327171d10453SEric Joyner 		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
327271d10453SEric Joyner 
327371d10453SEric Joyner 	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
327471d10453SEric Joyner }
327571d10453SEric Joyner 
327671d10453SEric Joyner /**
327771d10453SEric Joyner  * ice_aq_set_event_mask
327871d10453SEric Joyner  * @hw: pointer to the HW struct
327971d10453SEric Joyner  * @port_num: port number of the physical function
328071d10453SEric Joyner  * @mask: event mask to be set
328171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
328271d10453SEric Joyner  *
328371d10453SEric Joyner  * Set event mask (0x0613)
328471d10453SEric Joyner  */
328571d10453SEric Joyner enum ice_status
328671d10453SEric Joyner ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
328771d10453SEric Joyner 		      struct ice_sq_cd *cd)
328871d10453SEric Joyner {
328971d10453SEric Joyner 	struct ice_aqc_set_event_mask *cmd;
329071d10453SEric Joyner 	struct ice_aq_desc desc;
329171d10453SEric Joyner 
329271d10453SEric Joyner 	cmd = &desc.params.set_event_mask;
329371d10453SEric Joyner 
329471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
329571d10453SEric Joyner 
329671d10453SEric Joyner 	cmd->lport_num = port_num;
329771d10453SEric Joyner 
329871d10453SEric Joyner 	cmd->event_mask = CPU_TO_LE16(mask);
329971d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
330071d10453SEric Joyner }
330171d10453SEric Joyner 
330271d10453SEric Joyner /**
330371d10453SEric Joyner  * ice_aq_set_mac_loopback
330471d10453SEric Joyner  * @hw: pointer to the HW struct
330571d10453SEric Joyner  * @ena_lpbk: Enable or Disable loopback
330671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
330771d10453SEric Joyner  *
330871d10453SEric Joyner  * Enable/disable loopback on a given port
330971d10453SEric Joyner  */
331071d10453SEric Joyner enum ice_status
331171d10453SEric Joyner ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
331271d10453SEric Joyner {
331371d10453SEric Joyner 	struct ice_aqc_set_mac_lb *cmd;
331471d10453SEric Joyner 	struct ice_aq_desc desc;
331571d10453SEric Joyner 
331671d10453SEric Joyner 	cmd = &desc.params.set_mac_lb;
331771d10453SEric Joyner 
331871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
331971d10453SEric Joyner 	if (ena_lpbk)
332071d10453SEric Joyner 		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
332171d10453SEric Joyner 
332271d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
332371d10453SEric Joyner }
332471d10453SEric Joyner 
332571d10453SEric Joyner /**
332671d10453SEric Joyner  * ice_aq_set_port_id_led
332771d10453SEric Joyner  * @pi: pointer to the port information
332871d10453SEric Joyner  * @is_orig_mode: is this LED set to original mode (by the net-list)
332971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
333071d10453SEric Joyner  *
333171d10453SEric Joyner  * Set LED value for the given port (0x06e9)
333271d10453SEric Joyner  */
333371d10453SEric Joyner enum ice_status
333471d10453SEric Joyner ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
333571d10453SEric Joyner 		       struct ice_sq_cd *cd)
333671d10453SEric Joyner {
333771d10453SEric Joyner 	struct ice_aqc_set_port_id_led *cmd;
333871d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
333971d10453SEric Joyner 	struct ice_aq_desc desc;
334071d10453SEric Joyner 
334171d10453SEric Joyner 	cmd = &desc.params.set_port_id_led;
334271d10453SEric Joyner 
334371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
334471d10453SEric Joyner 
334571d10453SEric Joyner 	if (is_orig_mode)
334671d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
334771d10453SEric Joyner 	else
334871d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
334971d10453SEric Joyner 
335071d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
335171d10453SEric Joyner }
335271d10453SEric Joyner 
335371d10453SEric Joyner /**
335471d10453SEric Joyner  * ice_aq_sff_eeprom
335571d10453SEric Joyner  * @hw: pointer to the HW struct
335671d10453SEric Joyner  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
335771d10453SEric Joyner  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
335871d10453SEric Joyner  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
335971d10453SEric Joyner  * @page: QSFP page
336071d10453SEric Joyner  * @set_page: set or ignore the page
336171d10453SEric Joyner  * @data: pointer to data buffer to be read/written to the I2C device.
336271d10453SEric Joyner  * @length: 1-16 for read, 1 for write.
336371d10453SEric Joyner  * @write: 0 read, 1 for write.
336471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
336571d10453SEric Joyner  *
336671d10453SEric Joyner  * Read/Write SFF EEPROM (0x06EE)
336771d10453SEric Joyner  */
336871d10453SEric Joyner enum ice_status
336971d10453SEric Joyner ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
337071d10453SEric Joyner 		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
337171d10453SEric Joyner 		  bool write, struct ice_sq_cd *cd)
337271d10453SEric Joyner {
337371d10453SEric Joyner 	struct ice_aqc_sff_eeprom *cmd;
337471d10453SEric Joyner 	struct ice_aq_desc desc;
337571d10453SEric Joyner 	enum ice_status status;
337671d10453SEric Joyner 
337771d10453SEric Joyner 	if (!data || (mem_addr & 0xff00))
337871d10453SEric Joyner 		return ICE_ERR_PARAM;
337971d10453SEric Joyner 
338071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
338171d10453SEric Joyner 	cmd = &desc.params.read_write_sff_param;
338271d10453SEric Joyner 	desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD | ICE_AQ_FLAG_BUF);
338371d10453SEric Joyner 	cmd->lport_num = (u8)(lport & 0xff);
338471d10453SEric Joyner 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
338571d10453SEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(((bus_addr >> 1) &
338671d10453SEric Joyner 					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
338771d10453SEric Joyner 					((set_page <<
338871d10453SEric Joyner 					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
338971d10453SEric Joyner 					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
339071d10453SEric Joyner 	cmd->i2c_mem_addr = CPU_TO_LE16(mem_addr & 0xff);
339171d10453SEric Joyner 	cmd->eeprom_page = CPU_TO_LE16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
339271d10453SEric Joyner 	if (write)
339371d10453SEric Joyner 		cmd->i2c_bus_addr |= CPU_TO_LE16(ICE_AQC_SFF_IS_WRITE);
339471d10453SEric Joyner 
339571d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
339671d10453SEric Joyner 	return status;
339771d10453SEric Joyner }
339871d10453SEric Joyner 
339971d10453SEric Joyner /**
340071d10453SEric Joyner  * __ice_aq_get_set_rss_lut
340171d10453SEric Joyner  * @hw: pointer to the hardware structure
340271d10453SEric Joyner  * @vsi_id: VSI FW index
340371d10453SEric Joyner  * @lut_type: LUT table type
340471d10453SEric Joyner  * @lut: pointer to the LUT buffer provided by the caller
340571d10453SEric Joyner  * @lut_size: size of the LUT buffer
340671d10453SEric Joyner  * @glob_lut_idx: global LUT index
340771d10453SEric Joyner  * @set: set true to set the table, false to get the table
340871d10453SEric Joyner  *
340971d10453SEric Joyner  * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
341071d10453SEric Joyner  */
341171d10453SEric Joyner static enum ice_status
341271d10453SEric Joyner __ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
341371d10453SEric Joyner 			 u16 lut_size, u8 glob_lut_idx, bool set)
341471d10453SEric Joyner {
341571d10453SEric Joyner 	struct ice_aqc_get_set_rss_lut *cmd_resp;
341671d10453SEric Joyner 	struct ice_aq_desc desc;
341771d10453SEric Joyner 	enum ice_status status;
341871d10453SEric Joyner 	u16 flags = 0;
341971d10453SEric Joyner 
342071d10453SEric Joyner 	cmd_resp = &desc.params.get_set_rss_lut;
342171d10453SEric Joyner 
342271d10453SEric Joyner 	if (set) {
342371d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut);
342471d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
342571d10453SEric Joyner 	} else {
342671d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut);
342771d10453SEric Joyner 	}
342871d10453SEric Joyner 
342971d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
343071d10453SEric Joyner 					 ICE_AQC_GSET_RSS_LUT_VSI_ID_S) &
343171d10453SEric Joyner 					ICE_AQC_GSET_RSS_LUT_VSI_ID_M) |
343271d10453SEric Joyner 				       ICE_AQC_GSET_RSS_LUT_VSI_VALID);
343371d10453SEric Joyner 
343471d10453SEric Joyner 	switch (lut_type) {
343571d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI:
343671d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF:
343771d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL:
343871d10453SEric Joyner 		flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) &
343971d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M);
344071d10453SEric Joyner 		break;
344171d10453SEric Joyner 	default:
344271d10453SEric Joyner 		status = ICE_ERR_PARAM;
344371d10453SEric Joyner 		goto ice_aq_get_set_rss_lut_exit;
344471d10453SEric Joyner 	}
344571d10453SEric Joyner 
344671d10453SEric Joyner 	if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) {
344771d10453SEric Joyner 		flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) &
344871d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M);
344971d10453SEric Joyner 
345071d10453SEric Joyner 		if (!set)
345171d10453SEric Joyner 			goto ice_aq_get_set_rss_lut_send;
345271d10453SEric Joyner 	} else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
345371d10453SEric Joyner 		if (!set)
345471d10453SEric Joyner 			goto ice_aq_get_set_rss_lut_send;
345571d10453SEric Joyner 	} else {
345671d10453SEric Joyner 		goto ice_aq_get_set_rss_lut_send;
345771d10453SEric Joyner 	}
345871d10453SEric Joyner 
345971d10453SEric Joyner 	/* LUT size is only valid for Global and PF table types */
346071d10453SEric Joyner 	switch (lut_size) {
346171d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128:
346271d10453SEric Joyner 		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG <<
346371d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
346471d10453SEric Joyner 			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
346571d10453SEric Joyner 		break;
346671d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512:
346771d10453SEric Joyner 		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG <<
346871d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
346971d10453SEric Joyner 			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
347071d10453SEric Joyner 		break;
347171d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K:
347271d10453SEric Joyner 		if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
347371d10453SEric Joyner 			flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG <<
347471d10453SEric Joyner 				  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
347571d10453SEric Joyner 				 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
347671d10453SEric Joyner 			break;
347771d10453SEric Joyner 		}
347871d10453SEric Joyner 		/* fall-through */
347971d10453SEric Joyner 	default:
348071d10453SEric Joyner 		status = ICE_ERR_PARAM;
348171d10453SEric Joyner 		goto ice_aq_get_set_rss_lut_exit;
348271d10453SEric Joyner 	}
348371d10453SEric Joyner 
348471d10453SEric Joyner ice_aq_get_set_rss_lut_send:
348571d10453SEric Joyner 	cmd_resp->flags = CPU_TO_LE16(flags);
348671d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
348771d10453SEric Joyner 
348871d10453SEric Joyner ice_aq_get_set_rss_lut_exit:
348971d10453SEric Joyner 	return status;
349071d10453SEric Joyner }
349171d10453SEric Joyner 
349271d10453SEric Joyner /**
349371d10453SEric Joyner  * ice_aq_get_rss_lut
349471d10453SEric Joyner  * @hw: pointer to the hardware structure
349571d10453SEric Joyner  * @vsi_handle: software VSI handle
349671d10453SEric Joyner  * @lut_type: LUT table type
349771d10453SEric Joyner  * @lut: pointer to the LUT buffer provided by the caller
349871d10453SEric Joyner  * @lut_size: size of the LUT buffer
349971d10453SEric Joyner  *
350071d10453SEric Joyner  * get the RSS lookup table, PF or VSI type
350171d10453SEric Joyner  */
350271d10453SEric Joyner enum ice_status
350371d10453SEric Joyner ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type,
350471d10453SEric Joyner 		   u8 *lut, u16 lut_size)
350571d10453SEric Joyner {
350671d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
350771d10453SEric Joyner 		return ICE_ERR_PARAM;
350871d10453SEric Joyner 
350971d10453SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle),
351071d10453SEric Joyner 					lut_type, lut, lut_size, 0, false);
351171d10453SEric Joyner }
351271d10453SEric Joyner 
351371d10453SEric Joyner /**
351471d10453SEric Joyner  * ice_aq_set_rss_lut
351571d10453SEric Joyner  * @hw: pointer to the hardware structure
351671d10453SEric Joyner  * @vsi_handle: software VSI handle
351771d10453SEric Joyner  * @lut_type: LUT table type
351871d10453SEric Joyner  * @lut: pointer to the LUT buffer provided by the caller
351971d10453SEric Joyner  * @lut_size: size of the LUT buffer
352071d10453SEric Joyner  *
352171d10453SEric Joyner  * set the RSS lookup table, PF or VSI type
352271d10453SEric Joyner  */
352371d10453SEric Joyner enum ice_status
352471d10453SEric Joyner ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type,
352571d10453SEric Joyner 		   u8 *lut, u16 lut_size)
352671d10453SEric Joyner {
352771d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
352871d10453SEric Joyner 		return ICE_ERR_PARAM;
352971d10453SEric Joyner 
353071d10453SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle),
353171d10453SEric Joyner 					lut_type, lut, lut_size, 0, true);
353271d10453SEric Joyner }
353371d10453SEric Joyner 
353471d10453SEric Joyner /**
353571d10453SEric Joyner  * __ice_aq_get_set_rss_key
353671d10453SEric Joyner  * @hw: pointer to the HW struct
353771d10453SEric Joyner  * @vsi_id: VSI FW index
353871d10453SEric Joyner  * @key: pointer to key info struct
353971d10453SEric Joyner  * @set: set true to set the key, false to get the key
354071d10453SEric Joyner  *
354171d10453SEric Joyner  * get (0x0B04) or set (0x0B02) the RSS key per VSI
354271d10453SEric Joyner  */
354371d10453SEric Joyner static enum
354471d10453SEric Joyner ice_status __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
354571d10453SEric Joyner 				    struct ice_aqc_get_set_rss_keys *key,
354671d10453SEric Joyner 				    bool set)
354771d10453SEric Joyner {
354871d10453SEric Joyner 	struct ice_aqc_get_set_rss_key *cmd_resp;
354971d10453SEric Joyner 	u16 key_size = sizeof(*key);
355071d10453SEric Joyner 	struct ice_aq_desc desc;
355171d10453SEric Joyner 
355271d10453SEric Joyner 	cmd_resp = &desc.params.get_set_rss_key;
355371d10453SEric Joyner 
355471d10453SEric Joyner 	if (set) {
355571d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
355671d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
355771d10453SEric Joyner 	} else {
355871d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
355971d10453SEric Joyner 	}
356071d10453SEric Joyner 
356171d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
356271d10453SEric Joyner 					 ICE_AQC_GSET_RSS_KEY_VSI_ID_S) &
356371d10453SEric Joyner 					ICE_AQC_GSET_RSS_KEY_VSI_ID_M) |
356471d10453SEric Joyner 				       ICE_AQC_GSET_RSS_KEY_VSI_VALID);
356571d10453SEric Joyner 
356671d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
356771d10453SEric Joyner }
356871d10453SEric Joyner 
356971d10453SEric Joyner /**
357071d10453SEric Joyner  * ice_aq_get_rss_key
357171d10453SEric Joyner  * @hw: pointer to the HW struct
357271d10453SEric Joyner  * @vsi_handle: software VSI handle
357371d10453SEric Joyner  * @key: pointer to key info struct
357471d10453SEric Joyner  *
357571d10453SEric Joyner  * get the RSS key per VSI
357671d10453SEric Joyner  */
357771d10453SEric Joyner enum ice_status
357871d10453SEric Joyner ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
357971d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *key)
358071d10453SEric Joyner {
358171d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
358271d10453SEric Joyner 		return ICE_ERR_PARAM;
358371d10453SEric Joyner 
358471d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
358571d10453SEric Joyner 					key, false);
358671d10453SEric Joyner }
358771d10453SEric Joyner 
358871d10453SEric Joyner /**
358971d10453SEric Joyner  * ice_aq_set_rss_key
359071d10453SEric Joyner  * @hw: pointer to the HW struct
359171d10453SEric Joyner  * @vsi_handle: software VSI handle
359271d10453SEric Joyner  * @keys: pointer to key info struct
359371d10453SEric Joyner  *
359471d10453SEric Joyner  * set the RSS key per VSI
359571d10453SEric Joyner  */
359671d10453SEric Joyner enum ice_status
359771d10453SEric Joyner ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
359871d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *keys)
359971d10453SEric Joyner {
360071d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
360171d10453SEric Joyner 		return ICE_ERR_PARAM;
360271d10453SEric Joyner 
360371d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
360471d10453SEric Joyner 					keys, true);
360571d10453SEric Joyner }
360671d10453SEric Joyner 
360771d10453SEric Joyner /**
360871d10453SEric Joyner  * ice_aq_add_lan_txq
360971d10453SEric Joyner  * @hw: pointer to the hardware structure
361071d10453SEric Joyner  * @num_qgrps: Number of added queue groups
361171d10453SEric Joyner  * @qg_list: list of queue groups to be added
361271d10453SEric Joyner  * @buf_size: size of buffer for indirect command
361371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
361471d10453SEric Joyner  *
361571d10453SEric Joyner  * Add Tx LAN queue (0x0C30)
361671d10453SEric Joyner  *
361771d10453SEric Joyner  * NOTE:
361871d10453SEric Joyner  * Prior to calling add Tx LAN queue:
361971d10453SEric Joyner  * Initialize the following as part of the Tx queue context:
362071d10453SEric Joyner  * Completion queue ID if the queue uses Completion queue, Quanta profile,
362171d10453SEric Joyner  * Cache profile and Packet shaper profile.
362271d10453SEric Joyner  *
362371d10453SEric Joyner  * After add Tx LAN queue AQ command is completed:
362471d10453SEric Joyner  * Interrupts should be associated with specific queues,
362571d10453SEric Joyner  * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
362671d10453SEric Joyner  * flow.
362771d10453SEric Joyner  */
362871d10453SEric Joyner enum ice_status
362971d10453SEric Joyner ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
363071d10453SEric Joyner 		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
363171d10453SEric Joyner 		   struct ice_sq_cd *cd)
363271d10453SEric Joyner {
363371d10453SEric Joyner 	struct ice_aqc_add_tx_qgrp *list;
363471d10453SEric Joyner 	struct ice_aqc_add_txqs *cmd;
363571d10453SEric Joyner 	struct ice_aq_desc desc;
3636*7d7af7f8SEric Joyner 	u16 i, sum_size = 0;
363771d10453SEric Joyner 
363871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
363971d10453SEric Joyner 
364071d10453SEric Joyner 	cmd = &desc.params.add_txqs;
364171d10453SEric Joyner 
364271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
364371d10453SEric Joyner 
364471d10453SEric Joyner 	if (!qg_list)
364571d10453SEric Joyner 		return ICE_ERR_PARAM;
364671d10453SEric Joyner 
364771d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
364871d10453SEric Joyner 		return ICE_ERR_PARAM;
364971d10453SEric Joyner 
3650*7d7af7f8SEric Joyner 	for (i = 0, list = qg_list; i < num_qgrps; i++) {
3651*7d7af7f8SEric Joyner 		sum_size += ice_struct_size(list, txqs, list->num_txqs);
3652*7d7af7f8SEric Joyner 		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
3653*7d7af7f8SEric Joyner 						      list->num_txqs);
365471d10453SEric Joyner 	}
365571d10453SEric Joyner 
3656*7d7af7f8SEric Joyner 	if (buf_size != sum_size)
365771d10453SEric Joyner 		return ICE_ERR_PARAM;
365871d10453SEric Joyner 
365971d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
366071d10453SEric Joyner 
366171d10453SEric Joyner 	cmd->num_qgrps = num_qgrps;
366271d10453SEric Joyner 
366371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
366471d10453SEric Joyner }
366571d10453SEric Joyner 
366671d10453SEric Joyner /**
366771d10453SEric Joyner  * ice_aq_dis_lan_txq
366871d10453SEric Joyner  * @hw: pointer to the hardware structure
366971d10453SEric Joyner  * @num_qgrps: number of groups in the list
367071d10453SEric Joyner  * @qg_list: the list of groups to disable
367171d10453SEric Joyner  * @buf_size: the total size of the qg_list buffer in bytes
367271d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
367371d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
367471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
367571d10453SEric Joyner  *
367671d10453SEric Joyner  * Disable LAN Tx queue (0x0C31)
367771d10453SEric Joyner  */
367871d10453SEric Joyner static enum ice_status
367971d10453SEric Joyner ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
368071d10453SEric Joyner 		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
368171d10453SEric Joyner 		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
368271d10453SEric Joyner 		   struct ice_sq_cd *cd)
368371d10453SEric Joyner {
3684*7d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *item;
368571d10453SEric Joyner 	struct ice_aqc_dis_txqs *cmd;
368671d10453SEric Joyner 	struct ice_aq_desc desc;
368771d10453SEric Joyner 	enum ice_status status;
368871d10453SEric Joyner 	u16 i, sz = 0;
368971d10453SEric Joyner 
369071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
369171d10453SEric Joyner 	cmd = &desc.params.dis_txqs;
369271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
369371d10453SEric Joyner 
369471d10453SEric Joyner 	/* qg_list can be NULL only in VM/VF reset flow */
369571d10453SEric Joyner 	if (!qg_list && !rst_src)
369671d10453SEric Joyner 		return ICE_ERR_PARAM;
369771d10453SEric Joyner 
369871d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
369971d10453SEric Joyner 		return ICE_ERR_PARAM;
370071d10453SEric Joyner 
370171d10453SEric Joyner 	cmd->num_entries = num_qgrps;
370271d10453SEric Joyner 
370371d10453SEric Joyner 	cmd->vmvf_and_timeout = CPU_TO_LE16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
370471d10453SEric Joyner 					    ICE_AQC_Q_DIS_TIMEOUT_M);
370571d10453SEric Joyner 
370671d10453SEric Joyner 	switch (rst_src) {
370771d10453SEric Joyner 	case ICE_VM_RESET:
370871d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
370971d10453SEric Joyner 		cmd->vmvf_and_timeout |=
371071d10453SEric Joyner 			CPU_TO_LE16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
371171d10453SEric Joyner 		break;
371271d10453SEric Joyner 	case ICE_VF_RESET:
371371d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
371471d10453SEric Joyner 		/* In this case, FW expects vmvf_num to be absolute VF ID */
371571d10453SEric Joyner 		cmd->vmvf_and_timeout |=
371671d10453SEric Joyner 			CPU_TO_LE16((vmvf_num + hw->func_caps.vf_base_id) &
371771d10453SEric Joyner 				    ICE_AQC_Q_DIS_VMVF_NUM_M);
371871d10453SEric Joyner 		break;
371971d10453SEric Joyner 	case ICE_NO_RESET:
372071d10453SEric Joyner 	default:
372171d10453SEric Joyner 		break;
372271d10453SEric Joyner 	}
372371d10453SEric Joyner 
372471d10453SEric Joyner 	/* flush pipe on time out */
372571d10453SEric Joyner 	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
372671d10453SEric Joyner 	/* If no queue group info, we are in a reset flow. Issue the AQ */
372771d10453SEric Joyner 	if (!qg_list)
372871d10453SEric Joyner 		goto do_aq;
372971d10453SEric Joyner 
373071d10453SEric Joyner 	/* set RD bit to indicate that command buffer is provided by the driver
373171d10453SEric Joyner 	 * and it needs to be read by the firmware
373271d10453SEric Joyner 	 */
373371d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
373471d10453SEric Joyner 
3735*7d7af7f8SEric Joyner 	for (i = 0, item = qg_list; i < num_qgrps; i++) {
3736*7d7af7f8SEric Joyner 		u16 item_size = ice_struct_size(item, q_id, item->num_qs);
373771d10453SEric Joyner 
373871d10453SEric Joyner 		/* If the num of queues is even, add 2 bytes of padding */
3739*7d7af7f8SEric Joyner 		if ((item->num_qs % 2) == 0)
3740*7d7af7f8SEric Joyner 			item_size += 2;
3741*7d7af7f8SEric Joyner 
3742*7d7af7f8SEric Joyner 		sz += item_size;
3743*7d7af7f8SEric Joyner 
3744*7d7af7f8SEric Joyner 		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
374571d10453SEric Joyner 	}
374671d10453SEric Joyner 
374771d10453SEric Joyner 	if (buf_size != sz)
374871d10453SEric Joyner 		return ICE_ERR_PARAM;
374971d10453SEric Joyner 
375071d10453SEric Joyner do_aq:
375171d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
375271d10453SEric Joyner 	if (status) {
375371d10453SEric Joyner 		if (!qg_list)
375471d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
375571d10453SEric Joyner 				  vmvf_num, hw->adminq.sq_last_status);
375671d10453SEric Joyner 		else
375771d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
375871d10453SEric Joyner 				  LE16_TO_CPU(qg_list[0].q_id[0]),
375971d10453SEric Joyner 				  hw->adminq.sq_last_status);
376071d10453SEric Joyner 	}
376171d10453SEric Joyner 	return status;
376271d10453SEric Joyner }
376371d10453SEric Joyner 
376471d10453SEric Joyner /**
376571d10453SEric Joyner  * ice_aq_move_recfg_lan_txq
376671d10453SEric Joyner  * @hw: pointer to the hardware structure
376771d10453SEric Joyner  * @num_qs: number of queues to move/reconfigure
376871d10453SEric Joyner  * @is_move: true if this operation involves node movement
376971d10453SEric Joyner  * @is_tc_change: true if this operation involves a TC change
377071d10453SEric Joyner  * @subseq_call: true if this operation is a subsequent call
377171d10453SEric Joyner  * @flush_pipe: on timeout, true to flush pipe, false to return EAGAIN
377271d10453SEric Joyner  * @timeout: timeout in units of 100 usec (valid values 0-50)
377371d10453SEric Joyner  * @blocked_cgds: out param, bitmap of CGDs that timed out if returning EAGAIN
377471d10453SEric Joyner  * @buf: struct containing src/dest TEID and per-queue info
377571d10453SEric Joyner  * @buf_size: size of buffer for indirect command
377671d10453SEric Joyner  * @txqs_moved: out param, number of queues successfully moved
377771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
377871d10453SEric Joyner  *
377971d10453SEric Joyner  * Move / Reconfigure Tx LAN queues (0x0C32)
378071d10453SEric Joyner  */
378171d10453SEric Joyner enum ice_status
378271d10453SEric Joyner ice_aq_move_recfg_lan_txq(struct ice_hw *hw, u8 num_qs, bool is_move,
378371d10453SEric Joyner 			  bool is_tc_change, bool subseq_call, bool flush_pipe,
378471d10453SEric Joyner 			  u8 timeout, u32 *blocked_cgds,
378571d10453SEric Joyner 			  struct ice_aqc_move_txqs_data *buf, u16 buf_size,
378671d10453SEric Joyner 			  u8 *txqs_moved, struct ice_sq_cd *cd)
378771d10453SEric Joyner {
378871d10453SEric Joyner 	struct ice_aqc_move_txqs *cmd;
378971d10453SEric Joyner 	struct ice_aq_desc desc;
379071d10453SEric Joyner 	enum ice_status status;
379171d10453SEric Joyner 
379271d10453SEric Joyner 	cmd = &desc.params.move_txqs;
379371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_move_recfg_txqs);
379471d10453SEric Joyner 
379571d10453SEric Joyner #define ICE_LAN_TXQ_MOVE_TIMEOUT_MAX 50
379671d10453SEric Joyner 	if (timeout > ICE_LAN_TXQ_MOVE_TIMEOUT_MAX)
379771d10453SEric Joyner 		return ICE_ERR_PARAM;
379871d10453SEric Joyner 
379971d10453SEric Joyner 	if (is_tc_change && !flush_pipe && !blocked_cgds)
380071d10453SEric Joyner 		return ICE_ERR_PARAM;
380171d10453SEric Joyner 
380271d10453SEric Joyner 	if (!is_move && !is_tc_change)
380371d10453SEric Joyner 		return ICE_ERR_PARAM;
380471d10453SEric Joyner 
380571d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
380671d10453SEric Joyner 
380771d10453SEric Joyner 	if (is_move)
380871d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_MOVE;
380971d10453SEric Joyner 
381071d10453SEric Joyner 	if (is_tc_change)
381171d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_TC_CHANGE;
381271d10453SEric Joyner 
381371d10453SEric Joyner 	if (subseq_call)
381471d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_SUBSEQ_CALL;
381571d10453SEric Joyner 
381671d10453SEric Joyner 	if (flush_pipe)
381771d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_FLUSH_PIPE;
381871d10453SEric Joyner 
381971d10453SEric Joyner 	cmd->num_qs = num_qs;
382071d10453SEric Joyner 	cmd->timeout = ((timeout << ICE_AQC_Q_CMD_TIMEOUT_S) &
382171d10453SEric Joyner 			ICE_AQC_Q_CMD_TIMEOUT_M);
382271d10453SEric Joyner 
382371d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
382471d10453SEric Joyner 
382571d10453SEric Joyner 	if (!status && txqs_moved)
382671d10453SEric Joyner 		*txqs_moved = cmd->num_qs;
382771d10453SEric Joyner 
382871d10453SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EAGAIN &&
382971d10453SEric Joyner 	    is_tc_change && !flush_pipe)
383071d10453SEric Joyner 		*blocked_cgds = LE32_TO_CPU(cmd->blocked_cgds);
383171d10453SEric Joyner 
383271d10453SEric Joyner 	return status;
383371d10453SEric Joyner }
383471d10453SEric Joyner 
383571d10453SEric Joyner /* End of FW Admin Queue command wrappers */
383671d10453SEric Joyner 
383771d10453SEric Joyner /**
383871d10453SEric Joyner  * ice_write_byte - write a byte to a packed context structure
383971d10453SEric Joyner  * @src_ctx:  the context structure to read from
384071d10453SEric Joyner  * @dest_ctx: the context to be written to
384171d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
384271d10453SEric Joyner  */
384371d10453SEric Joyner static void
384471d10453SEric Joyner ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
384571d10453SEric Joyner {
384671d10453SEric Joyner 	u8 src_byte, dest_byte, mask;
384771d10453SEric Joyner 	u8 *from, *dest;
384871d10453SEric Joyner 	u16 shift_width;
384971d10453SEric Joyner 
385071d10453SEric Joyner 	/* copy from the next struct field */
385171d10453SEric Joyner 	from = src_ctx + ce_info->offset;
385271d10453SEric Joyner 
385371d10453SEric Joyner 	/* prepare the bits and mask */
385471d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
385571d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
385671d10453SEric Joyner 
385771d10453SEric Joyner 	src_byte = *from;
385871d10453SEric Joyner 	src_byte &= mask;
385971d10453SEric Joyner 
386071d10453SEric Joyner 	/* shift to correct alignment */
386171d10453SEric Joyner 	mask <<= shift_width;
386271d10453SEric Joyner 	src_byte <<= shift_width;
386371d10453SEric Joyner 
386471d10453SEric Joyner 	/* get the current bits from the target bit string */
386571d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
386671d10453SEric Joyner 
386771d10453SEric Joyner 	ice_memcpy(&dest_byte, dest, sizeof(dest_byte), ICE_DMA_TO_NONDMA);
386871d10453SEric Joyner 
386971d10453SEric Joyner 	dest_byte &= ~mask;	/* get the bits not changing */
387071d10453SEric Joyner 	dest_byte |= src_byte;	/* add in the new bits */
387171d10453SEric Joyner 
387271d10453SEric Joyner 	/* put it all back */
387371d10453SEric Joyner 	ice_memcpy(dest, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA);
387471d10453SEric Joyner }
387571d10453SEric Joyner 
387671d10453SEric Joyner /**
387771d10453SEric Joyner  * ice_write_word - write a word to a packed context structure
387871d10453SEric Joyner  * @src_ctx:  the context structure to read from
387971d10453SEric Joyner  * @dest_ctx: the context to be written to
388071d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
388171d10453SEric Joyner  */
388271d10453SEric Joyner static void
388371d10453SEric Joyner ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
388471d10453SEric Joyner {
388571d10453SEric Joyner 	u16 src_word, mask;
388671d10453SEric Joyner 	__le16 dest_word;
388771d10453SEric Joyner 	u8 *from, *dest;
388871d10453SEric Joyner 	u16 shift_width;
388971d10453SEric Joyner 
389071d10453SEric Joyner 	/* copy from the next struct field */
389171d10453SEric Joyner 	from = src_ctx + ce_info->offset;
389271d10453SEric Joyner 
389371d10453SEric Joyner 	/* prepare the bits and mask */
389471d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
389571d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
389671d10453SEric Joyner 
389771d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
389871d10453SEric Joyner 	 * will be in a different bit position on big endian machines
389971d10453SEric Joyner 	 */
390071d10453SEric Joyner 	src_word = *(u16 *)from;
390171d10453SEric Joyner 	src_word &= mask;
390271d10453SEric Joyner 
390371d10453SEric Joyner 	/* shift to correct alignment */
390471d10453SEric Joyner 	mask <<= shift_width;
390571d10453SEric Joyner 	src_word <<= shift_width;
390671d10453SEric Joyner 
390771d10453SEric Joyner 	/* get the current bits from the target bit string */
390871d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
390971d10453SEric Joyner 
391071d10453SEric Joyner 	ice_memcpy(&dest_word, dest, sizeof(dest_word), ICE_DMA_TO_NONDMA);
391171d10453SEric Joyner 
391271d10453SEric Joyner 	dest_word &= ~(CPU_TO_LE16(mask));	/* get the bits not changing */
391371d10453SEric Joyner 	dest_word |= CPU_TO_LE16(src_word);	/* add in the new bits */
391471d10453SEric Joyner 
391571d10453SEric Joyner 	/* put it all back */
391671d10453SEric Joyner 	ice_memcpy(dest, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA);
391771d10453SEric Joyner }
391871d10453SEric Joyner 
391971d10453SEric Joyner /**
392071d10453SEric Joyner  * ice_write_dword - write a dword to a packed context structure
392171d10453SEric Joyner  * @src_ctx:  the context structure to read from
392271d10453SEric Joyner  * @dest_ctx: the context to be written to
392371d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
392471d10453SEric Joyner  */
392571d10453SEric Joyner static void
392671d10453SEric Joyner ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
392771d10453SEric Joyner {
392871d10453SEric Joyner 	u32 src_dword, mask;
392971d10453SEric Joyner 	__le32 dest_dword;
393071d10453SEric Joyner 	u8 *from, *dest;
393171d10453SEric Joyner 	u16 shift_width;
393271d10453SEric Joyner 
393371d10453SEric Joyner 	/* copy from the next struct field */
393471d10453SEric Joyner 	from = src_ctx + ce_info->offset;
393571d10453SEric Joyner 
393671d10453SEric Joyner 	/* prepare the bits and mask */
393771d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
393871d10453SEric Joyner 
393971d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
394071d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
394171d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
394271d10453SEric Joyner 	 */
394371d10453SEric Joyner 	if (ce_info->width < 32)
394471d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
394571d10453SEric Joyner 	else
394671d10453SEric Joyner 		mask = (u32)~0;
394771d10453SEric Joyner 
394871d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
394971d10453SEric Joyner 	 * will be in a different bit position on big endian machines
395071d10453SEric Joyner 	 */
395171d10453SEric Joyner 	src_dword = *(u32 *)from;
395271d10453SEric Joyner 	src_dword &= mask;
395371d10453SEric Joyner 
395471d10453SEric Joyner 	/* shift to correct alignment */
395571d10453SEric Joyner 	mask <<= shift_width;
395671d10453SEric Joyner 	src_dword <<= shift_width;
395771d10453SEric Joyner 
395871d10453SEric Joyner 	/* get the current bits from the target bit string */
395971d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
396071d10453SEric Joyner 
396171d10453SEric Joyner 	ice_memcpy(&dest_dword, dest, sizeof(dest_dword), ICE_DMA_TO_NONDMA);
396271d10453SEric Joyner 
396371d10453SEric Joyner 	dest_dword &= ~(CPU_TO_LE32(mask));	/* get the bits not changing */
396471d10453SEric Joyner 	dest_dword |= CPU_TO_LE32(src_dword);	/* add in the new bits */
396571d10453SEric Joyner 
396671d10453SEric Joyner 	/* put it all back */
396771d10453SEric Joyner 	ice_memcpy(dest, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA);
396871d10453SEric Joyner }
396971d10453SEric Joyner 
397071d10453SEric Joyner /**
397171d10453SEric Joyner  * ice_write_qword - write a qword to a packed context structure
397271d10453SEric Joyner  * @src_ctx:  the context structure to read from
397371d10453SEric Joyner  * @dest_ctx: the context to be written to
397471d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
397571d10453SEric Joyner  */
397671d10453SEric Joyner static void
397771d10453SEric Joyner ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
397871d10453SEric Joyner {
397971d10453SEric Joyner 	u64 src_qword, mask;
398071d10453SEric Joyner 	__le64 dest_qword;
398171d10453SEric Joyner 	u8 *from, *dest;
398271d10453SEric Joyner 	u16 shift_width;
398371d10453SEric Joyner 
398471d10453SEric Joyner 	/* copy from the next struct field */
398571d10453SEric Joyner 	from = src_ctx + ce_info->offset;
398671d10453SEric Joyner 
398771d10453SEric Joyner 	/* prepare the bits and mask */
398871d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
398971d10453SEric Joyner 
399071d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
399171d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
399271d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
399371d10453SEric Joyner 	 */
399471d10453SEric Joyner 	if (ce_info->width < 64)
399571d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
399671d10453SEric Joyner 	else
399771d10453SEric Joyner 		mask = (u64)~0;
399871d10453SEric Joyner 
399971d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
400071d10453SEric Joyner 	 * will be in a different bit position on big endian machines
400171d10453SEric Joyner 	 */
400271d10453SEric Joyner 	src_qword = *(u64 *)from;
400371d10453SEric Joyner 	src_qword &= mask;
400471d10453SEric Joyner 
400571d10453SEric Joyner 	/* shift to correct alignment */
400671d10453SEric Joyner 	mask <<= shift_width;
400771d10453SEric Joyner 	src_qword <<= shift_width;
400871d10453SEric Joyner 
400971d10453SEric Joyner 	/* get the current bits from the target bit string */
401071d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
401171d10453SEric Joyner 
401271d10453SEric Joyner 	ice_memcpy(&dest_qword, dest, sizeof(dest_qword), ICE_DMA_TO_NONDMA);
401371d10453SEric Joyner 
401471d10453SEric Joyner 	dest_qword &= ~(CPU_TO_LE64(mask));	/* get the bits not changing */
401571d10453SEric Joyner 	dest_qword |= CPU_TO_LE64(src_qword);	/* add in the new bits */
401671d10453SEric Joyner 
401771d10453SEric Joyner 	/* put it all back */
401871d10453SEric Joyner 	ice_memcpy(dest, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA);
401971d10453SEric Joyner }
402071d10453SEric Joyner 
402171d10453SEric Joyner /**
402271d10453SEric Joyner  * ice_set_ctx - set context bits in packed structure
4023*7d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
402471d10453SEric Joyner  * @src_ctx:  pointer to a generic non-packed context structure
402571d10453SEric Joyner  * @dest_ctx: pointer to memory for the packed structure
402671d10453SEric Joyner  * @ce_info:  a description of the structure to be transformed
402771d10453SEric Joyner  */
402871d10453SEric Joyner enum ice_status
4029*7d7af7f8SEric Joyner ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
4030*7d7af7f8SEric Joyner 	    const struct ice_ctx_ele *ce_info)
403171d10453SEric Joyner {
403271d10453SEric Joyner 	int f;
403371d10453SEric Joyner 
403471d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
403571d10453SEric Joyner 		/* We have to deal with each element of the FW response
403671d10453SEric Joyner 		 * using the correct size so that we are correct regardless
403771d10453SEric Joyner 		 * of the endianness of the machine.
403871d10453SEric Joyner 		 */
4039*7d7af7f8SEric Joyner 		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
4040*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
4041*7d7af7f8SEric Joyner 				  f, ce_info[f].width, ce_info[f].size_of);
4042*7d7af7f8SEric Joyner 			continue;
4043*7d7af7f8SEric Joyner 		}
404471d10453SEric Joyner 		switch (ce_info[f].size_of) {
404571d10453SEric Joyner 		case sizeof(u8):
404671d10453SEric Joyner 			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
404771d10453SEric Joyner 			break;
404871d10453SEric Joyner 		case sizeof(u16):
404971d10453SEric Joyner 			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
405071d10453SEric Joyner 			break;
405171d10453SEric Joyner 		case sizeof(u32):
405271d10453SEric Joyner 			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
405371d10453SEric Joyner 			break;
405471d10453SEric Joyner 		case sizeof(u64):
405571d10453SEric Joyner 			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
405671d10453SEric Joyner 			break;
405771d10453SEric Joyner 		default:
405871d10453SEric Joyner 			return ICE_ERR_INVAL_SIZE;
405971d10453SEric Joyner 		}
406071d10453SEric Joyner 	}
406171d10453SEric Joyner 
406271d10453SEric Joyner 	return ICE_SUCCESS;
406371d10453SEric Joyner }
406471d10453SEric Joyner 
406571d10453SEric Joyner /**
406671d10453SEric Joyner  * ice_read_byte - read context byte into struct
406771d10453SEric Joyner  * @src_ctx:  the context structure to read from
406871d10453SEric Joyner  * @dest_ctx: the context to be written to
406971d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
407071d10453SEric Joyner  */
407171d10453SEric Joyner static void
407271d10453SEric Joyner ice_read_byte(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
407371d10453SEric Joyner {
407471d10453SEric Joyner 	u8 dest_byte, mask;
407571d10453SEric Joyner 	u8 *src, *target;
407671d10453SEric Joyner 	u16 shift_width;
407771d10453SEric Joyner 
407871d10453SEric Joyner 	/* prepare the bits and mask */
407971d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
408071d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
408171d10453SEric Joyner 
408271d10453SEric Joyner 	/* shift to correct alignment */
408371d10453SEric Joyner 	mask <<= shift_width;
408471d10453SEric Joyner 
408571d10453SEric Joyner 	/* get the current bits from the src bit string */
408671d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
408771d10453SEric Joyner 
408871d10453SEric Joyner 	ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_DMA_TO_NONDMA);
408971d10453SEric Joyner 
409071d10453SEric Joyner 	dest_byte &= ~(mask);
409171d10453SEric Joyner 
409271d10453SEric Joyner 	dest_byte >>= shift_width;
409371d10453SEric Joyner 
409471d10453SEric Joyner 	/* get the address from the struct field */
409571d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
409671d10453SEric Joyner 
409771d10453SEric Joyner 	/* put it back in the struct */
409871d10453SEric Joyner 	ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA);
409971d10453SEric Joyner }
410071d10453SEric Joyner 
410171d10453SEric Joyner /**
410271d10453SEric Joyner  * ice_read_word - read context word into struct
410371d10453SEric Joyner  * @src_ctx:  the context structure to read from
410471d10453SEric Joyner  * @dest_ctx: the context to be written to
410571d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
410671d10453SEric Joyner  */
410771d10453SEric Joyner static void
410871d10453SEric Joyner ice_read_word(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
410971d10453SEric Joyner {
411071d10453SEric Joyner 	u16 dest_word, mask;
411171d10453SEric Joyner 	u8 *src, *target;
411271d10453SEric Joyner 	__le16 src_word;
411371d10453SEric Joyner 	u16 shift_width;
411471d10453SEric Joyner 
411571d10453SEric Joyner 	/* prepare the bits and mask */
411671d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
411771d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
411871d10453SEric Joyner 
411971d10453SEric Joyner 	/* shift to correct alignment */
412071d10453SEric Joyner 	mask <<= shift_width;
412171d10453SEric Joyner 
412271d10453SEric Joyner 	/* get the current bits from the src bit string */
412371d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
412471d10453SEric Joyner 
412571d10453SEric Joyner 	ice_memcpy(&src_word, src, sizeof(src_word), ICE_DMA_TO_NONDMA);
412671d10453SEric Joyner 
412771d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
412871d10453SEric Joyner 	 * correctly
412971d10453SEric Joyner 	 */
413071d10453SEric Joyner 	src_word &= ~(CPU_TO_LE16(mask));
413171d10453SEric Joyner 
413271d10453SEric Joyner 	/* get the data back into host order before shifting */
413371d10453SEric Joyner 	dest_word = LE16_TO_CPU(src_word);
413471d10453SEric Joyner 
413571d10453SEric Joyner 	dest_word >>= shift_width;
413671d10453SEric Joyner 
413771d10453SEric Joyner 	/* get the address from the struct field */
413871d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
413971d10453SEric Joyner 
414071d10453SEric Joyner 	/* put it back in the struct */
414171d10453SEric Joyner 	ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA);
414271d10453SEric Joyner }
414371d10453SEric Joyner 
414471d10453SEric Joyner /**
414571d10453SEric Joyner  * ice_read_dword - read context dword into struct
414671d10453SEric Joyner  * @src_ctx:  the context structure to read from
414771d10453SEric Joyner  * @dest_ctx: the context to be written to
414871d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
414971d10453SEric Joyner  */
415071d10453SEric Joyner static void
415171d10453SEric Joyner ice_read_dword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
415271d10453SEric Joyner {
415371d10453SEric Joyner 	u32 dest_dword, mask;
415471d10453SEric Joyner 	__le32 src_dword;
415571d10453SEric Joyner 	u8 *src, *target;
415671d10453SEric Joyner 	u16 shift_width;
415771d10453SEric Joyner 
415871d10453SEric Joyner 	/* prepare the bits and mask */
415971d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
416071d10453SEric Joyner 
416171d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
416271d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
416371d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
416471d10453SEric Joyner 	 */
416571d10453SEric Joyner 	if (ce_info->width < 32)
416671d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
416771d10453SEric Joyner 	else
416871d10453SEric Joyner 		mask = (u32)~0;
416971d10453SEric Joyner 
417071d10453SEric Joyner 	/* shift to correct alignment */
417171d10453SEric Joyner 	mask <<= shift_width;
417271d10453SEric Joyner 
417371d10453SEric Joyner 	/* get the current bits from the src bit string */
417471d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
417571d10453SEric Joyner 
417671d10453SEric Joyner 	ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_DMA_TO_NONDMA);
417771d10453SEric Joyner 
417871d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
417971d10453SEric Joyner 	 * correctly
418071d10453SEric Joyner 	 */
418171d10453SEric Joyner 	src_dword &= ~(CPU_TO_LE32(mask));
418271d10453SEric Joyner 
418371d10453SEric Joyner 	/* get the data back into host order before shifting */
418471d10453SEric Joyner 	dest_dword = LE32_TO_CPU(src_dword);
418571d10453SEric Joyner 
418671d10453SEric Joyner 	dest_dword >>= shift_width;
418771d10453SEric Joyner 
418871d10453SEric Joyner 	/* get the address from the struct field */
418971d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
419071d10453SEric Joyner 
419171d10453SEric Joyner 	/* put it back in the struct */
419271d10453SEric Joyner 	ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA);
419371d10453SEric Joyner }
419471d10453SEric Joyner 
419571d10453SEric Joyner /**
419671d10453SEric Joyner  * ice_read_qword - read context qword into struct
419771d10453SEric Joyner  * @src_ctx:  the context structure to read from
419871d10453SEric Joyner  * @dest_ctx: the context to be written to
419971d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
420071d10453SEric Joyner  */
420171d10453SEric Joyner static void
420271d10453SEric Joyner ice_read_qword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
420371d10453SEric Joyner {
420471d10453SEric Joyner 	u64 dest_qword, mask;
420571d10453SEric Joyner 	__le64 src_qword;
420671d10453SEric Joyner 	u8 *src, *target;
420771d10453SEric Joyner 	u16 shift_width;
420871d10453SEric Joyner 
420971d10453SEric Joyner 	/* prepare the bits and mask */
421071d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
421171d10453SEric Joyner 
421271d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
421371d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
421471d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
421571d10453SEric Joyner 	 */
421671d10453SEric Joyner 	if (ce_info->width < 64)
421771d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
421871d10453SEric Joyner 	else
421971d10453SEric Joyner 		mask = (u64)~0;
422071d10453SEric Joyner 
422171d10453SEric Joyner 	/* shift to correct alignment */
422271d10453SEric Joyner 	mask <<= shift_width;
422371d10453SEric Joyner 
422471d10453SEric Joyner 	/* get the current bits from the src bit string */
422571d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
422671d10453SEric Joyner 
422771d10453SEric Joyner 	ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_DMA_TO_NONDMA);
422871d10453SEric Joyner 
422971d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
423071d10453SEric Joyner 	 * correctly
423171d10453SEric Joyner 	 */
423271d10453SEric Joyner 	src_qword &= ~(CPU_TO_LE64(mask));
423371d10453SEric Joyner 
423471d10453SEric Joyner 	/* get the data back into host order before shifting */
423571d10453SEric Joyner 	dest_qword = LE64_TO_CPU(src_qword);
423671d10453SEric Joyner 
423771d10453SEric Joyner 	dest_qword >>= shift_width;
423871d10453SEric Joyner 
423971d10453SEric Joyner 	/* get the address from the struct field */
424071d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
424171d10453SEric Joyner 
424271d10453SEric Joyner 	/* put it back in the struct */
424371d10453SEric Joyner 	ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA);
424471d10453SEric Joyner }
424571d10453SEric Joyner 
424671d10453SEric Joyner /**
424771d10453SEric Joyner  * ice_get_ctx - extract context bits from a packed structure
424871d10453SEric Joyner  * @src_ctx:  pointer to a generic packed context structure
424971d10453SEric Joyner  * @dest_ctx: pointer to a generic non-packed context structure
425071d10453SEric Joyner  * @ce_info:  a description of the structure to be read from
425171d10453SEric Joyner  */
425271d10453SEric Joyner enum ice_status
425371d10453SEric Joyner ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
425471d10453SEric Joyner {
425571d10453SEric Joyner 	int f;
425671d10453SEric Joyner 
425771d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
425871d10453SEric Joyner 		switch (ce_info[f].size_of) {
425971d10453SEric Joyner 		case 1:
426071d10453SEric Joyner 			ice_read_byte(src_ctx, dest_ctx, &ce_info[f]);
426171d10453SEric Joyner 			break;
426271d10453SEric Joyner 		case 2:
426371d10453SEric Joyner 			ice_read_word(src_ctx, dest_ctx, &ce_info[f]);
426471d10453SEric Joyner 			break;
426571d10453SEric Joyner 		case 4:
426671d10453SEric Joyner 			ice_read_dword(src_ctx, dest_ctx, &ce_info[f]);
426771d10453SEric Joyner 			break;
426871d10453SEric Joyner 		case 8:
426971d10453SEric Joyner 			ice_read_qword(src_ctx, dest_ctx, &ce_info[f]);
427071d10453SEric Joyner 			break;
427171d10453SEric Joyner 		default:
427271d10453SEric Joyner 			/* nothing to do, just keep going */
427371d10453SEric Joyner 			break;
427471d10453SEric Joyner 		}
427571d10453SEric Joyner 	}
427671d10453SEric Joyner 
427771d10453SEric Joyner 	return ICE_SUCCESS;
427871d10453SEric Joyner }
427971d10453SEric Joyner 
428071d10453SEric Joyner /**
428171d10453SEric Joyner  * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
428271d10453SEric Joyner  * @hw: pointer to the HW struct
428371d10453SEric Joyner  * @vsi_handle: software VSI handle
428471d10453SEric Joyner  * @tc: TC number
428571d10453SEric Joyner  * @q_handle: software queue handle
428671d10453SEric Joyner  */
428771d10453SEric Joyner struct ice_q_ctx *
428871d10453SEric Joyner ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
428971d10453SEric Joyner {
429071d10453SEric Joyner 	struct ice_vsi_ctx *vsi;
429171d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
429271d10453SEric Joyner 
429371d10453SEric Joyner 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
429471d10453SEric Joyner 	if (!vsi)
429571d10453SEric Joyner 		return NULL;
429671d10453SEric Joyner 	if (q_handle >= vsi->num_lan_q_entries[tc])
429771d10453SEric Joyner 		return NULL;
429871d10453SEric Joyner 	if (!vsi->lan_q_ctx[tc])
429971d10453SEric Joyner 		return NULL;
430071d10453SEric Joyner 	q_ctx = vsi->lan_q_ctx[tc];
430171d10453SEric Joyner 	return &q_ctx[q_handle];
430271d10453SEric Joyner }
430371d10453SEric Joyner 
430471d10453SEric Joyner /**
430571d10453SEric Joyner  * ice_ena_vsi_txq
430671d10453SEric Joyner  * @pi: port information structure
430771d10453SEric Joyner  * @vsi_handle: software VSI handle
430871d10453SEric Joyner  * @tc: TC number
430971d10453SEric Joyner  * @q_handle: software queue handle
431071d10453SEric Joyner  * @num_qgrps: Number of added queue groups
431171d10453SEric Joyner  * @buf: list of queue groups to be added
431271d10453SEric Joyner  * @buf_size: size of buffer for indirect command
431371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
431471d10453SEric Joyner  *
431571d10453SEric Joyner  * This function adds one LAN queue
431671d10453SEric Joyner  */
431771d10453SEric Joyner enum ice_status
431871d10453SEric Joyner ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
431971d10453SEric Joyner 		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
432071d10453SEric Joyner 		struct ice_sq_cd *cd)
432171d10453SEric Joyner {
432271d10453SEric Joyner 	struct ice_aqc_txsched_elem_data node = { 0 };
432371d10453SEric Joyner 	struct ice_sched_node *parent;
432471d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
432571d10453SEric Joyner 	enum ice_status status;
432671d10453SEric Joyner 	struct ice_hw *hw;
432771d10453SEric Joyner 
432871d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
432971d10453SEric Joyner 		return ICE_ERR_CFG;
433071d10453SEric Joyner 
433171d10453SEric Joyner 	if (num_qgrps > 1 || buf->num_txqs > 1)
433271d10453SEric Joyner 		return ICE_ERR_MAX_LIMIT;
433371d10453SEric Joyner 
433471d10453SEric Joyner 	hw = pi->hw;
433571d10453SEric Joyner 
433671d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
433771d10453SEric Joyner 		return ICE_ERR_PARAM;
433871d10453SEric Joyner 
433971d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
434071d10453SEric Joyner 
434171d10453SEric Joyner 	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
434271d10453SEric Joyner 	if (!q_ctx) {
434371d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
434471d10453SEric Joyner 			  q_handle);
434571d10453SEric Joyner 		status = ICE_ERR_PARAM;
434671d10453SEric Joyner 		goto ena_txq_exit;
434771d10453SEric Joyner 	}
434871d10453SEric Joyner 
434971d10453SEric Joyner 	/* find a parent node */
435071d10453SEric Joyner 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
435171d10453SEric Joyner 					    ICE_SCHED_NODE_OWNER_LAN);
435271d10453SEric Joyner 	if (!parent) {
435371d10453SEric Joyner 		status = ICE_ERR_PARAM;
435471d10453SEric Joyner 		goto ena_txq_exit;
435571d10453SEric Joyner 	}
435671d10453SEric Joyner 
435771d10453SEric Joyner 	buf->parent_teid = parent->info.node_teid;
435871d10453SEric Joyner 	node.parent_teid = parent->info.node_teid;
435971d10453SEric Joyner 	/* Mark that the values in the "generic" section as valid. The default
436071d10453SEric Joyner 	 * value in the "generic" section is zero. This means that :
436171d10453SEric Joyner 	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
436271d10453SEric Joyner 	 * - 0 priority among siblings, indicated by Bit 1-3.
436371d10453SEric Joyner 	 * - WFQ, indicated by Bit 4.
436471d10453SEric Joyner 	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
436571d10453SEric Joyner 	 * Bit 5-6.
436671d10453SEric Joyner 	 * - Bit 7 is reserved.
436771d10453SEric Joyner 	 * Without setting the generic section as valid in valid_sections, the
436871d10453SEric Joyner 	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
436971d10453SEric Joyner 	 */
4370*7d7af7f8SEric Joyner 	buf->txqs[0].info.valid_sections =
4371*7d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
4372*7d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_EIR;
4373*7d7af7f8SEric Joyner 	buf->txqs[0].info.generic = 0;
4374*7d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_profile_idx =
4375*7d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
4376*7d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_alloc =
4377*7d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
4378*7d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_profile_idx =
4379*7d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
4380*7d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_alloc =
4381*7d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
438271d10453SEric Joyner 
438371d10453SEric Joyner 	/* add the LAN queue */
438471d10453SEric Joyner 	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
438571d10453SEric Joyner 	if (status != ICE_SUCCESS) {
438671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
438771d10453SEric Joyner 			  LE16_TO_CPU(buf->txqs[0].txq_id),
438871d10453SEric Joyner 			  hw->adminq.sq_last_status);
438971d10453SEric Joyner 		goto ena_txq_exit;
439071d10453SEric Joyner 	}
439171d10453SEric Joyner 
439271d10453SEric Joyner 	node.node_teid = buf->txqs[0].q_teid;
439371d10453SEric Joyner 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
439471d10453SEric Joyner 	q_ctx->q_handle = q_handle;
439571d10453SEric Joyner 	q_ctx->q_teid = LE32_TO_CPU(node.node_teid);
439671d10453SEric Joyner 
439771d10453SEric Joyner 	/* add a leaf node into scheduler tree queue layer */
439871d10453SEric Joyner 	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node);
439971d10453SEric Joyner 	if (!status)
440071d10453SEric Joyner 		status = ice_sched_replay_q_bw(pi, q_ctx);
440171d10453SEric Joyner 
440271d10453SEric Joyner ena_txq_exit:
440371d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
440471d10453SEric Joyner 	return status;
440571d10453SEric Joyner }
440671d10453SEric Joyner 
440771d10453SEric Joyner /**
440871d10453SEric Joyner  * ice_dis_vsi_txq
440971d10453SEric Joyner  * @pi: port information structure
441071d10453SEric Joyner  * @vsi_handle: software VSI handle
441171d10453SEric Joyner  * @tc: TC number
441271d10453SEric Joyner  * @num_queues: number of queues
441371d10453SEric Joyner  * @q_handles: pointer to software queue handle array
441471d10453SEric Joyner  * @q_ids: pointer to the q_id array
441571d10453SEric Joyner  * @q_teids: pointer to queue node teids
441671d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
441771d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
441871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
441971d10453SEric Joyner  *
442071d10453SEric Joyner  * This function removes queues and their corresponding nodes in SW DB
442171d10453SEric Joyner  */
442271d10453SEric Joyner enum ice_status
442371d10453SEric Joyner ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
442471d10453SEric Joyner 		u16 *q_handles, u16 *q_ids, u32 *q_teids,
442571d10453SEric Joyner 		enum ice_disq_rst_src rst_src, u16 vmvf_num,
442671d10453SEric Joyner 		struct ice_sq_cd *cd)
442771d10453SEric Joyner {
442871d10453SEric Joyner 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
4429*7d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *qg_list;
443071d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
4431*7d7af7f8SEric Joyner 	struct ice_hw *hw;
4432*7d7af7f8SEric Joyner 	u16 i, buf_size;
443371d10453SEric Joyner 
443471d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
443571d10453SEric Joyner 		return ICE_ERR_CFG;
443671d10453SEric Joyner 
4437*7d7af7f8SEric Joyner 	hw = pi->hw;
4438*7d7af7f8SEric Joyner 
443971d10453SEric Joyner 	if (!num_queues) {
444071d10453SEric Joyner 		/* if queue is disabled already yet the disable queue command
444171d10453SEric Joyner 		 * has to be sent to complete the VF reset, then call
444271d10453SEric Joyner 		 * ice_aq_dis_lan_txq without any queue information
444371d10453SEric Joyner 		 */
444471d10453SEric Joyner 		if (rst_src)
4445*7d7af7f8SEric Joyner 			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
444671d10453SEric Joyner 						  vmvf_num, NULL);
444771d10453SEric Joyner 		return ICE_ERR_CFG;
444871d10453SEric Joyner 	}
444971d10453SEric Joyner 
4450*7d7af7f8SEric Joyner 	buf_size = ice_struct_size(qg_list, q_id, 1);
4451*7d7af7f8SEric Joyner 	qg_list = (struct ice_aqc_dis_txq_item *)ice_malloc(hw, buf_size);
4452*7d7af7f8SEric Joyner 	if (!qg_list)
4453*7d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
4454*7d7af7f8SEric Joyner 
445571d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
445671d10453SEric Joyner 
445771d10453SEric Joyner 	for (i = 0; i < num_queues; i++) {
445871d10453SEric Joyner 		struct ice_sched_node *node;
445971d10453SEric Joyner 
446071d10453SEric Joyner 		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
446171d10453SEric Joyner 		if (!node)
446271d10453SEric Joyner 			continue;
4463*7d7af7f8SEric Joyner 		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
446471d10453SEric Joyner 		if (!q_ctx) {
4465*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
446671d10453SEric Joyner 				  q_handles[i]);
446771d10453SEric Joyner 			continue;
446871d10453SEric Joyner 		}
446971d10453SEric Joyner 		if (q_ctx->q_handle != q_handles[i]) {
4470*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
447171d10453SEric Joyner 				  q_ctx->q_handle, q_handles[i]);
447271d10453SEric Joyner 			continue;
447371d10453SEric Joyner 		}
4474*7d7af7f8SEric Joyner 		qg_list->parent_teid = node->info.parent_teid;
4475*7d7af7f8SEric Joyner 		qg_list->num_qs = 1;
4476*7d7af7f8SEric Joyner 		qg_list->q_id[0] = CPU_TO_LE16(q_ids[i]);
4477*7d7af7f8SEric Joyner 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
4478*7d7af7f8SEric Joyner 					    vmvf_num, cd);
447971d10453SEric Joyner 
448071d10453SEric Joyner 		if (status != ICE_SUCCESS)
448171d10453SEric Joyner 			break;
448271d10453SEric Joyner 		ice_free_sched_node(pi, node);
448371d10453SEric Joyner 		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
448471d10453SEric Joyner 	}
448571d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
4486*7d7af7f8SEric Joyner 	ice_free(hw, qg_list);
448771d10453SEric Joyner 	return status;
448871d10453SEric Joyner }
448971d10453SEric Joyner 
449071d10453SEric Joyner /**
449171d10453SEric Joyner  * ice_cfg_vsi_qs - configure the new/existing VSI queues
449271d10453SEric Joyner  * @pi: port information structure
449371d10453SEric Joyner  * @vsi_handle: software VSI handle
449471d10453SEric Joyner  * @tc_bitmap: TC bitmap
449571d10453SEric Joyner  * @maxqs: max queues array per TC
449671d10453SEric Joyner  * @owner: LAN or RDMA
449771d10453SEric Joyner  *
449871d10453SEric Joyner  * This function adds/updates the VSI queues per TC.
449971d10453SEric Joyner  */
450071d10453SEric Joyner static enum ice_status
450171d10453SEric Joyner ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
450271d10453SEric Joyner 	       u16 *maxqs, u8 owner)
450371d10453SEric Joyner {
450471d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
450571d10453SEric Joyner 	u8 i;
450671d10453SEric Joyner 
450771d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
450871d10453SEric Joyner 		return ICE_ERR_CFG;
450971d10453SEric Joyner 
451071d10453SEric Joyner 	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
451171d10453SEric Joyner 		return ICE_ERR_PARAM;
451271d10453SEric Joyner 
451371d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
451471d10453SEric Joyner 
451571d10453SEric Joyner 	ice_for_each_traffic_class(i) {
451671d10453SEric Joyner 		/* configuration is possible only if TC node is present */
451771d10453SEric Joyner 		if (!ice_sched_get_tc_node(pi, i))
451871d10453SEric Joyner 			continue;
451971d10453SEric Joyner 
452071d10453SEric Joyner 		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
452171d10453SEric Joyner 					   ice_is_tc_ena(tc_bitmap, i));
452271d10453SEric Joyner 		if (status)
452371d10453SEric Joyner 			break;
452471d10453SEric Joyner 	}
452571d10453SEric Joyner 
452671d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
452771d10453SEric Joyner 	return status;
452871d10453SEric Joyner }
452971d10453SEric Joyner 
453071d10453SEric Joyner /**
453171d10453SEric Joyner  * ice_cfg_vsi_lan - configure VSI LAN queues
453271d10453SEric Joyner  * @pi: port information structure
453371d10453SEric Joyner  * @vsi_handle: software VSI handle
453471d10453SEric Joyner  * @tc_bitmap: TC bitmap
453571d10453SEric Joyner  * @max_lanqs: max LAN queues array per TC
453671d10453SEric Joyner  *
453771d10453SEric Joyner  * This function adds/updates the VSI LAN queues per TC.
453871d10453SEric Joyner  */
453971d10453SEric Joyner enum ice_status
454071d10453SEric Joyner ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
454171d10453SEric Joyner 		u16 *max_lanqs)
454271d10453SEric Joyner {
454371d10453SEric Joyner 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
454471d10453SEric Joyner 			      ICE_SCHED_NODE_OWNER_LAN);
454571d10453SEric Joyner }
454671d10453SEric Joyner 
454771d10453SEric Joyner /**
4548*7d7af7f8SEric Joyner  * ice_is_main_vsi - checks whether the VSI is main VSI
4549*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
4550*7d7af7f8SEric Joyner  * @vsi_handle: VSI handle
4551*7d7af7f8SEric Joyner  *
4552*7d7af7f8SEric Joyner  * Checks whether the VSI is the main VSI (the first PF VSI created on
4553*7d7af7f8SEric Joyner  * given PF).
4554*7d7af7f8SEric Joyner  */
4555*7d7af7f8SEric Joyner static bool ice_is_main_vsi(struct ice_hw *hw, u16 vsi_handle)
4556*7d7af7f8SEric Joyner {
4557*7d7af7f8SEric Joyner 	return vsi_handle == ICE_MAIN_VSI_HANDLE && hw->vsi_ctx[vsi_handle];
4558*7d7af7f8SEric Joyner }
4559*7d7af7f8SEric Joyner 
4560*7d7af7f8SEric Joyner /**
456171d10453SEric Joyner  * ice_replay_pre_init - replay pre initialization
456271d10453SEric Joyner  * @hw: pointer to the HW struct
4563*7d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function initializes filters
456471d10453SEric Joyner  *
456571d10453SEric Joyner  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
456671d10453SEric Joyner  */
4567*7d7af7f8SEric Joyner static enum ice_status
4568*7d7af7f8SEric Joyner ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
456971d10453SEric Joyner {
4570*7d7af7f8SEric Joyner 	enum ice_status status;
457171d10453SEric Joyner 	u8 i;
457271d10453SEric Joyner 
457371d10453SEric Joyner 	/* Delete old entries from replay filter list head if there is any */
4574*7d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
457571d10453SEric Joyner 	/* In start of replay, move entries into replay_rules list, it
457671d10453SEric Joyner 	 * will allow adding rules entries back to filt_rules list,
457771d10453SEric Joyner 	 * which is operational list.
457871d10453SEric Joyner 	 */
457971d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++)
458071d10453SEric Joyner 		LIST_REPLACE_INIT(&sw->recp_list[i].filt_rules,
458171d10453SEric Joyner 				  &sw->recp_list[i].filt_replay_rules);
458271d10453SEric Joyner 	ice_sched_replay_agg_vsi_preinit(hw);
458371d10453SEric Joyner 
4584*7d7af7f8SEric Joyner 	status = ice_sched_replay_root_node_bw(hw->port_info);
4585*7d7af7f8SEric Joyner 	if (status)
4586*7d7af7f8SEric Joyner 		return status;
4587*7d7af7f8SEric Joyner 
458871d10453SEric Joyner 	return ice_sched_replay_tc_node_bw(hw->port_info);
458971d10453SEric Joyner }
459071d10453SEric Joyner 
459171d10453SEric Joyner /**
459271d10453SEric Joyner  * ice_replay_vsi - replay VSI configuration
459371d10453SEric Joyner  * @hw: pointer to the HW struct
459471d10453SEric Joyner  * @vsi_handle: driver VSI handle
459571d10453SEric Joyner  *
459671d10453SEric Joyner  * Restore all VSI configuration after reset. It is required to call this
459771d10453SEric Joyner  * function with main VSI first.
459871d10453SEric Joyner  */
459971d10453SEric Joyner enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
460071d10453SEric Joyner {
4601*7d7af7f8SEric Joyner 	struct ice_switch_info *sw = hw->switch_info;
4602*7d7af7f8SEric Joyner 	struct ice_port_info *pi = hw->port_info;
460371d10453SEric Joyner 	enum ice_status status;
460471d10453SEric Joyner 
460571d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
460671d10453SEric Joyner 		return ICE_ERR_PARAM;
460771d10453SEric Joyner 
460871d10453SEric Joyner 	/* Replay pre-initialization if there is any */
4609*7d7af7f8SEric Joyner 	if (ice_is_main_vsi(hw, vsi_handle)) {
4610*7d7af7f8SEric Joyner 		status = ice_replay_pre_init(hw, sw);
461171d10453SEric Joyner 		if (status)
461271d10453SEric Joyner 			return status;
461371d10453SEric Joyner 	}
461471d10453SEric Joyner 	/* Replay per VSI all RSS configurations */
461571d10453SEric Joyner 	status = ice_replay_rss_cfg(hw, vsi_handle);
461671d10453SEric Joyner 	if (status)
461771d10453SEric Joyner 		return status;
461871d10453SEric Joyner 	/* Replay per VSI all filters */
4619*7d7af7f8SEric Joyner 	status = ice_replay_vsi_all_fltr(hw, pi, vsi_handle);
462071d10453SEric Joyner 	if (!status)
462171d10453SEric Joyner 		status = ice_replay_vsi_agg(hw, vsi_handle);
462271d10453SEric Joyner 	return status;
462371d10453SEric Joyner }
462471d10453SEric Joyner 
462571d10453SEric Joyner /**
462671d10453SEric Joyner  * ice_replay_post - post replay configuration cleanup
462771d10453SEric Joyner  * @hw: pointer to the HW struct
462871d10453SEric Joyner  *
462971d10453SEric Joyner  * Post replay cleanup.
463071d10453SEric Joyner  */
463171d10453SEric Joyner void ice_replay_post(struct ice_hw *hw)
463271d10453SEric Joyner {
463371d10453SEric Joyner 	/* Delete old entries from replay filter list head */
463471d10453SEric Joyner 	ice_rm_all_sw_replay_rule_info(hw);
463571d10453SEric Joyner 	ice_sched_replay_agg(hw);
463671d10453SEric Joyner }
463771d10453SEric Joyner 
463871d10453SEric Joyner /**
463971d10453SEric Joyner  * ice_stat_update40 - read 40 bit stat from the chip and update stat values
464071d10453SEric Joyner  * @hw: ptr to the hardware info
464171d10453SEric Joyner  * @reg: offset of 64 bit HW register to read from
464271d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
464371d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
464471d10453SEric Joyner  * @cur_stat: ptr to current stat value
464571d10453SEric Joyner  */
464671d10453SEric Joyner void
464771d10453SEric Joyner ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
464871d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
464971d10453SEric Joyner {
465071d10453SEric Joyner 	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
465171d10453SEric Joyner 
465271d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
465371d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
465471d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
465571d10453SEric Joyner 	 * count up from zero.
465671d10453SEric Joyner 	 */
465771d10453SEric Joyner 	if (!prev_stat_loaded) {
465871d10453SEric Joyner 		*prev_stat = new_data;
465971d10453SEric Joyner 		return;
466071d10453SEric Joyner 	}
466171d10453SEric Joyner 
466271d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
466371d10453SEric Joyner 	 * add it to the software stat value.
466471d10453SEric Joyner 	 */
466571d10453SEric Joyner 	if (new_data >= *prev_stat)
466671d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
466771d10453SEric Joyner 	else
466871d10453SEric Joyner 		/* to manage the potential roll-over */
466971d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
467071d10453SEric Joyner 
467171d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
467271d10453SEric Joyner 	*prev_stat = new_data;
467371d10453SEric Joyner }
467471d10453SEric Joyner 
467571d10453SEric Joyner /**
467671d10453SEric Joyner  * ice_stat_update32 - read 32 bit stat from the chip and update stat values
467771d10453SEric Joyner  * @hw: ptr to the hardware info
467871d10453SEric Joyner  * @reg: offset of HW register to read from
467971d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
468071d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
468171d10453SEric Joyner  * @cur_stat: ptr to current stat value
468271d10453SEric Joyner  */
468371d10453SEric Joyner void
468471d10453SEric Joyner ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
468571d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
468671d10453SEric Joyner {
468771d10453SEric Joyner 	u32 new_data;
468871d10453SEric Joyner 
468971d10453SEric Joyner 	new_data = rd32(hw, reg);
469071d10453SEric Joyner 
469171d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
469271d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
469371d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
469471d10453SEric Joyner 	 * count up from zero.
469571d10453SEric Joyner 	 */
469671d10453SEric Joyner 	if (!prev_stat_loaded) {
469771d10453SEric Joyner 		*prev_stat = new_data;
469871d10453SEric Joyner 		return;
469971d10453SEric Joyner 	}
470071d10453SEric Joyner 
470171d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
470271d10453SEric Joyner 	 * add it to the software stat value.
470371d10453SEric Joyner 	 */
470471d10453SEric Joyner 	if (new_data >= *prev_stat)
470571d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
470671d10453SEric Joyner 	else
470771d10453SEric Joyner 		/* to manage the potential roll-over */
470871d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
470971d10453SEric Joyner 
471071d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
471171d10453SEric Joyner 	*prev_stat = new_data;
471271d10453SEric Joyner }
471371d10453SEric Joyner 
471471d10453SEric Joyner /**
471571d10453SEric Joyner  * ice_stat_update_repc - read GLV_REPC stats from chip and update stat values
471671d10453SEric Joyner  * @hw: ptr to the hardware info
471771d10453SEric Joyner  * @vsi_handle: VSI handle
471871d10453SEric Joyner  * @prev_stat_loaded: bool to specify if the previous stat values are loaded
471971d10453SEric Joyner  * @cur_stats: ptr to current stats structure
472071d10453SEric Joyner  *
472171d10453SEric Joyner  * The GLV_REPC statistic register actually tracks two 16bit statistics, and
472271d10453SEric Joyner  * thus cannot be read using the normal ice_stat_update32 function.
472371d10453SEric Joyner  *
472471d10453SEric Joyner  * Read the GLV_REPC register associated with the given VSI, and update the
472571d10453SEric Joyner  * rx_no_desc and rx_error values in the ice_eth_stats structure.
472671d10453SEric Joyner  *
472771d10453SEric Joyner  * Because the statistics in GLV_REPC stick at 0xFFFF, the register must be
472871d10453SEric Joyner  * cleared each time it's read.
472971d10453SEric Joyner  *
473071d10453SEric Joyner  * Note that the GLV_RDPC register also counts the causes that would trigger
473171d10453SEric Joyner  * GLV_REPC. However, it does not give the finer grained detail about why the
473271d10453SEric Joyner  * packets are being dropped. The GLV_REPC values can be used to distinguish
473371d10453SEric Joyner  * whether Rx packets are dropped due to errors or due to no available
473471d10453SEric Joyner  * descriptors.
473571d10453SEric Joyner  */
473671d10453SEric Joyner void
473771d10453SEric Joyner ice_stat_update_repc(struct ice_hw *hw, u16 vsi_handle, bool prev_stat_loaded,
473871d10453SEric Joyner 		     struct ice_eth_stats *cur_stats)
473971d10453SEric Joyner {
474071d10453SEric Joyner 	u16 vsi_num, no_desc, error_cnt;
474171d10453SEric Joyner 	u32 repc;
474271d10453SEric Joyner 
474371d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
474471d10453SEric Joyner 		return;
474571d10453SEric Joyner 
474671d10453SEric Joyner 	vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
474771d10453SEric Joyner 
474871d10453SEric Joyner 	/* If we haven't loaded stats yet, just clear the current value */
474971d10453SEric Joyner 	if (!prev_stat_loaded) {
475071d10453SEric Joyner 		wr32(hw, GLV_REPC(vsi_num), 0);
475171d10453SEric Joyner 		return;
475271d10453SEric Joyner 	}
475371d10453SEric Joyner 
475471d10453SEric Joyner 	repc = rd32(hw, GLV_REPC(vsi_num));
475571d10453SEric Joyner 	no_desc = (repc & GLV_REPC_NO_DESC_CNT_M) >> GLV_REPC_NO_DESC_CNT_S;
475671d10453SEric Joyner 	error_cnt = (repc & GLV_REPC_ERROR_CNT_M) >> GLV_REPC_ERROR_CNT_S;
475771d10453SEric Joyner 
475871d10453SEric Joyner 	/* Clear the count by writing to the stats register */
475971d10453SEric Joyner 	wr32(hw, GLV_REPC(vsi_num), 0);
476071d10453SEric Joyner 
476171d10453SEric Joyner 	cur_stats->rx_no_desc += no_desc;
476271d10453SEric Joyner 	cur_stats->rx_errors += error_cnt;
476371d10453SEric Joyner }
476471d10453SEric Joyner 
476571d10453SEric Joyner /**
476671d10453SEric Joyner  * ice_aq_alternate_write
476771d10453SEric Joyner  * @hw: pointer to the hardware structure
476871d10453SEric Joyner  * @reg_addr0: address of first dword to be written
476971d10453SEric Joyner  * @reg_val0: value to be written under 'reg_addr0'
477071d10453SEric Joyner  * @reg_addr1: address of second dword to be written
477171d10453SEric Joyner  * @reg_val1: value to be written under 'reg_addr1'
477271d10453SEric Joyner  *
477371d10453SEric Joyner  * Write one or two dwords to alternate structure. Fields are indicated
477471d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers.
477571d10453SEric Joyner  */
477671d10453SEric Joyner enum ice_status
477771d10453SEric Joyner ice_aq_alternate_write(struct ice_hw *hw, u32 reg_addr0, u32 reg_val0,
477871d10453SEric Joyner 		       u32 reg_addr1, u32 reg_val1)
477971d10453SEric Joyner {
478071d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
478171d10453SEric Joyner 	struct ice_aq_desc desc;
478271d10453SEric Joyner 	enum ice_status status;
478371d10453SEric Joyner 
478471d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
478571d10453SEric Joyner 
478671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_alt_direct);
478771d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
478871d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
478971d10453SEric Joyner 	cmd->dword0_value = CPU_TO_LE32(reg_val0);
479071d10453SEric Joyner 	cmd->dword1_value = CPU_TO_LE32(reg_val1);
479171d10453SEric Joyner 
479271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
479371d10453SEric Joyner 
479471d10453SEric Joyner 	return status;
479571d10453SEric Joyner }
479671d10453SEric Joyner 
479771d10453SEric Joyner /**
479871d10453SEric Joyner  * ice_aq_alternate_read
479971d10453SEric Joyner  * @hw: pointer to the hardware structure
480071d10453SEric Joyner  * @reg_addr0: address of first dword to be read
480171d10453SEric Joyner  * @reg_val0: pointer for data read from 'reg_addr0'
480271d10453SEric Joyner  * @reg_addr1: address of second dword to be read
480371d10453SEric Joyner  * @reg_val1: pointer for data read from 'reg_addr1'
480471d10453SEric Joyner  *
480571d10453SEric Joyner  * Read one or two dwords from alternate structure. Fields are indicated
480671d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer
480771d10453SEric Joyner  * is not passed then only register at 'reg_addr0' is read.
480871d10453SEric Joyner  */
480971d10453SEric Joyner enum ice_status
481071d10453SEric Joyner ice_aq_alternate_read(struct ice_hw *hw, u32 reg_addr0, u32 *reg_val0,
481171d10453SEric Joyner 		      u32 reg_addr1, u32 *reg_val1)
481271d10453SEric Joyner {
481371d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
481471d10453SEric Joyner 	struct ice_aq_desc desc;
481571d10453SEric Joyner 	enum ice_status status;
481671d10453SEric Joyner 
481771d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
481871d10453SEric Joyner 
481971d10453SEric Joyner 	if (!reg_val0)
482071d10453SEric Joyner 		return ICE_ERR_PARAM;
482171d10453SEric Joyner 
482271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_alt_direct);
482371d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
482471d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
482571d10453SEric Joyner 
482671d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
482771d10453SEric Joyner 
482871d10453SEric Joyner 	if (status == ICE_SUCCESS) {
482971d10453SEric Joyner 		*reg_val0 = LE32_TO_CPU(cmd->dword0_value);
483071d10453SEric Joyner 
483171d10453SEric Joyner 		if (reg_val1)
483271d10453SEric Joyner 			*reg_val1 = LE32_TO_CPU(cmd->dword1_value);
483371d10453SEric Joyner 	}
483471d10453SEric Joyner 
483571d10453SEric Joyner 	return status;
483671d10453SEric Joyner }
483771d10453SEric Joyner 
483871d10453SEric Joyner /**
483971d10453SEric Joyner  *  ice_aq_alternate_write_done
484071d10453SEric Joyner  *  @hw: pointer to the HW structure.
484171d10453SEric Joyner  *  @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS
484271d10453SEric Joyner  *  @reset_needed: indicates the SW should trigger GLOBAL reset
484371d10453SEric Joyner  *
484471d10453SEric Joyner  *  Indicates to the FW that alternate structures have been changed.
484571d10453SEric Joyner  */
484671d10453SEric Joyner enum ice_status
484771d10453SEric Joyner ice_aq_alternate_write_done(struct ice_hw *hw, u8 bios_mode, bool *reset_needed)
484871d10453SEric Joyner {
484971d10453SEric Joyner 	struct ice_aqc_done_alt_write *cmd;
485071d10453SEric Joyner 	struct ice_aq_desc desc;
485171d10453SEric Joyner 	enum ice_status status;
485271d10453SEric Joyner 
485371d10453SEric Joyner 	cmd = &desc.params.done_alt_write;
485471d10453SEric Joyner 
485571d10453SEric Joyner 	if (!reset_needed)
485671d10453SEric Joyner 		return ICE_ERR_PARAM;
485771d10453SEric Joyner 
485871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_done_alt_write);
485971d10453SEric Joyner 	cmd->flags = bios_mode;
486071d10453SEric Joyner 
486171d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
486271d10453SEric Joyner 	if (!status)
486371d10453SEric Joyner 		*reset_needed = (LE16_TO_CPU(cmd->flags) &
486471d10453SEric Joyner 				 ICE_AQC_RESP_RESET_NEEDED) != 0;
486571d10453SEric Joyner 
486671d10453SEric Joyner 	return status;
486771d10453SEric Joyner }
486871d10453SEric Joyner 
486971d10453SEric Joyner /**
487071d10453SEric Joyner  *  ice_aq_alternate_clear
487171d10453SEric Joyner  *  @hw: pointer to the HW structure.
487271d10453SEric Joyner  *
487371d10453SEric Joyner  *  Clear the alternate structures of the port from which the function
487471d10453SEric Joyner  *  is called.
487571d10453SEric Joyner  */
487671d10453SEric Joyner enum ice_status ice_aq_alternate_clear(struct ice_hw *hw)
487771d10453SEric Joyner {
487871d10453SEric Joyner 	struct ice_aq_desc desc;
487971d10453SEric Joyner 	enum ice_status status;
488071d10453SEric Joyner 
488171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_port_alt_write);
488271d10453SEric Joyner 
488371d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
488471d10453SEric Joyner 
488571d10453SEric Joyner 	return status;
488671d10453SEric Joyner }
488771d10453SEric Joyner 
488871d10453SEric Joyner /**
488971d10453SEric Joyner  * ice_sched_query_elem - query element information from HW
489071d10453SEric Joyner  * @hw: pointer to the HW struct
489171d10453SEric Joyner  * @node_teid: node TEID to be queried
489271d10453SEric Joyner  * @buf: buffer to element information
489371d10453SEric Joyner  *
489471d10453SEric Joyner  * This function queries HW element information
489571d10453SEric Joyner  */
489671d10453SEric Joyner enum ice_status
489771d10453SEric Joyner ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
4898*7d7af7f8SEric Joyner 		     struct ice_aqc_txsched_elem_data *buf)
489971d10453SEric Joyner {
490071d10453SEric Joyner 	u16 buf_size, num_elem_ret = 0;
490171d10453SEric Joyner 	enum ice_status status;
490271d10453SEric Joyner 
490371d10453SEric Joyner 	buf_size = sizeof(*buf);
490471d10453SEric Joyner 	ice_memset(buf, 0, buf_size, ICE_NONDMA_MEM);
4905*7d7af7f8SEric Joyner 	buf->node_teid = CPU_TO_LE32(node_teid);
490671d10453SEric Joyner 	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
490771d10453SEric Joyner 					  NULL);
490871d10453SEric Joyner 	if (status != ICE_SUCCESS || num_elem_ret != 1)
490971d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
491071d10453SEric Joyner 	return status;
491171d10453SEric Joyner }
491271d10453SEric Joyner 
491371d10453SEric Joyner /**
491471d10453SEric Joyner  * ice_get_fw_mode - returns FW mode
491571d10453SEric Joyner  * @hw: pointer to the HW struct
491671d10453SEric Joyner  */
491771d10453SEric Joyner enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
491871d10453SEric Joyner {
491971d10453SEric Joyner #define ICE_FW_MODE_DBG_M BIT(0)
492071d10453SEric Joyner #define ICE_FW_MODE_REC_M BIT(1)
492171d10453SEric Joyner #define ICE_FW_MODE_ROLLBACK_M BIT(2)
492271d10453SEric Joyner 	u32 fw_mode;
492371d10453SEric Joyner 
492471d10453SEric Joyner 	/* check the current FW mode */
492571d10453SEric Joyner 	fw_mode = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_MODES_M;
492671d10453SEric Joyner 
492771d10453SEric Joyner 	if (fw_mode & ICE_FW_MODE_DBG_M)
492871d10453SEric Joyner 		return ICE_FW_MODE_DBG;
492971d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_REC_M)
493071d10453SEric Joyner 		return ICE_FW_MODE_REC;
493171d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_ROLLBACK_M)
493271d10453SEric Joyner 		return ICE_FW_MODE_ROLLBACK;
493371d10453SEric Joyner 	else
493471d10453SEric Joyner 		return ICE_FW_MODE_NORMAL;
493571d10453SEric Joyner }
493671d10453SEric Joyner 
493771d10453SEric Joyner /**
493871d10453SEric Joyner  * ice_cfg_get_cur_lldp_persist_status
493971d10453SEric Joyner  * @hw: pointer to the HW struct
494071d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
494171d10453SEric Joyner  *
494271d10453SEric Joyner  * Get the current status of LLDP persistent
494371d10453SEric Joyner  */
494471d10453SEric Joyner enum ice_status
494571d10453SEric Joyner ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
494671d10453SEric Joyner {
494771d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
494871d10453SEric Joyner 	enum ice_status ret;
494971d10453SEric Joyner 	__le32 raw_data;
495071d10453SEric Joyner 	u32 data, mask;
495171d10453SEric Joyner 
495271d10453SEric Joyner 	if (!lldp_status)
495371d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
495471d10453SEric Joyner 
495571d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
495671d10453SEric Joyner 	if (ret)
495771d10453SEric Joyner 		return ret;
495871d10453SEric Joyner 
495971d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LLDP_PRESERVED_MOD_ID,
496071d10453SEric Joyner 			      ICE_AQC_NVM_CUR_LLDP_PERSIST_RD_OFFSET,
496171d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data,
496271d10453SEric Joyner 			      false, true, NULL);
496371d10453SEric Joyner 	if (!ret) {
496471d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
496571d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
496671d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
496771d10453SEric Joyner 		data = data & mask;
496871d10453SEric Joyner 		*lldp_status = data >>
496971d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
497071d10453SEric Joyner 	}
497171d10453SEric Joyner 
497271d10453SEric Joyner 	ice_release_nvm(hw);
497371d10453SEric Joyner 
497471d10453SEric Joyner 	return ret;
497571d10453SEric Joyner }
497671d10453SEric Joyner 
497771d10453SEric Joyner /**
497871d10453SEric Joyner  * ice_get_dflt_lldp_persist_status
497971d10453SEric Joyner  * @hw: pointer to the HW struct
498071d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
498171d10453SEric Joyner  *
498271d10453SEric Joyner  * Get the default status of LLDP persistent
498371d10453SEric Joyner  */
498471d10453SEric Joyner enum ice_status
498571d10453SEric Joyner ice_get_dflt_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
498671d10453SEric Joyner {
498771d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
498871d10453SEric Joyner 	u32 data, mask, loc_data, loc_data_tmp;
498971d10453SEric Joyner 	enum ice_status ret;
499071d10453SEric Joyner 	__le16 loc_raw_data;
499171d10453SEric Joyner 	__le32 raw_data;
499271d10453SEric Joyner 
499371d10453SEric Joyner 	if (!lldp_status)
499471d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
499571d10453SEric Joyner 
499671d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
499771d10453SEric Joyner 	if (ret)
499871d10453SEric Joyner 		return ret;
499971d10453SEric Joyner 
500071d10453SEric Joyner 	/* Read the offset of EMP_SR_PTR */
500171d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT,
500271d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_OFFSET,
500371d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_RD_LEN,
500471d10453SEric Joyner 			      &loc_raw_data, false, true, NULL);
500571d10453SEric Joyner 	if (ret)
500671d10453SEric Joyner 		goto exit;
500771d10453SEric Joyner 
500871d10453SEric Joyner 	loc_data = LE16_TO_CPU(loc_raw_data);
500971d10453SEric Joyner 	if (loc_data & ICE_AQC_NVM_EMP_SR_PTR_TYPE_M) {
501071d10453SEric Joyner 		loc_data &= ICE_AQC_NVM_EMP_SR_PTR_M;
501171d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_SECTOR_UNIT;
501271d10453SEric Joyner 	} else {
501371d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_WORD_UNIT;
501471d10453SEric Joyner 	}
501571d10453SEric Joyner 
501671d10453SEric Joyner 	/* Read the offset of LLDP configuration pointer */
501771d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_PTR_OFFSET;
501871d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
501971d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_CFG_PTR_RD_LEN, &loc_raw_data,
502071d10453SEric Joyner 			      false, true, NULL);
502171d10453SEric Joyner 	if (ret)
502271d10453SEric Joyner 		goto exit;
502371d10453SEric Joyner 
502471d10453SEric Joyner 	loc_data_tmp = LE16_TO_CPU(loc_raw_data);
502571d10453SEric Joyner 	loc_data_tmp *= ICE_AQC_NVM_WORD_UNIT;
502671d10453SEric Joyner 	loc_data += loc_data_tmp;
502771d10453SEric Joyner 
502871d10453SEric Joyner 	/* We need to skip LLDP configuration section length (2 bytes) */
502971d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_HEADER_LEN;
503071d10453SEric Joyner 
503171d10453SEric Joyner 	/* Read the LLDP Default Configure */
503271d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
503371d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data, false,
503471d10453SEric Joyner 			      true, NULL);
503571d10453SEric Joyner 	if (!ret) {
503671d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
503771d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
503871d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
503971d10453SEric Joyner 		data = data & mask;
504071d10453SEric Joyner 		*lldp_status = data >>
504171d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
504271d10453SEric Joyner 	}
504371d10453SEric Joyner 
504471d10453SEric Joyner exit:
504571d10453SEric Joyner 	ice_release_nvm(hw);
504671d10453SEric Joyner 
504771d10453SEric Joyner 	return ret;
504871d10453SEric Joyner }
504971d10453SEric Joyner 
505071d10453SEric Joyner /**
505171d10453SEric Joyner  * ice_fw_supports_link_override
505271d10453SEric Joyner  * @hw: pointer to the hardware structure
505371d10453SEric Joyner  *
505471d10453SEric Joyner  * Checks if the firmware supports link override
505571d10453SEric Joyner  */
505671d10453SEric Joyner bool ice_fw_supports_link_override(struct ice_hw *hw)
505771d10453SEric Joyner {
505871d10453SEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_LINK_OVERRIDE_MAJ) {
505971d10453SEric Joyner 		if (hw->api_min_ver > ICE_FW_API_LINK_OVERRIDE_MIN)
506071d10453SEric Joyner 			return true;
506171d10453SEric Joyner 		if (hw->api_min_ver == ICE_FW_API_LINK_OVERRIDE_MIN &&
506271d10453SEric Joyner 		    hw->api_patch >= ICE_FW_API_LINK_OVERRIDE_PATCH)
506371d10453SEric Joyner 			return true;
506471d10453SEric Joyner 	} else if (hw->api_maj_ver > ICE_FW_API_LINK_OVERRIDE_MAJ) {
506571d10453SEric Joyner 		return true;
506671d10453SEric Joyner 	}
506771d10453SEric Joyner 
506871d10453SEric Joyner 	return false;
506971d10453SEric Joyner }
507071d10453SEric Joyner 
507171d10453SEric Joyner /**
507271d10453SEric Joyner  * ice_get_link_default_override
507371d10453SEric Joyner  * @ldo: pointer to the link default override struct
507471d10453SEric Joyner  * @pi: pointer to the port info struct
507571d10453SEric Joyner  *
507671d10453SEric Joyner  * Gets the link default override for a port
507771d10453SEric Joyner  */
507871d10453SEric Joyner enum ice_status
507971d10453SEric Joyner ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
508071d10453SEric Joyner 			      struct ice_port_info *pi)
508171d10453SEric Joyner {
508271d10453SEric Joyner 	u16 i, tlv, tlv_len, tlv_start, buf, offset;
508371d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
508471d10453SEric Joyner 	enum ice_status status;
508571d10453SEric Joyner 
508671d10453SEric Joyner 	status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
508771d10453SEric Joyner 					ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
508871d10453SEric Joyner 	if (status) {
5089*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n");
509071d10453SEric Joyner 		return status;
509171d10453SEric Joyner 	}
509271d10453SEric Joyner 
509371d10453SEric Joyner 	/* Each port has its own config; calculate for our port */
509471d10453SEric Joyner 	tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
509571d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
509671d10453SEric Joyner 
509771d10453SEric Joyner 	/* link options first */
509871d10453SEric Joyner 	status = ice_read_sr_word(hw, tlv_start, &buf);
509971d10453SEric Joyner 	if (status) {
5100*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
510171d10453SEric Joyner 		return status;
510271d10453SEric Joyner 	}
510371d10453SEric Joyner 	ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
510471d10453SEric Joyner 	ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
510571d10453SEric Joyner 		ICE_LINK_OVERRIDE_PHY_CFG_S;
510671d10453SEric Joyner 
510771d10453SEric Joyner 	/* link PHY config */
510871d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
510971d10453SEric Joyner 	status = ice_read_sr_word(hw, offset, &buf);
511071d10453SEric Joyner 	if (status) {
5111*7d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n");
511271d10453SEric Joyner 		return status;
511371d10453SEric Joyner 	}
511471d10453SEric Joyner 	ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
511571d10453SEric Joyner 
511671d10453SEric Joyner 	/* PHY types low */
511771d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
511871d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
511971d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
512071d10453SEric Joyner 		if (status) {
5121*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
512271d10453SEric Joyner 			return status;
512371d10453SEric Joyner 		}
512471d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
512571d10453SEric Joyner 		ldo->phy_type_low |= ((u64)buf << (i * 16));
512671d10453SEric Joyner 	}
512771d10453SEric Joyner 
512871d10453SEric Joyner 	/* PHY types high */
512971d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
513071d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
513171d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
513271d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
513371d10453SEric Joyner 		if (status) {
5134*7d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
513571d10453SEric Joyner 			return status;
513671d10453SEric Joyner 		}
513771d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
513871d10453SEric Joyner 		ldo->phy_type_high |= ((u64)buf << (i * 16));
513971d10453SEric Joyner 	}
514071d10453SEric Joyner 
514171d10453SEric Joyner 	return status;
514271d10453SEric Joyner }
5143*7d7af7f8SEric Joyner 
5144*7d7af7f8SEric Joyner /**
5145*7d7af7f8SEric Joyner  * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
5146*7d7af7f8SEric Joyner  * @caps: get PHY capability data
5147*7d7af7f8SEric Joyner  */
5148*7d7af7f8SEric Joyner bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
5149*7d7af7f8SEric Joyner {
5150*7d7af7f8SEric Joyner 	if (caps->caps & ICE_AQC_PHY_AN_MODE ||
5151*7d7af7f8SEric Joyner 	    caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
5152*7d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE73 |
5153*7d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE37))
5154*7d7af7f8SEric Joyner 		return true;
5155*7d7af7f8SEric Joyner 
5156*7d7af7f8SEric Joyner 	return false;
5157*7d7af7f8SEric Joyner }
5158*7d7af7f8SEric Joyner 
5159*7d7af7f8SEric Joyner /**
5160*7d7af7f8SEric Joyner  * ice_aq_set_lldp_mib - Set the LLDP MIB
5161*7d7af7f8SEric Joyner  * @hw: pointer to the HW struct
5162*7d7af7f8SEric Joyner  * @mib_type: Local, Remote or both Local and Remote MIBs
5163*7d7af7f8SEric Joyner  * @buf: pointer to the caller-supplied buffer to store the MIB block
5164*7d7af7f8SEric Joyner  * @buf_size: size of the buffer (in bytes)
5165*7d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
5166*7d7af7f8SEric Joyner  *
5167*7d7af7f8SEric Joyner  * Set the LLDP MIB. (0x0A08)
5168*7d7af7f8SEric Joyner  */
5169*7d7af7f8SEric Joyner enum ice_status
5170*7d7af7f8SEric Joyner ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
5171*7d7af7f8SEric Joyner 		    struct ice_sq_cd *cd)
5172*7d7af7f8SEric Joyner {
5173*7d7af7f8SEric Joyner 	struct ice_aqc_lldp_set_local_mib *cmd;
5174*7d7af7f8SEric Joyner 	struct ice_aq_desc desc;
5175*7d7af7f8SEric Joyner 
5176*7d7af7f8SEric Joyner 	cmd = &desc.params.lldp_set_mib;
5177*7d7af7f8SEric Joyner 
5178*7d7af7f8SEric Joyner 	if (buf_size == 0 || !buf)
5179*7d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
5180*7d7af7f8SEric Joyner 
5181*7d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
5182*7d7af7f8SEric Joyner 
5183*7d7af7f8SEric Joyner 	desc.flags |= CPU_TO_LE16((u16)ICE_AQ_FLAG_RD);
5184*7d7af7f8SEric Joyner 	desc.datalen = CPU_TO_LE16(buf_size);
5185*7d7af7f8SEric Joyner 
5186*7d7af7f8SEric Joyner 	cmd->type = mib_type;
5187*7d7af7f8SEric Joyner 	cmd->length = CPU_TO_LE16(buf_size);
5188*7d7af7f8SEric Joyner 
5189*7d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
5190*7d7af7f8SEric Joyner }
5191*7d7af7f8SEric Joyner 
5192*7d7af7f8SEric Joyner /**
5193*7d7af7f8SEric Joyner  * ice_fw_supports_lldp_fltr - check NVM version supports lldp_fltr_ctrl
5194*7d7af7f8SEric Joyner  * @hw: pointer to HW struct
5195*7d7af7f8SEric Joyner  */
5196*7d7af7f8SEric Joyner bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
5197*7d7af7f8SEric Joyner {
5198*7d7af7f8SEric Joyner 	if (hw->mac_type != ICE_MAC_E810)
5199*7d7af7f8SEric Joyner 		return false;
5200*7d7af7f8SEric Joyner 
5201*7d7af7f8SEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_LLDP_FLTR_MAJ) {
5202*7d7af7f8SEric Joyner 		if (hw->api_min_ver > ICE_FW_API_LLDP_FLTR_MIN)
5203*7d7af7f8SEric Joyner 			return true;
5204*7d7af7f8SEric Joyner 		if (hw->api_min_ver == ICE_FW_API_LLDP_FLTR_MIN &&
5205*7d7af7f8SEric Joyner 		    hw->api_patch >= ICE_FW_API_LLDP_FLTR_PATCH)
5206*7d7af7f8SEric Joyner 			return true;
5207*7d7af7f8SEric Joyner 	} else if (hw->api_maj_ver > ICE_FW_API_LLDP_FLTR_MAJ) {
5208*7d7af7f8SEric Joyner 		return true;
5209*7d7af7f8SEric Joyner 	}
5210*7d7af7f8SEric Joyner 	return false;
5211*7d7af7f8SEric Joyner }
5212*7d7af7f8SEric Joyner 
5213*7d7af7f8SEric Joyner /**
5214*7d7af7f8SEric Joyner  * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
5215*7d7af7f8SEric Joyner  * @hw: pointer to HW struct
5216*7d7af7f8SEric Joyner  * @vsi_num: absolute HW index for VSI
5217*7d7af7f8SEric Joyner  * @add: boolean for if adding or removing a filter
5218*7d7af7f8SEric Joyner  */
5219*7d7af7f8SEric Joyner enum ice_status
5220*7d7af7f8SEric Joyner ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
5221*7d7af7f8SEric Joyner {
5222*7d7af7f8SEric Joyner 	struct ice_aqc_lldp_filter_ctrl *cmd;
5223*7d7af7f8SEric Joyner 	struct ice_aq_desc desc;
5224*7d7af7f8SEric Joyner 
5225*7d7af7f8SEric Joyner 	cmd = &desc.params.lldp_filter_ctrl;
5226*7d7af7f8SEric Joyner 
5227*7d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
5228*7d7af7f8SEric Joyner 
5229*7d7af7f8SEric Joyner 	if (add)
5230*7d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
5231*7d7af7f8SEric Joyner 	else
5232*7d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
5233*7d7af7f8SEric Joyner 
5234*7d7af7f8SEric Joyner 	cmd->vsi_num = CPU_TO_LE16(vsi_num);
5235*7d7af7f8SEric Joyner 
5236*7d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
5237*7d7af7f8SEric Joyner }
5238