xref: /freebsd/sys/dev/ice/ice_common.c (revision 56429daea255fa719169bb23ded66f8edb6f5408)
171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2d08b8680SEric Joyner /*  Copyright (c) 2021, 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 /**
43*56429daeSEric Joyner  * dump_phy_type - helper function that prints PHY type strings
44*56429daeSEric Joyner  * @hw: pointer to the HW structure
45*56429daeSEric Joyner  * @phy: 64 bit PHY type to decipher
46*56429daeSEric Joyner  * @i: bit index within phy
47*56429daeSEric Joyner  * @phy_string: string corresponding to bit i in phy
48*56429daeSEric Joyner  * @prefix: prefix string to differentiate multiple dumps
49*56429daeSEric Joyner  */
50*56429daeSEric Joyner static void
51*56429daeSEric Joyner dump_phy_type(struct ice_hw *hw, u64 phy, u8 i, const char *phy_string,
52*56429daeSEric Joyner 	      const char *prefix)
53*56429daeSEric Joyner {
54*56429daeSEric Joyner 	if (phy & BIT_ULL(i))
55*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "%s: bit(%d): %s\n", prefix, i,
56*56429daeSEric Joyner 			  phy_string);
57*56429daeSEric Joyner }
58*56429daeSEric Joyner 
59*56429daeSEric Joyner /**
60*56429daeSEric Joyner  * ice_dump_phy_type_low - helper function to dump phy_type_low
61*56429daeSEric Joyner  * @hw: pointer to the HW structure
62*56429daeSEric Joyner  * @low: 64 bit value for phy_type_low
63*56429daeSEric Joyner  * @prefix: prefix string to differentiate multiple dumps
64*56429daeSEric Joyner  */
65*56429daeSEric Joyner static void
66*56429daeSEric Joyner ice_dump_phy_type_low(struct ice_hw *hw, u64 low, const char *prefix)
67*56429daeSEric Joyner {
68*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix,
69*56429daeSEric Joyner 		  (unsigned long long)low);
70*56429daeSEric Joyner 
71*56429daeSEric Joyner 	dump_phy_type(hw, low, 0, "100BASE_TX", prefix);
72*56429daeSEric Joyner 	dump_phy_type(hw, low, 1, "100M_SGMII", prefix);
73*56429daeSEric Joyner 	dump_phy_type(hw, low, 2, "1000BASE_T", prefix);
74*56429daeSEric Joyner 	dump_phy_type(hw, low, 3, "1000BASE_SX", prefix);
75*56429daeSEric Joyner 	dump_phy_type(hw, low, 4, "1000BASE_LX", prefix);
76*56429daeSEric Joyner 	dump_phy_type(hw, low, 5, "1000BASE_KX", prefix);
77*56429daeSEric Joyner 	dump_phy_type(hw, low, 6, "1G_SGMII", prefix);
78*56429daeSEric Joyner 	dump_phy_type(hw, low, 7, "2500BASE_T", prefix);
79*56429daeSEric Joyner 	dump_phy_type(hw, low, 8, "2500BASE_X", prefix);
80*56429daeSEric Joyner 	dump_phy_type(hw, low, 9, "2500BASE_KX", prefix);
81*56429daeSEric Joyner 	dump_phy_type(hw, low, 10, "5GBASE_T", prefix);
82*56429daeSEric Joyner 	dump_phy_type(hw, low, 11, "5GBASE_KR", prefix);
83*56429daeSEric Joyner 	dump_phy_type(hw, low, 12, "10GBASE_T", prefix);
84*56429daeSEric Joyner 	dump_phy_type(hw, low, 13, "10G_SFI_DA", prefix);
85*56429daeSEric Joyner 	dump_phy_type(hw, low, 14, "10GBASE_SR", prefix);
86*56429daeSEric Joyner 	dump_phy_type(hw, low, 15, "10GBASE_LR", prefix);
87*56429daeSEric Joyner 	dump_phy_type(hw, low, 16, "10GBASE_KR_CR1", prefix);
88*56429daeSEric Joyner 	dump_phy_type(hw, low, 17, "10G_SFI_AOC_ACC", prefix);
89*56429daeSEric Joyner 	dump_phy_type(hw, low, 18, "10G_SFI_C2C", prefix);
90*56429daeSEric Joyner 	dump_phy_type(hw, low, 19, "25GBASE_T", prefix);
91*56429daeSEric Joyner 	dump_phy_type(hw, low, 20, "25GBASE_CR", prefix);
92*56429daeSEric Joyner 	dump_phy_type(hw, low, 21, "25GBASE_CR_S", prefix);
93*56429daeSEric Joyner 	dump_phy_type(hw, low, 22, "25GBASE_CR1", prefix);
94*56429daeSEric Joyner 	dump_phy_type(hw, low, 23, "25GBASE_SR", prefix);
95*56429daeSEric Joyner 	dump_phy_type(hw, low, 24, "25GBASE_LR", prefix);
96*56429daeSEric Joyner 	dump_phy_type(hw, low, 25, "25GBASE_KR", prefix);
97*56429daeSEric Joyner 	dump_phy_type(hw, low, 26, "25GBASE_KR_S", prefix);
98*56429daeSEric Joyner 	dump_phy_type(hw, low, 27, "25GBASE_KR1", prefix);
99*56429daeSEric Joyner 	dump_phy_type(hw, low, 28, "25G_AUI_AOC_ACC", prefix);
100*56429daeSEric Joyner 	dump_phy_type(hw, low, 29, "25G_AUI_C2C", prefix);
101*56429daeSEric Joyner 	dump_phy_type(hw, low, 30, "40GBASE_CR4", prefix);
102*56429daeSEric Joyner 	dump_phy_type(hw, low, 31, "40GBASE_SR4", prefix);
103*56429daeSEric Joyner 	dump_phy_type(hw, low, 32, "40GBASE_LR4", prefix);
104*56429daeSEric Joyner 	dump_phy_type(hw, low, 33, "40GBASE_KR4", prefix);
105*56429daeSEric Joyner 	dump_phy_type(hw, low, 34, "40G_XLAUI_AOC_ACC", prefix);
106*56429daeSEric Joyner 	dump_phy_type(hw, low, 35, "40G_XLAUI", prefix);
107*56429daeSEric Joyner 	dump_phy_type(hw, low, 36, "50GBASE_CR2", prefix);
108*56429daeSEric Joyner 	dump_phy_type(hw, low, 37, "50GBASE_SR2", prefix);
109*56429daeSEric Joyner 	dump_phy_type(hw, low, 38, "50GBASE_LR2", prefix);
110*56429daeSEric Joyner 	dump_phy_type(hw, low, 39, "50GBASE_KR2", prefix);
111*56429daeSEric Joyner 	dump_phy_type(hw, low, 40, "50G_LAUI2_AOC_ACC", prefix);
112*56429daeSEric Joyner 	dump_phy_type(hw, low, 41, "50G_LAUI2", prefix);
113*56429daeSEric Joyner 	dump_phy_type(hw, low, 42, "50G_AUI2_AOC_ACC", prefix);
114*56429daeSEric Joyner 	dump_phy_type(hw, low, 43, "50G_AUI2", prefix);
115*56429daeSEric Joyner 	dump_phy_type(hw, low, 44, "50GBASE_CP", prefix);
116*56429daeSEric Joyner 	dump_phy_type(hw, low, 45, "50GBASE_SR", prefix);
117*56429daeSEric Joyner 	dump_phy_type(hw, low, 46, "50GBASE_FR", prefix);
118*56429daeSEric Joyner 	dump_phy_type(hw, low, 47, "50GBASE_LR", prefix);
119*56429daeSEric Joyner 	dump_phy_type(hw, low, 48, "50GBASE_KR_PAM4", prefix);
120*56429daeSEric Joyner 	dump_phy_type(hw, low, 49, "50G_AUI1_AOC_ACC", prefix);
121*56429daeSEric Joyner 	dump_phy_type(hw, low, 50, "50G_AUI1", prefix);
122*56429daeSEric Joyner 	dump_phy_type(hw, low, 51, "100GBASE_CR4", prefix);
123*56429daeSEric Joyner 	dump_phy_type(hw, low, 52, "100GBASE_SR4", prefix);
124*56429daeSEric Joyner 	dump_phy_type(hw, low, 53, "100GBASE_LR4", prefix);
125*56429daeSEric Joyner 	dump_phy_type(hw, low, 54, "100GBASE_KR4", prefix);
126*56429daeSEric Joyner 	dump_phy_type(hw, low, 55, "100G_CAUI4_AOC_ACC", prefix);
127*56429daeSEric Joyner 	dump_phy_type(hw, low, 56, "100G_CAUI4", prefix);
128*56429daeSEric Joyner 	dump_phy_type(hw, low, 57, "100G_AUI4_AOC_ACC", prefix);
129*56429daeSEric Joyner 	dump_phy_type(hw, low, 58, "100G_AUI4", prefix);
130*56429daeSEric Joyner 	dump_phy_type(hw, low, 59, "100GBASE_CR_PAM4", prefix);
131*56429daeSEric Joyner 	dump_phy_type(hw, low, 60, "100GBASE_KR_PAM4", prefix);
132*56429daeSEric Joyner 	dump_phy_type(hw, low, 61, "100GBASE_CP2", prefix);
133*56429daeSEric Joyner 	dump_phy_type(hw, low, 62, "100GBASE_SR2", prefix);
134*56429daeSEric Joyner 	dump_phy_type(hw, low, 63, "100GBASE_DR", prefix);
135*56429daeSEric Joyner }
136*56429daeSEric Joyner 
137*56429daeSEric Joyner /**
138*56429daeSEric Joyner  * ice_dump_phy_type_high - helper function to dump phy_type_high
139*56429daeSEric Joyner  * @hw: pointer to the HW structure
140*56429daeSEric Joyner  * @high: 64 bit value for phy_type_high
141*56429daeSEric Joyner  * @prefix: prefix string to differentiate multiple dumps
142*56429daeSEric Joyner  */
143*56429daeSEric Joyner static void
144*56429daeSEric Joyner ice_dump_phy_type_high(struct ice_hw *hw, u64 high, const char *prefix)
145*56429daeSEric Joyner {
146*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix,
147*56429daeSEric Joyner 		  (unsigned long long)high);
148*56429daeSEric Joyner 
149*56429daeSEric Joyner 	dump_phy_type(hw, high, 0, "100GBASE_KR2_PAM4", prefix);
150*56429daeSEric Joyner 	dump_phy_type(hw, high, 1, "100G_CAUI2_AOC_ACC", prefix);
151*56429daeSEric Joyner 	dump_phy_type(hw, high, 2, "100G_CAUI2", prefix);
152*56429daeSEric Joyner 	dump_phy_type(hw, high, 3, "100G_AUI2_AOC_ACC", prefix);
153*56429daeSEric Joyner 	dump_phy_type(hw, high, 4, "100G_AUI2", prefix);
154*56429daeSEric Joyner }
155*56429daeSEric Joyner 
156*56429daeSEric Joyner /**
15771d10453SEric Joyner  * ice_set_mac_type - Sets MAC type
15871d10453SEric Joyner  * @hw: pointer to the HW structure
15971d10453SEric Joyner  *
16071d10453SEric Joyner  * This function sets the MAC type of the adapter based on the
16171d10453SEric Joyner  * vendor ID and device ID stored in the HW structure.
16271d10453SEric Joyner  */
16371d10453SEric Joyner enum ice_status ice_set_mac_type(struct ice_hw *hw)
16471d10453SEric Joyner {
16571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
16671d10453SEric Joyner 
16771d10453SEric Joyner 	if (hw->vendor_id != ICE_INTEL_VENDOR_ID)
16871d10453SEric Joyner 		return ICE_ERR_DEVICE_NOT_SUPPORTED;
16971d10453SEric Joyner 
17071d10453SEric Joyner 	switch (hw->device_id) {
17171d10453SEric Joyner 	case ICE_DEV_ID_E810C_BACKPLANE:
17271d10453SEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
17371d10453SEric Joyner 	case ICE_DEV_ID_E810C_SFP:
17471d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_BACKPLANE:
17571d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_QSFP:
17671d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_SFP:
17771d10453SEric Joyner 		hw->mac_type = ICE_MAC_E810;
17871d10453SEric Joyner 		break;
17971d10453SEric Joyner 	case ICE_DEV_ID_E822C_10G_BASE_T:
18071d10453SEric Joyner 	case ICE_DEV_ID_E822C_BACKPLANE:
18171d10453SEric Joyner 	case ICE_DEV_ID_E822C_QSFP:
18271d10453SEric Joyner 	case ICE_DEV_ID_E822C_SFP:
18371d10453SEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
18471d10453SEric Joyner 	case ICE_DEV_ID_E822L_10G_BASE_T:
18571d10453SEric Joyner 	case ICE_DEV_ID_E822L_BACKPLANE:
18671d10453SEric Joyner 	case ICE_DEV_ID_E822L_SFP:
18771d10453SEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
18871d10453SEric Joyner 	case ICE_DEV_ID_E823L_10G_BASE_T:
18971d10453SEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
19071d10453SEric Joyner 	case ICE_DEV_ID_E823L_BACKPLANE:
19171d10453SEric Joyner 	case ICE_DEV_ID_E823L_QSFP:
19271d10453SEric Joyner 	case ICE_DEV_ID_E823L_SFP:
193*56429daeSEric Joyner 	case ICE_DEV_ID_E823C_10G_BASE_T:
194*56429daeSEric Joyner 	case ICE_DEV_ID_E823C_BACKPLANE:
195*56429daeSEric Joyner 	case ICE_DEV_ID_E823C_QSFP:
196*56429daeSEric Joyner 	case ICE_DEV_ID_E823C_SFP:
197*56429daeSEric Joyner 	case ICE_DEV_ID_E823C_SGMII:
19871d10453SEric Joyner 		hw->mac_type = ICE_MAC_GENERIC;
19971d10453SEric Joyner 		break;
20071d10453SEric Joyner 	default:
20171d10453SEric Joyner 		hw->mac_type = ICE_MAC_UNKNOWN;
20271d10453SEric Joyner 		break;
20371d10453SEric Joyner 	}
20471d10453SEric Joyner 
20571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
20671d10453SEric Joyner 	return ICE_SUCCESS;
20771d10453SEric Joyner }
20871d10453SEric Joyner 
20971d10453SEric Joyner /**
210*56429daeSEric Joyner  * ice_is_e810
211*56429daeSEric Joyner  * @hw: pointer to the hardware structure
212*56429daeSEric Joyner  *
213*56429daeSEric Joyner  * returns true if the device is E810 based, false if not.
214*56429daeSEric Joyner  */
215*56429daeSEric Joyner bool ice_is_e810(struct ice_hw *hw)
216*56429daeSEric Joyner {
217*56429daeSEric Joyner 	return hw->mac_type == ICE_MAC_E810;
218*56429daeSEric Joyner }
219*56429daeSEric Joyner 
220*56429daeSEric Joyner /**
221*56429daeSEric Joyner  * ice_is_e810t
222*56429daeSEric Joyner  * @hw: pointer to the hardware structure
223*56429daeSEric Joyner  *
224*56429daeSEric Joyner  * returns true if the device is E810T based, false if not.
225*56429daeSEric Joyner  */
226*56429daeSEric Joyner bool ice_is_e810t(struct ice_hw *hw)
227*56429daeSEric Joyner {
228*56429daeSEric Joyner 	switch (hw->device_id) {
229*56429daeSEric Joyner 	case ICE_DEV_ID_E810C_SFP:
230*56429daeSEric Joyner 		if (hw->subsystem_device_id == ICE_SUBDEV_ID_E810T ||
231*56429daeSEric Joyner 		    hw->subsystem_device_id == ICE_SUBDEV_ID_E810T2)
232*56429daeSEric Joyner 			return true;
233*56429daeSEric Joyner 		break;
234*56429daeSEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
235*56429daeSEric Joyner 		if (hw->subsystem_device_id == ICE_SUBDEV_ID_E810T2)
236*56429daeSEric Joyner 			return true;
237*56429daeSEric Joyner 		break;
238*56429daeSEric Joyner 	default:
239*56429daeSEric Joyner 		break;
240*56429daeSEric Joyner 	}
241*56429daeSEric Joyner 
242*56429daeSEric Joyner 	return false;
243*56429daeSEric Joyner }
244*56429daeSEric Joyner 
245*56429daeSEric Joyner /**
24671d10453SEric Joyner  * ice_clear_pf_cfg - Clear PF configuration
24771d10453SEric Joyner  * @hw: pointer to the hardware structure
24871d10453SEric Joyner  *
24971d10453SEric Joyner  * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
25071d10453SEric Joyner  * configuration, flow director filters, etc.).
25171d10453SEric Joyner  */
25271d10453SEric Joyner enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
25371d10453SEric Joyner {
25471d10453SEric Joyner 	struct ice_aq_desc desc;
25571d10453SEric Joyner 
25671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
25771d10453SEric Joyner 
25871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
25971d10453SEric Joyner }
26071d10453SEric Joyner 
26171d10453SEric Joyner /**
26271d10453SEric Joyner  * ice_aq_manage_mac_read - manage MAC address read command
26371d10453SEric Joyner  * @hw: pointer to the HW struct
26471d10453SEric Joyner  * @buf: a virtual buffer to hold the manage MAC read response
26571d10453SEric Joyner  * @buf_size: Size of the virtual buffer
26671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
26771d10453SEric Joyner  *
26871d10453SEric Joyner  * This function is used to return per PF station MAC address (0x0107).
26971d10453SEric Joyner  * NOTE: Upon successful completion of this command, MAC address information
27071d10453SEric Joyner  * is returned in user specified buffer. Please interpret user specified
27171d10453SEric Joyner  * buffer as "manage_mac_read" response.
27271d10453SEric Joyner  * Response such as various MAC addresses are stored in HW struct (port.mac)
2737d7af7f8SEric Joyner  * ice_discover_dev_caps is expected to be called before this function is
2747d7af7f8SEric Joyner  * called.
27571d10453SEric Joyner  */
27671d10453SEric Joyner enum ice_status
27771d10453SEric Joyner ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
27871d10453SEric Joyner 		       struct ice_sq_cd *cd)
27971d10453SEric Joyner {
28071d10453SEric Joyner 	struct ice_aqc_manage_mac_read_resp *resp;
28171d10453SEric Joyner 	struct ice_aqc_manage_mac_read *cmd;
28271d10453SEric Joyner 	struct ice_aq_desc desc;
28371d10453SEric Joyner 	enum ice_status status;
28471d10453SEric Joyner 	u16 flags;
28571d10453SEric Joyner 	u8 i;
28671d10453SEric Joyner 
28771d10453SEric Joyner 	cmd = &desc.params.mac_read;
28871d10453SEric Joyner 
28971d10453SEric Joyner 	if (buf_size < sizeof(*resp))
29071d10453SEric Joyner 		return ICE_ERR_BUF_TOO_SHORT;
29171d10453SEric Joyner 
29271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
29371d10453SEric Joyner 
29471d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
29571d10453SEric Joyner 	if (status)
29671d10453SEric Joyner 		return status;
29771d10453SEric Joyner 
29871d10453SEric Joyner 	resp = (struct ice_aqc_manage_mac_read_resp *)buf;
29971d10453SEric Joyner 	flags = LE16_TO_CPU(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
30071d10453SEric Joyner 
30171d10453SEric Joyner 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
30271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
30371d10453SEric Joyner 		return ICE_ERR_CFG;
30471d10453SEric Joyner 	}
30571d10453SEric Joyner 
30671d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
30771d10453SEric Joyner 	for (i = 0; i < cmd->num_addr; i++)
30871d10453SEric Joyner 		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
30971d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.lan_addr,
31071d10453SEric Joyner 				   resp[i].mac_addr, ETH_ALEN,
31171d10453SEric Joyner 				   ICE_DMA_TO_NONDMA);
31271d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.perm_addr,
31371d10453SEric Joyner 				   resp[i].mac_addr,
31471d10453SEric Joyner 				   ETH_ALEN, ICE_DMA_TO_NONDMA);
31571d10453SEric Joyner 			break;
31671d10453SEric Joyner 		}
31771d10453SEric Joyner 	return ICE_SUCCESS;
31871d10453SEric Joyner }
31971d10453SEric Joyner 
32071d10453SEric Joyner /**
32171d10453SEric Joyner  * ice_aq_get_phy_caps - returns PHY capabilities
32271d10453SEric Joyner  * @pi: port information structure
32371d10453SEric Joyner  * @qual_mods: report qualified modules
32471d10453SEric Joyner  * @report_mode: report mode capabilities
32571d10453SEric Joyner  * @pcaps: structure for PHY capabilities to be filled
32671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
32771d10453SEric Joyner  *
32871d10453SEric Joyner  * Returns the various PHY capabilities supported on the Port (0x0600)
32971d10453SEric Joyner  */
33071d10453SEric Joyner enum ice_status
33171d10453SEric Joyner ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
33271d10453SEric Joyner 		    struct ice_aqc_get_phy_caps_data *pcaps,
33371d10453SEric Joyner 		    struct ice_sq_cd *cd)
33471d10453SEric Joyner {
33571d10453SEric Joyner 	struct ice_aqc_get_phy_caps *cmd;
33671d10453SEric Joyner 	u16 pcaps_size = sizeof(*pcaps);
33771d10453SEric Joyner 	struct ice_aq_desc desc;
33871d10453SEric Joyner 	enum ice_status status;
339*56429daeSEric Joyner 	const char *prefix;
3407d7af7f8SEric Joyner 	struct ice_hw *hw;
34171d10453SEric Joyner 
34271d10453SEric Joyner 	cmd = &desc.params.get_phy;
34371d10453SEric Joyner 
34471d10453SEric Joyner 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
34571d10453SEric Joyner 		return ICE_ERR_PARAM;
3467d7af7f8SEric Joyner 	hw = pi->hw;
34771d10453SEric Joyner 
3489cf1841cSEric Joyner 	if (report_mode == ICE_AQC_REPORT_DFLT_CFG &&
3499cf1841cSEric Joyner 	    !ice_fw_supports_report_dflt_cfg(hw))
3509cf1841cSEric Joyner 		return ICE_ERR_PARAM;
3519cf1841cSEric Joyner 
35271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
35371d10453SEric Joyner 
35471d10453SEric Joyner 	if (qual_mods)
35571d10453SEric Joyner 		cmd->param0 |= CPU_TO_LE16(ICE_AQC_GET_PHY_RQM);
35671d10453SEric Joyner 
35771d10453SEric Joyner 	cmd->param0 |= CPU_TO_LE16(report_mode);
3587d7af7f8SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
3597d7af7f8SEric Joyner 
360*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
361*56429daeSEric Joyner 
362*56429daeSEric Joyner 	if (report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA)
363*56429daeSEric Joyner 		prefix = "phy_caps_media";
364*56429daeSEric Joyner 	else if (report_mode == ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA)
365*56429daeSEric Joyner 		prefix = "phy_caps_no_media";
366*56429daeSEric Joyner 	else if (report_mode == ICE_AQC_REPORT_ACTIVE_CFG)
367*56429daeSEric Joyner 		prefix = "phy_caps_active";
368*56429daeSEric Joyner 	else if (report_mode == ICE_AQC_REPORT_DFLT_CFG)
369*56429daeSEric Joyner 		prefix = "phy_caps_default";
370*56429daeSEric Joyner 	else
371*56429daeSEric Joyner 		prefix = "phy_caps_invalid";
372*56429daeSEric Joyner 
373*56429daeSEric Joyner 	ice_dump_phy_type_low(hw, LE64_TO_CPU(pcaps->phy_type_low), prefix);
374*56429daeSEric Joyner 	ice_dump_phy_type_high(hw, LE64_TO_CPU(pcaps->phy_type_high), prefix);
375*56429daeSEric Joyner 
376*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
377*56429daeSEric Joyner 		  prefix, report_mode);
378*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
379*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
3807d7af7f8SEric Joyner 		  pcaps->low_power_ctrl_an);
381*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
382*56429daeSEric Joyner 		  pcaps->eee_cap);
383*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
3847d7af7f8SEric Joyner 		  pcaps->eeer_value);
385*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
3867d7af7f8SEric Joyner 		  pcaps->link_fec_options);
387*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
388*56429daeSEric Joyner 		  prefix, pcaps->module_compliance_enforcement);
389*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
390*56429daeSEric Joyner 		  prefix, pcaps->extended_compliance_code);
391*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
3927d7af7f8SEric Joyner 		  pcaps->module_type[0]);
393*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
3947d7af7f8SEric Joyner 		  pcaps->module_type[1]);
395*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
3967d7af7f8SEric Joyner 		  pcaps->module_type[2]);
39771d10453SEric Joyner 
3989cf1841cSEric Joyner 	if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
39971d10453SEric Joyner 		pi->phy.phy_type_low = LE64_TO_CPU(pcaps->phy_type_low);
40071d10453SEric Joyner 		pi->phy.phy_type_high = LE64_TO_CPU(pcaps->phy_type_high);
4017d7af7f8SEric Joyner 		ice_memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
4027d7af7f8SEric Joyner 			   sizeof(pi->phy.link_info.module_type),
4037d7af7f8SEric Joyner 			   ICE_NONDMA_TO_NONDMA);
40471d10453SEric Joyner 	}
40571d10453SEric Joyner 
40671d10453SEric Joyner 	return status;
40771d10453SEric Joyner }
40871d10453SEric Joyner 
40971d10453SEric Joyner /**
410*56429daeSEric Joyner  * ice_aq_get_netlist_node
411*56429daeSEric Joyner  * @hw: pointer to the hw struct
412*56429daeSEric Joyner  * @cmd: get_link_topo AQ structure
413*56429daeSEric Joyner  * @node_part_number: output node part number if node found
414*56429daeSEric Joyner  * @node_handle: output node handle parameter if node found
41571d10453SEric Joyner  */
416*56429daeSEric Joyner enum ice_status
417*56429daeSEric Joyner ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
418*56429daeSEric Joyner 			u8 *node_part_number, u16 *node_handle)
41971d10453SEric Joyner {
42071d10453SEric Joyner 	struct ice_aq_desc desc;
42171d10453SEric Joyner 
42271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
423*56429daeSEric Joyner 	desc.params.get_link_topo = *cmd;
42471d10453SEric Joyner 
425*56429daeSEric Joyner 	if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL))
426*56429daeSEric Joyner 		return ICE_ERR_NOT_SUPPORTED;
42771d10453SEric Joyner 
428*56429daeSEric Joyner 	if (node_handle)
429*56429daeSEric Joyner 		*node_handle =
430*56429daeSEric Joyner 			LE16_TO_CPU(desc.params.get_link_topo.addr.handle);
431*56429daeSEric Joyner 	if (node_part_number)
432*56429daeSEric Joyner 		*node_part_number = desc.params.get_link_topo.node_part_num;
43371d10453SEric Joyner 
434*56429daeSEric Joyner 	return ICE_SUCCESS;
435*56429daeSEric Joyner }
436*56429daeSEric Joyner 
437*56429daeSEric Joyner #define MAX_NETLIST_SIZE 10
438*56429daeSEric Joyner /**
439*56429daeSEric Joyner  * ice_find_netlist_node
440*56429daeSEric Joyner  * @hw: pointer to the hw struct
441*56429daeSEric Joyner  * @node_type_ctx: type of netlist node to look for
442*56429daeSEric Joyner  * @node_part_number: node part number to look for
443*56429daeSEric Joyner  * @node_handle: output parameter if node found - optional
444*56429daeSEric Joyner  *
445*56429daeSEric Joyner  * Find and return the node handle for a given node type and part number in the
446*56429daeSEric Joyner  * netlist. When found ICE_SUCCESS is returned, ICE_ERR_DOES_NOT_EXIST
447*56429daeSEric Joyner  * otherwise. If @node_handle provided, it would be set to found node handle.
448*56429daeSEric Joyner  */
449*56429daeSEric Joyner enum ice_status
450*56429daeSEric Joyner ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number,
451*56429daeSEric Joyner 		      u16 *node_handle)
452*56429daeSEric Joyner {
453*56429daeSEric Joyner 	struct ice_aqc_get_link_topo cmd;
454*56429daeSEric Joyner 	u8 rec_node_part_number;
455*56429daeSEric Joyner 	enum ice_status status;
456*56429daeSEric Joyner 	u16 rec_node_handle;
457*56429daeSEric Joyner 	u8 idx;
458*56429daeSEric Joyner 
459*56429daeSEric Joyner 	for (idx = 0; idx < MAX_NETLIST_SIZE; idx++) {
460*56429daeSEric Joyner 		memset(&cmd, 0, sizeof(cmd));
461*56429daeSEric Joyner 
462*56429daeSEric Joyner 		cmd.addr.topo_params.node_type_ctx =
463*56429daeSEric Joyner 			(node_type_ctx << ICE_AQC_LINK_TOPO_NODE_TYPE_S);
464*56429daeSEric Joyner 		cmd.addr.topo_params.index = idx;
465*56429daeSEric Joyner 
466*56429daeSEric Joyner 		status = ice_aq_get_netlist_node(hw, &cmd,
467*56429daeSEric Joyner 						 &rec_node_part_number,
468*56429daeSEric Joyner 						 &rec_node_handle);
469*56429daeSEric Joyner 		if (status)
470*56429daeSEric Joyner 			return status;
471*56429daeSEric Joyner 
472*56429daeSEric Joyner 		if (rec_node_part_number == node_part_number) {
473*56429daeSEric Joyner 			if (node_handle)
474*56429daeSEric Joyner 				*node_handle = rec_node_handle;
475*56429daeSEric Joyner 			return ICE_SUCCESS;
476*56429daeSEric Joyner 		}
477*56429daeSEric Joyner 	}
478*56429daeSEric Joyner 
479*56429daeSEric Joyner 	return ICE_ERR_DOES_NOT_EXIST;
48071d10453SEric Joyner }
48171d10453SEric Joyner 
482d08b8680SEric Joyner /**
48371d10453SEric Joyner  * ice_is_media_cage_present
48471d10453SEric Joyner  * @pi: port information structure
48571d10453SEric Joyner  *
48671d10453SEric Joyner  * Returns true if media cage is present, else false. If no cage, then
48771d10453SEric Joyner  * media type is backplane or BASE-T.
48871d10453SEric Joyner  */
48971d10453SEric Joyner static bool ice_is_media_cage_present(struct ice_port_info *pi)
49071d10453SEric Joyner {
491*56429daeSEric Joyner 	struct ice_aqc_get_link_topo *cmd;
492*56429daeSEric Joyner 	struct ice_aq_desc desc;
493*56429daeSEric Joyner 
494*56429daeSEric Joyner 	cmd = &desc.params.get_link_topo;
495*56429daeSEric Joyner 
496*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
497*56429daeSEric Joyner 
498*56429daeSEric Joyner 	cmd->addr.topo_params.node_type_ctx =
499*56429daeSEric Joyner 		(ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
500*56429daeSEric Joyner 		 ICE_AQC_LINK_TOPO_NODE_CTX_S);
501*56429daeSEric Joyner 
502*56429daeSEric Joyner 	/* set node type */
503*56429daeSEric Joyner 	cmd->addr.topo_params.node_type_ctx |=
504*56429daeSEric Joyner 		(ICE_AQC_LINK_TOPO_NODE_TYPE_M &
505*56429daeSEric Joyner 		 ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE);
506*56429daeSEric Joyner 
50771d10453SEric Joyner 	/* Node type cage can be used to determine if cage is present. If AQC
50871d10453SEric Joyner 	 * returns error (ENOENT), then no cage present. If no cage present then
50971d10453SEric Joyner 	 * connection type is backplane or BASE-T.
51071d10453SEric Joyner 	 */
511*56429daeSEric Joyner 	return ice_aq_get_netlist_node(pi->hw, cmd, NULL, NULL);
51271d10453SEric Joyner }
51371d10453SEric Joyner 
51471d10453SEric Joyner /**
51571d10453SEric Joyner  * ice_get_media_type - Gets media type
51671d10453SEric Joyner  * @pi: port information structure
51771d10453SEric Joyner  */
51871d10453SEric Joyner static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
51971d10453SEric Joyner {
52071d10453SEric Joyner 	struct ice_link_status *hw_link_info;
52171d10453SEric Joyner 
52271d10453SEric Joyner 	if (!pi)
52371d10453SEric Joyner 		return ICE_MEDIA_UNKNOWN;
52471d10453SEric Joyner 
52571d10453SEric Joyner 	hw_link_info = &pi->phy.link_info;
52671d10453SEric Joyner 	if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
52771d10453SEric Joyner 		/* If more than one media type is selected, report unknown */
52871d10453SEric Joyner 		return ICE_MEDIA_UNKNOWN;
52971d10453SEric Joyner 
53071d10453SEric Joyner 	if (hw_link_info->phy_type_low) {
5317d7af7f8SEric Joyner 		/* 1G SGMII is a special case where some DA cable PHYs
5327d7af7f8SEric Joyner 		 * may show this as an option when it really shouldn't
5337d7af7f8SEric Joyner 		 * be since SGMII is meant to be between a MAC and a PHY
5347d7af7f8SEric Joyner 		 * in a backplane. Try to detect this case and handle it
5357d7af7f8SEric Joyner 		 */
5367d7af7f8SEric Joyner 		if (hw_link_info->phy_type_low == ICE_PHY_TYPE_LOW_1G_SGMII &&
5377d7af7f8SEric Joyner 		    (hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
5387d7af7f8SEric Joyner 		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
5397d7af7f8SEric Joyner 		    hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
5407d7af7f8SEric Joyner 		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
5417d7af7f8SEric Joyner 			return ICE_MEDIA_DA;
5427d7af7f8SEric Joyner 
54371d10453SEric Joyner 		switch (hw_link_info->phy_type_low) {
54471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_SX:
54571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_LX:
54671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_SR:
54771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_LR:
54871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
54971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_SR:
55071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_LR:
55171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_SR4:
55271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_LR4:
55371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_SR2:
55471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_LR2:
55571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_SR:
55671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_FR:
55771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_LR:
55871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_SR4:
55971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_LR4:
56071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_SR2:
56171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_DR:
56271d10453SEric Joyner 			return ICE_MEDIA_FIBER;
5637d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
5647d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
5657d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
5667d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
5677d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
5687d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
5697d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
5707d7af7f8SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
5717d7af7f8SEric Joyner 			return ICE_MEDIA_FIBER;
57271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100BASE_TX:
57371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_T:
57471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_2500BASE_T:
57571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_5GBASE_T:
57671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_T:
57771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_T:
57871d10453SEric Joyner 			return ICE_MEDIA_BASET;
57971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10G_SFI_DA:
58071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_CR:
58171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
58271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_CR1:
58371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_CR4:
58471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_CR2:
58571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_CP:
58671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_CR4:
58771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
58871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_CP2:
58971d10453SEric Joyner 			return ICE_MEDIA_DA;
59071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
59171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40G_XLAUI:
59271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_LAUI2:
59371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI2:
59471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50G_AUI1:
59571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_AUI4:
59671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100G_CAUI4:
59771d10453SEric Joyner 			if (ice_is_media_cage_present(pi))
5987d7af7f8SEric Joyner 				return ICE_MEDIA_AUI;
59971d10453SEric Joyner 			/* fall-through */
60071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_1000BASE_KX:
60171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_2500BASE_KX:
60271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_2500BASE_X:
60371d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_5GBASE_KR:
60471d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
60571d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_KR:
60671d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_KR1:
60771d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
60871d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_40GBASE_KR4:
60971d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
61071d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_50GBASE_KR2:
61171d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_KR4:
61271d10453SEric Joyner 		case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
61371d10453SEric Joyner 			return ICE_MEDIA_BACKPLANE;
61471d10453SEric Joyner 		}
61571d10453SEric Joyner 	} else {
61671d10453SEric Joyner 		switch (hw_link_info->phy_type_high) {
61771d10453SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_AUI2:
6187d7af7f8SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_CAUI2:
61971d10453SEric Joyner 			if (ice_is_media_cage_present(pi))
6207d7af7f8SEric Joyner 				return ICE_MEDIA_AUI;
62171d10453SEric Joyner 			/* fall-through */
62271d10453SEric Joyner 		case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
62371d10453SEric Joyner 			return ICE_MEDIA_BACKPLANE;
6247d7af7f8SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
6257d7af7f8SEric Joyner 		case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
6267d7af7f8SEric Joyner 			return ICE_MEDIA_FIBER;
62771d10453SEric Joyner 		}
62871d10453SEric Joyner 	}
62971d10453SEric Joyner 	return ICE_MEDIA_UNKNOWN;
63071d10453SEric Joyner }
63171d10453SEric Joyner 
63271d10453SEric Joyner /**
63371d10453SEric Joyner  * ice_aq_get_link_info
63471d10453SEric Joyner  * @pi: port information structure
63571d10453SEric Joyner  * @ena_lse: enable/disable LinkStatusEvent reporting
63671d10453SEric Joyner  * @link: pointer to link status structure - optional
63771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
63871d10453SEric Joyner  *
63971d10453SEric Joyner  * Get Link Status (0x607). Returns the link status of the adapter.
64071d10453SEric Joyner  */
64171d10453SEric Joyner enum ice_status
64271d10453SEric Joyner ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
64371d10453SEric Joyner 		     struct ice_link_status *link, struct ice_sq_cd *cd)
64471d10453SEric Joyner {
64571d10453SEric Joyner 	struct ice_aqc_get_link_status_data link_data = { 0 };
64671d10453SEric Joyner 	struct ice_aqc_get_link_status *resp;
64771d10453SEric Joyner 	struct ice_link_status *li_old, *li;
64871d10453SEric Joyner 	enum ice_media_type *hw_media_type;
64971d10453SEric Joyner 	struct ice_fc_info *hw_fc_info;
65071d10453SEric Joyner 	bool tx_pause, rx_pause;
65171d10453SEric Joyner 	struct ice_aq_desc desc;
65271d10453SEric Joyner 	enum ice_status status;
65371d10453SEric Joyner 	struct ice_hw *hw;
65471d10453SEric Joyner 	u16 cmd_flags;
65571d10453SEric Joyner 
65671d10453SEric Joyner 	if (!pi)
65771d10453SEric Joyner 		return ICE_ERR_PARAM;
65871d10453SEric Joyner 	hw = pi->hw;
65971d10453SEric Joyner 
66071d10453SEric Joyner 	li_old = &pi->phy.link_info_old;
66171d10453SEric Joyner 	hw_media_type = &pi->phy.media_type;
66271d10453SEric Joyner 	li = &pi->phy.link_info;
66371d10453SEric Joyner 	hw_fc_info = &pi->fc;
66471d10453SEric Joyner 
66571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
66671d10453SEric Joyner 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
66771d10453SEric Joyner 	resp = &desc.params.get_link_status;
66871d10453SEric Joyner 	resp->cmd_flags = CPU_TO_LE16(cmd_flags);
66971d10453SEric Joyner 	resp->lport_num = pi->lport;
67071d10453SEric Joyner 
67171d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);
67271d10453SEric Joyner 
67371d10453SEric Joyner 	if (status != ICE_SUCCESS)
67471d10453SEric Joyner 		return status;
67571d10453SEric Joyner 
67671d10453SEric Joyner 	/* save off old link status information */
67771d10453SEric Joyner 	*li_old = *li;
67871d10453SEric Joyner 
67971d10453SEric Joyner 	/* update current link status information */
68071d10453SEric Joyner 	li->link_speed = LE16_TO_CPU(link_data.link_speed);
68171d10453SEric Joyner 	li->phy_type_low = LE64_TO_CPU(link_data.phy_type_low);
68271d10453SEric Joyner 	li->phy_type_high = LE64_TO_CPU(link_data.phy_type_high);
68371d10453SEric Joyner 	*hw_media_type = ice_get_media_type(pi);
68471d10453SEric Joyner 	li->link_info = link_data.link_info;
6859cf1841cSEric Joyner 	li->link_cfg_err = link_data.link_cfg_err;
68671d10453SEric Joyner 	li->an_info = link_data.an_info;
68771d10453SEric Joyner 	li->ext_info = link_data.ext_info;
68871d10453SEric Joyner 	li->max_frame_size = LE16_TO_CPU(link_data.max_frame_size);
68971d10453SEric Joyner 	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
69071d10453SEric Joyner 	li->topo_media_conflict = link_data.topo_media_conflict;
69171d10453SEric Joyner 	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
69271d10453SEric Joyner 				      ICE_AQ_CFG_PACING_TYPE_M);
69371d10453SEric Joyner 
69471d10453SEric Joyner 	/* update fc info */
69571d10453SEric Joyner 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
69671d10453SEric Joyner 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
69771d10453SEric Joyner 	if (tx_pause && rx_pause)
69871d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_FULL;
69971d10453SEric Joyner 	else if (tx_pause)
70071d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
70171d10453SEric Joyner 	else if (rx_pause)
70271d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
70371d10453SEric Joyner 	else
70471d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_NONE;
70571d10453SEric Joyner 
70671d10453SEric Joyner 	li->lse_ena = !!(resp->cmd_flags & CPU_TO_LE16(ICE_AQ_LSE_IS_ENABLED));
70771d10453SEric Joyner 
7087d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get link info\n");
70971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_speed = 0x%x\n", li->link_speed);
71071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
71171d10453SEric Joyner 		  (unsigned long long)li->phy_type_low);
71271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
71371d10453SEric Joyner 		  (unsigned long long)li->phy_type_high);
71471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	media_type = 0x%x\n", *hw_media_type);
71571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_info = 0x%x\n", li->link_info);
716*56429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_cfg_err = 0x%x\n", li->link_cfg_err);
71771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	an_info = 0x%x\n", li->an_info);
71871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	ext_info = 0x%x\n", li->ext_info);
7197d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	fec_info = 0x%x\n", li->fec_info);
72071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	lse_ena = 0x%x\n", li->lse_ena);
7217d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	max_frame = 0x%x\n",
7227d7af7f8SEric Joyner 		  li->max_frame_size);
72371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	pacing = 0x%x\n", li->pacing);
72471d10453SEric Joyner 
72571d10453SEric Joyner 	/* save link status information */
72671d10453SEric Joyner 	if (link)
72771d10453SEric Joyner 		*link = *li;
72871d10453SEric Joyner 
72971d10453SEric Joyner 	/* flag cleared so calling functions don't call AQ again */
73071d10453SEric Joyner 	pi->phy.get_link_info = false;
73171d10453SEric Joyner 
73271d10453SEric Joyner 	return ICE_SUCCESS;
73371d10453SEric Joyner }
73471d10453SEric Joyner 
73571d10453SEric Joyner /**
7367d7af7f8SEric Joyner  * ice_fill_tx_timer_and_fc_thresh
73771d10453SEric Joyner  * @hw: pointer to the HW struct
7387d7af7f8SEric Joyner  * @cmd: pointer to MAC cfg structure
73971d10453SEric Joyner  *
7407d7af7f8SEric Joyner  * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
7417d7af7f8SEric Joyner  * descriptor
74271d10453SEric Joyner  */
7437d7af7f8SEric Joyner static void
7447d7af7f8SEric Joyner ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
7457d7af7f8SEric Joyner 				struct ice_aqc_set_mac_cfg *cmd)
74671d10453SEric Joyner {
7477d7af7f8SEric Joyner 	u16 fc_thres_val, tx_timer_val;
7487d7af7f8SEric Joyner 	u32 val;
74971d10453SEric Joyner 
75071d10453SEric Joyner 	/* We read back the transmit timer and fc threshold value of
75171d10453SEric Joyner 	 * LFC. Thus, we will use index =
75271d10453SEric Joyner 	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
75371d10453SEric Joyner 	 *
754*56429daeSEric Joyner 	 * Also, because we are operating on transmit timer and fc
75571d10453SEric Joyner 	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
75671d10453SEric Joyner 	 */
75771d10453SEric Joyner #define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
75871d10453SEric Joyner 
75971d10453SEric Joyner 	/* Retrieve the transmit timer */
7607d7af7f8SEric Joyner 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
7617d7af7f8SEric Joyner 	tx_timer_val = val &
76271d10453SEric Joyner 		PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
76371d10453SEric Joyner 	cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
76471d10453SEric Joyner 
76571d10453SEric Joyner 	/* Retrieve the fc threshold */
7667d7af7f8SEric Joyner 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
7677d7af7f8SEric Joyner 	fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
7687d7af7f8SEric Joyner 
7697d7af7f8SEric Joyner 	cmd->fc_refresh_threshold = CPU_TO_LE16(fc_thres_val);
7707d7af7f8SEric Joyner }
7717d7af7f8SEric Joyner 
7727d7af7f8SEric Joyner /**
7737d7af7f8SEric Joyner  * ice_aq_set_mac_cfg
7747d7af7f8SEric Joyner  * @hw: pointer to the HW struct
7757d7af7f8SEric Joyner  * @max_frame_size: Maximum Frame Size to be supported
776*56429daeSEric Joyner  * @auto_drop: Tell HW to drop packets if TC queue is blocked
7777d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
7787d7af7f8SEric Joyner  *
7797d7af7f8SEric Joyner  * Set MAC configuration (0x0603)
7807d7af7f8SEric Joyner  */
7817d7af7f8SEric Joyner enum ice_status
782*56429daeSEric Joyner ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,
783*56429daeSEric Joyner 		   struct ice_sq_cd *cd)
7847d7af7f8SEric Joyner {
7857d7af7f8SEric Joyner 	struct ice_aqc_set_mac_cfg *cmd;
7867d7af7f8SEric Joyner 	struct ice_aq_desc desc;
7877d7af7f8SEric Joyner 
7887d7af7f8SEric Joyner 	cmd = &desc.params.set_mac_cfg;
7897d7af7f8SEric Joyner 
7907d7af7f8SEric Joyner 	if (max_frame_size == 0)
7917d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
7927d7af7f8SEric Joyner 
7937d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
7947d7af7f8SEric Joyner 
7957d7af7f8SEric Joyner 	cmd->max_frame_size = CPU_TO_LE16(max_frame_size);
7967d7af7f8SEric Joyner 
797*56429daeSEric Joyner 	if (ice_is_fw_auto_drop_supported(hw) && auto_drop)
798*56429daeSEric Joyner 		cmd->drop_opts |= ICE_AQ_SET_MAC_AUTO_DROP_BLOCKING_PKTS;
7997d7af7f8SEric Joyner 	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
80071d10453SEric Joyner 
80171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
80271d10453SEric Joyner }
80371d10453SEric Joyner 
80471d10453SEric Joyner /**
80571d10453SEric Joyner  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
80671d10453SEric Joyner  * @hw: pointer to the HW struct
80771d10453SEric Joyner  */
80871d10453SEric Joyner static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
80971d10453SEric Joyner {
81071d10453SEric Joyner 	struct ice_switch_info *sw;
8117d7af7f8SEric Joyner 	enum ice_status status;
81271d10453SEric Joyner 
81371d10453SEric Joyner 	hw->switch_info = (struct ice_switch_info *)
81471d10453SEric Joyner 			  ice_malloc(hw, sizeof(*hw->switch_info));
81571d10453SEric Joyner 
81671d10453SEric Joyner 	sw = hw->switch_info;
81771d10453SEric Joyner 
81871d10453SEric Joyner 	if (!sw)
81971d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
82071d10453SEric Joyner 
82171d10453SEric Joyner 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
8227d7af7f8SEric Joyner 	sw->prof_res_bm_init = 0;
82371d10453SEric Joyner 
8247d7af7f8SEric Joyner 	status = ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
8257d7af7f8SEric Joyner 	if (status) {
8267d7af7f8SEric Joyner 		ice_free(hw, hw->switch_info);
8277d7af7f8SEric Joyner 		return status;
8287d7af7f8SEric Joyner 	}
8297d7af7f8SEric Joyner 	return ICE_SUCCESS;
83071d10453SEric Joyner }
83171d10453SEric Joyner 
83271d10453SEric Joyner /**
8337d7af7f8SEric Joyner  * ice_cleanup_fltr_mgmt_single - clears single filter mngt struct
83471d10453SEric Joyner  * @hw: pointer to the HW struct
8357d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function clears filters
83671d10453SEric Joyner  */
8377d7af7f8SEric Joyner static void
8387d7af7f8SEric Joyner ice_cleanup_fltr_mgmt_single(struct ice_hw *hw, struct ice_switch_info *sw)
83971d10453SEric Joyner {
84071d10453SEric Joyner 	struct ice_vsi_list_map_info *v_pos_map;
84171d10453SEric Joyner 	struct ice_vsi_list_map_info *v_tmp_map;
84271d10453SEric Joyner 	struct ice_sw_recipe *recps;
84371d10453SEric Joyner 	u8 i;
84471d10453SEric Joyner 
8457d7af7f8SEric Joyner 	if (!sw)
8467d7af7f8SEric Joyner 		return;
8477d7af7f8SEric Joyner 
84871d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
84971d10453SEric Joyner 				 ice_vsi_list_map_info, list_entry) {
85071d10453SEric Joyner 		LIST_DEL(&v_pos_map->list_entry);
85171d10453SEric Joyner 		ice_free(hw, v_pos_map);
85271d10453SEric Joyner 	}
8537d7af7f8SEric Joyner 	recps = sw->recp_list;
85471d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
85571d10453SEric Joyner 		struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
85671d10453SEric Joyner 
85771d10453SEric Joyner 		recps[i].root_rid = i;
85871d10453SEric Joyner 		LIST_FOR_EACH_ENTRY_SAFE(rg_entry, tmprg_entry,
85971d10453SEric Joyner 					 &recps[i].rg_list, ice_recp_grp_entry,
86071d10453SEric Joyner 					 l_entry) {
86171d10453SEric Joyner 			LIST_DEL(&rg_entry->l_entry);
86271d10453SEric Joyner 			ice_free(hw, rg_entry);
86371d10453SEric Joyner 		}
86471d10453SEric Joyner 
86571d10453SEric Joyner 		if (recps[i].adv_rule) {
86671d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
86771d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *lst_itr;
86871d10453SEric Joyner 
86971d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
87071d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
87171d10453SEric Joyner 						 &recps[i].filt_rules,
87271d10453SEric Joyner 						 ice_adv_fltr_mgmt_list_entry,
87371d10453SEric Joyner 						 list_entry) {
87471d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
87571d10453SEric Joyner 				ice_free(hw, lst_itr->lkups);
87671d10453SEric Joyner 				ice_free(hw, lst_itr);
87771d10453SEric Joyner 			}
87871d10453SEric Joyner 		} else {
87971d10453SEric Joyner 			struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
88071d10453SEric Joyner 
88171d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
88271d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
88371d10453SEric Joyner 						 &recps[i].filt_rules,
88471d10453SEric Joyner 						 ice_fltr_mgmt_list_entry,
88571d10453SEric Joyner 						 list_entry) {
88671d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
88771d10453SEric Joyner 				ice_free(hw, lst_itr);
88871d10453SEric Joyner 			}
88971d10453SEric Joyner 		}
89071d10453SEric Joyner 		if (recps[i].root_buf)
89171d10453SEric Joyner 			ice_free(hw, recps[i].root_buf);
89271d10453SEric Joyner 	}
8937d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
89471d10453SEric Joyner 	ice_free(hw, sw->recp_list);
89571d10453SEric Joyner 	ice_free(hw, sw);
89671d10453SEric Joyner }
89771d10453SEric Joyner 
89871d10453SEric Joyner /**
899*56429daeSEric Joyner  * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
9007d7af7f8SEric Joyner  * @hw: pointer to the HW struct
9017d7af7f8SEric Joyner  */
9027d7af7f8SEric Joyner static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
9037d7af7f8SEric Joyner {
9047d7af7f8SEric Joyner 	ice_cleanup_fltr_mgmt_single(hw, hw->switch_info);
9057d7af7f8SEric Joyner }
9067d7af7f8SEric Joyner 
9077d7af7f8SEric Joyner /**
90871d10453SEric Joyner  * ice_get_itr_intrl_gran
90971d10453SEric Joyner  * @hw: pointer to the HW struct
91071d10453SEric Joyner  *
91171d10453SEric Joyner  * Determines the ITR/INTRL granularities based on the maximum aggregate
91271d10453SEric Joyner  * bandwidth according to the device's configuration during power-on.
91371d10453SEric Joyner  */
91471d10453SEric Joyner static void ice_get_itr_intrl_gran(struct ice_hw *hw)
91571d10453SEric Joyner {
91671d10453SEric Joyner 	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
91771d10453SEric Joyner 			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
91871d10453SEric Joyner 			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
91971d10453SEric Joyner 
92071d10453SEric Joyner 	switch (max_agg_bw) {
92171d10453SEric Joyner 	case ICE_MAX_AGG_BW_200G:
92271d10453SEric Joyner 	case ICE_MAX_AGG_BW_100G:
92371d10453SEric Joyner 	case ICE_MAX_AGG_BW_50G:
92471d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
92571d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
92671d10453SEric Joyner 		break;
92771d10453SEric Joyner 	case ICE_MAX_AGG_BW_25G:
92871d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
92971d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
93071d10453SEric Joyner 		break;
93171d10453SEric Joyner 	}
93271d10453SEric Joyner }
93371d10453SEric Joyner 
93471d10453SEric Joyner /**
93571d10453SEric Joyner  * ice_print_rollback_msg - print FW rollback message
93671d10453SEric Joyner  * @hw: pointer to the hardware structure
93771d10453SEric Joyner  */
93871d10453SEric Joyner void ice_print_rollback_msg(struct ice_hw *hw)
93971d10453SEric Joyner {
94071d10453SEric Joyner 	char nvm_str[ICE_NVM_VER_LEN] = { 0 };
94171d10453SEric Joyner 	struct ice_orom_info *orom;
942d08b8680SEric Joyner 	struct ice_nvm_info *nvm;
94371d10453SEric Joyner 
944d08b8680SEric Joyner 	orom = &hw->flash.orom;
945d08b8680SEric Joyner 	nvm = &hw->flash.nvm;
94671d10453SEric Joyner 
94771d10453SEric Joyner 	SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d",
948d08b8680SEric Joyner 		 nvm->major, nvm->minor, nvm->eetrack, orom->major,
94971d10453SEric Joyner 		 orom->build, orom->patch);
95071d10453SEric Joyner 	ice_warn(hw,
95171d10453SEric 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",
95271d10453SEric Joyner 		 nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
95371d10453SEric Joyner }
95471d10453SEric Joyner 
95571d10453SEric Joyner /**
956*56429daeSEric Joyner  * ice_set_umac_shared
957*56429daeSEric Joyner  * @hw: pointer to the hw struct
958*56429daeSEric Joyner  *
959*56429daeSEric Joyner  * Set boolean flag to allow unicast MAC sharing
960*56429daeSEric Joyner  */
961*56429daeSEric Joyner void ice_set_umac_shared(struct ice_hw *hw)
962*56429daeSEric Joyner {
963*56429daeSEric Joyner 	hw->umac_shared = true;
964*56429daeSEric Joyner }
965*56429daeSEric Joyner 
966*56429daeSEric Joyner /**
96771d10453SEric Joyner  * ice_init_hw - main hardware initialization routine
96871d10453SEric Joyner  * @hw: pointer to the hardware structure
96971d10453SEric Joyner  */
97071d10453SEric Joyner enum ice_status ice_init_hw(struct ice_hw *hw)
97171d10453SEric Joyner {
97271d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
97371d10453SEric Joyner 	enum ice_status status;
97471d10453SEric Joyner 	u16 mac_buf_len;
97571d10453SEric Joyner 	void *mac_buf;
97671d10453SEric Joyner 
97771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
97871d10453SEric Joyner 
97971d10453SEric Joyner 	/* Set MAC type based on DeviceID */
98071d10453SEric Joyner 	status = ice_set_mac_type(hw);
98171d10453SEric Joyner 	if (status)
98271d10453SEric Joyner 		return status;
98371d10453SEric Joyner 
98471d10453SEric Joyner 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
98571d10453SEric Joyner 			 PF_FUNC_RID_FUNCTION_NUMBER_M) >>
98671d10453SEric Joyner 		PF_FUNC_RID_FUNCTION_NUMBER_S;
98771d10453SEric Joyner 
98871d10453SEric Joyner 	status = ice_reset(hw, ICE_RESET_PFR);
98971d10453SEric Joyner 	if (status)
99071d10453SEric Joyner 		return status;
99171d10453SEric Joyner 	ice_get_itr_intrl_gran(hw);
99271d10453SEric Joyner 
99371d10453SEric Joyner 	status = ice_create_all_ctrlq(hw);
99471d10453SEric Joyner 	if (status)
99571d10453SEric Joyner 		goto err_unroll_cqinit;
99671d10453SEric Joyner 
997*56429daeSEric Joyner 	ice_fwlog_set_support_ena(hw);
998*56429daeSEric Joyner 	status = ice_fwlog_set(hw, &hw->fwlog_cfg);
999*56429daeSEric Joyner 	if (status) {
1000*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging, status %d.\n",
1001*56429daeSEric Joyner 			  status);
1002*56429daeSEric Joyner 	} else {
1003*56429daeSEric Joyner 		if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_REGISTER_ON_INIT) {
1004*56429daeSEric Joyner 			status = ice_fwlog_register(hw);
1005*56429daeSEric Joyner 			if (status)
1006*56429daeSEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "Failed to register for FW logging events, status %d.\n",
1007*56429daeSEric Joyner 					  status);
1008*56429daeSEric Joyner 		} else {
1009*56429daeSEric Joyner 			status = ice_fwlog_unregister(hw);
1010*56429daeSEric Joyner 			if (status)
1011*56429daeSEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "Failed to unregister for FW logging events, status %d.\n",
1012*56429daeSEric Joyner 					  status);
1013*56429daeSEric Joyner 		}
1014*56429daeSEric Joyner 	}
1015*56429daeSEric Joyner 
101671d10453SEric Joyner 	status = ice_init_nvm(hw);
101771d10453SEric Joyner 	if (status)
101871d10453SEric Joyner 		goto err_unroll_cqinit;
101971d10453SEric Joyner 
102071d10453SEric Joyner 	if (ice_get_fw_mode(hw) == ICE_FW_MODE_ROLLBACK)
102171d10453SEric Joyner 		ice_print_rollback_msg(hw);
102271d10453SEric Joyner 
102371d10453SEric Joyner 	status = ice_clear_pf_cfg(hw);
102471d10453SEric Joyner 	if (status)
102571d10453SEric Joyner 		goto err_unroll_cqinit;
102671d10453SEric Joyner 
102771d10453SEric Joyner 	ice_clear_pxe_mode(hw);
102871d10453SEric Joyner 
102971d10453SEric Joyner 	status = ice_get_caps(hw);
103071d10453SEric Joyner 	if (status)
103171d10453SEric Joyner 		goto err_unroll_cqinit;
103271d10453SEric Joyner 
103371d10453SEric Joyner 	hw->port_info = (struct ice_port_info *)
103471d10453SEric Joyner 			ice_malloc(hw, sizeof(*hw->port_info));
103571d10453SEric Joyner 	if (!hw->port_info) {
103671d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
103771d10453SEric Joyner 		goto err_unroll_cqinit;
103871d10453SEric Joyner 	}
103971d10453SEric Joyner 
104071d10453SEric Joyner 	/* set the back pointer to HW */
104171d10453SEric Joyner 	hw->port_info->hw = hw;
104271d10453SEric Joyner 
104371d10453SEric Joyner 	/* Initialize port_info struct with switch configuration data */
104471d10453SEric Joyner 	status = ice_get_initial_sw_cfg(hw);
104571d10453SEric Joyner 	if (status)
104671d10453SEric Joyner 		goto err_unroll_alloc;
104771d10453SEric Joyner 
104871d10453SEric Joyner 	hw->evb_veb = true;
104971d10453SEric Joyner 	/* Query the allocated resources for Tx scheduler */
105071d10453SEric Joyner 	status = ice_sched_query_res_alloc(hw);
105171d10453SEric Joyner 	if (status) {
10527d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
105371d10453SEric Joyner 		goto err_unroll_alloc;
105471d10453SEric Joyner 	}
105571d10453SEric Joyner 	ice_sched_get_psm_clk_freq(hw);
105671d10453SEric Joyner 
105771d10453SEric Joyner 	/* Initialize port_info struct with scheduler data */
105871d10453SEric Joyner 	status = ice_sched_init_port(hw->port_info);
105971d10453SEric Joyner 	if (status)
106071d10453SEric Joyner 		goto err_unroll_sched;
106171d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
106271d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
106371d10453SEric Joyner 	if (!pcaps) {
106471d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
106571d10453SEric Joyner 		goto err_unroll_sched;
106671d10453SEric Joyner 	}
106771d10453SEric Joyner 
106871d10453SEric Joyner 	/* Initialize port_info struct with PHY capabilities */
106971d10453SEric Joyner 	status = ice_aq_get_phy_caps(hw->port_info, false,
10709cf1841cSEric Joyner 				     ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, NULL);
107171d10453SEric Joyner 	ice_free(hw, pcaps);
107271d10453SEric Joyner 	if (status)
10739cf1841cSEric Joyner 		ice_warn(hw, "Get PHY capabilities failed status = %d, continuing anyway\n",
10749cf1841cSEric Joyner 			 status);
107571d10453SEric Joyner 
107671d10453SEric Joyner 	/* Initialize port_info struct with link information */
107771d10453SEric Joyner 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
107871d10453SEric Joyner 	if (status)
107971d10453SEric Joyner 		goto err_unroll_sched;
108071d10453SEric Joyner 	/* need a valid SW entry point to build a Tx tree */
108171d10453SEric Joyner 	if (!hw->sw_entry_point_layer) {
108271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
108371d10453SEric Joyner 		status = ICE_ERR_CFG;
108471d10453SEric Joyner 		goto err_unroll_sched;
108571d10453SEric Joyner 	}
108671d10453SEric Joyner 	INIT_LIST_HEAD(&hw->agg_list);
108771d10453SEric Joyner 	/* Initialize max burst size */
108871d10453SEric Joyner 	if (!hw->max_burst_size)
108971d10453SEric Joyner 		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
109071d10453SEric Joyner 	status = ice_init_fltr_mgmt_struct(hw);
109171d10453SEric Joyner 	if (status)
109271d10453SEric Joyner 		goto err_unroll_sched;
109371d10453SEric Joyner 
109471d10453SEric Joyner 	/* Get MAC information */
1095*56429daeSEric Joyner 
109671d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
109771d10453SEric Joyner 	mac_buf = ice_calloc(hw, 2,
109871d10453SEric Joyner 			     sizeof(struct ice_aqc_manage_mac_read_resp));
109971d10453SEric Joyner 	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
110071d10453SEric Joyner 
110171d10453SEric Joyner 	if (!mac_buf) {
110271d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
110371d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
110471d10453SEric Joyner 	}
110571d10453SEric Joyner 
110671d10453SEric Joyner 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
110771d10453SEric Joyner 	ice_free(hw, mac_buf);
110871d10453SEric Joyner 
110971d10453SEric Joyner 	if (status)
111071d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
1111*56429daeSEric Joyner 
11127d7af7f8SEric Joyner 	/* enable jumbo frame support at MAC level */
1113*56429daeSEric Joyner 	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, false,
1114*56429daeSEric Joyner 				    NULL);
11157d7af7f8SEric Joyner 	if (status)
11167d7af7f8SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
1117*56429daeSEric Joyner 
111871d10453SEric Joyner 	status = ice_init_hw_tbls(hw);
111971d10453SEric Joyner 	if (status)
112071d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
112171d10453SEric Joyner 	ice_init_lock(&hw->tnl_lock);
1122d08b8680SEric Joyner 
112371d10453SEric Joyner 	return ICE_SUCCESS;
112471d10453SEric Joyner 
112571d10453SEric Joyner err_unroll_fltr_mgmt_struct:
112671d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
112771d10453SEric Joyner err_unroll_sched:
112871d10453SEric Joyner 	ice_sched_cleanup_all(hw);
112971d10453SEric Joyner err_unroll_alloc:
113071d10453SEric Joyner 	ice_free(hw, hw->port_info);
113171d10453SEric Joyner 	hw->port_info = NULL;
113271d10453SEric Joyner err_unroll_cqinit:
113371d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
113471d10453SEric Joyner 	return status;
113571d10453SEric Joyner }
113671d10453SEric Joyner 
113771d10453SEric Joyner /**
113871d10453SEric Joyner  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
113971d10453SEric Joyner  * @hw: pointer to the hardware structure
114071d10453SEric Joyner  *
114171d10453SEric Joyner  * This should be called only during nominal operation, not as a result of
114271d10453SEric Joyner  * ice_init_hw() failing since ice_init_hw() will take care of unrolling
114371d10453SEric Joyner  * applicable initializations if it fails for any reason.
114471d10453SEric Joyner  */
114571d10453SEric Joyner void ice_deinit_hw(struct ice_hw *hw)
114671d10453SEric Joyner {
114771d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
114871d10453SEric Joyner 
114971d10453SEric Joyner 	ice_sched_cleanup_all(hw);
115071d10453SEric Joyner 	ice_sched_clear_agg(hw);
115171d10453SEric Joyner 	ice_free_seg(hw);
115271d10453SEric Joyner 	ice_free_hw_tbls(hw);
115371d10453SEric Joyner 	ice_destroy_lock(&hw->tnl_lock);
115471d10453SEric Joyner 
115571d10453SEric Joyner 	if (hw->port_info) {
115671d10453SEric Joyner 		ice_free(hw, hw->port_info);
115771d10453SEric Joyner 		hw->port_info = NULL;
115871d10453SEric Joyner 	}
115971d10453SEric Joyner 
116071d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
116171d10453SEric Joyner 
116271d10453SEric Joyner 	/* Clear VSI contexts if not already cleared */
116371d10453SEric Joyner 	ice_clear_all_vsi_ctx(hw);
116471d10453SEric Joyner }
116571d10453SEric Joyner 
116671d10453SEric Joyner /**
116771d10453SEric Joyner  * ice_check_reset - Check to see if a global reset is complete
116871d10453SEric Joyner  * @hw: pointer to the hardware structure
116971d10453SEric Joyner  */
117071d10453SEric Joyner enum ice_status ice_check_reset(struct ice_hw *hw)
117171d10453SEric Joyner {
11727d7af7f8SEric Joyner 	u32 cnt, reg = 0, grst_timeout, uld_mask;
117371d10453SEric Joyner 
117471d10453SEric Joyner 	/* Poll for Device Active state in case a recent CORER, GLOBR,
117571d10453SEric Joyner 	 * or EMPR has occurred. The grst delay value is in 100ms units.
117671d10453SEric Joyner 	 * Add 1sec for outstanding AQ commands that can take a long time.
117771d10453SEric Joyner 	 */
11787d7af7f8SEric Joyner 	grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
117971d10453SEric Joyner 			GLGEN_RSTCTL_GRSTDEL_S) + 10;
118071d10453SEric Joyner 
11817d7af7f8SEric Joyner 	for (cnt = 0; cnt < grst_timeout; cnt++) {
118271d10453SEric Joyner 		ice_msec_delay(100, true);
118371d10453SEric Joyner 		reg = rd32(hw, GLGEN_RSTAT);
118471d10453SEric Joyner 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
118571d10453SEric Joyner 			break;
118671d10453SEric Joyner 	}
118771d10453SEric Joyner 
11887d7af7f8SEric Joyner 	if (cnt == grst_timeout) {
11897d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n");
119071d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
119171d10453SEric Joyner 	}
119271d10453SEric Joyner 
119371d10453SEric Joyner #define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
119471d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_1_M |\
119571d10453SEric Joyner 				 GLNVM_ULD_CORER_DONE_M |\
119671d10453SEric Joyner 				 GLNVM_ULD_GLOBR_DONE_M |\
119771d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_M |\
119871d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_1_M |\
119971d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_2_M)
120071d10453SEric Joyner 
120171d10453SEric Joyner 	uld_mask = ICE_RESET_DONE_MASK;
120271d10453SEric Joyner 
120371d10453SEric Joyner 	/* Device is Active; check Global Reset processes are done */
120471d10453SEric Joyner 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
120571d10453SEric Joyner 		reg = rd32(hw, GLNVM_ULD) & uld_mask;
120671d10453SEric Joyner 		if (reg == uld_mask) {
12077d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt);
120871d10453SEric Joyner 			break;
120971d10453SEric Joyner 		}
121071d10453SEric Joyner 		ice_msec_delay(10, true);
121171d10453SEric Joyner 	}
121271d10453SEric Joyner 
121371d10453SEric Joyner 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
12147d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
121571d10453SEric Joyner 			  reg);
121671d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
121771d10453SEric Joyner 	}
121871d10453SEric Joyner 
121971d10453SEric Joyner 	return ICE_SUCCESS;
122071d10453SEric Joyner }
122171d10453SEric Joyner 
122271d10453SEric Joyner /**
122371d10453SEric Joyner  * ice_pf_reset - Reset the PF
122471d10453SEric Joyner  * @hw: pointer to the hardware structure
122571d10453SEric Joyner  *
122671d10453SEric Joyner  * If a global reset has been triggered, this function checks
122771d10453SEric Joyner  * for its completion and then issues the PF reset
122871d10453SEric Joyner  */
122971d10453SEric Joyner static enum ice_status ice_pf_reset(struct ice_hw *hw)
123071d10453SEric Joyner {
123171d10453SEric Joyner 	u32 cnt, reg;
123271d10453SEric Joyner 
123371d10453SEric Joyner 	/* If at function entry a global reset was already in progress, i.e.
123471d10453SEric Joyner 	 * state is not 'device active' or any of the reset done bits are not
123571d10453SEric Joyner 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
123671d10453SEric Joyner 	 * global reset is done.
123771d10453SEric Joyner 	 */
123871d10453SEric Joyner 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
123971d10453SEric Joyner 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
124071d10453SEric Joyner 		/* poll on global reset currently in progress until done */
124171d10453SEric Joyner 		if (ice_check_reset(hw))
124271d10453SEric Joyner 			return ICE_ERR_RESET_FAILED;
124371d10453SEric Joyner 
124471d10453SEric Joyner 		return ICE_SUCCESS;
124571d10453SEric Joyner 	}
124671d10453SEric Joyner 
124771d10453SEric Joyner 	/* Reset the PF */
124871d10453SEric Joyner 	reg = rd32(hw, PFGEN_CTRL);
124971d10453SEric Joyner 
125071d10453SEric Joyner 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
125171d10453SEric Joyner 
12527d7af7f8SEric Joyner 	/* Wait for the PFR to complete. The wait time is the global config lock
12537d7af7f8SEric Joyner 	 * timeout plus the PFR timeout which will account for a possible reset
12547d7af7f8SEric Joyner 	 * that is occurring during a download package operation.
12557d7af7f8SEric Joyner 	 */
12567d7af7f8SEric Joyner 	for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT +
12577d7af7f8SEric Joyner 	     ICE_PF_RESET_WAIT_COUNT; cnt++) {
125871d10453SEric Joyner 		reg = rd32(hw, PFGEN_CTRL);
125971d10453SEric Joyner 		if (!(reg & PFGEN_CTRL_PFSWR_M))
126071d10453SEric Joyner 			break;
126171d10453SEric Joyner 
126271d10453SEric Joyner 		ice_msec_delay(1, true);
126371d10453SEric Joyner 	}
126471d10453SEric Joyner 
126571d10453SEric Joyner 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
12667d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n");
126771d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
126871d10453SEric Joyner 	}
126971d10453SEric Joyner 
127071d10453SEric Joyner 	return ICE_SUCCESS;
127171d10453SEric Joyner }
127271d10453SEric Joyner 
127371d10453SEric Joyner /**
127471d10453SEric Joyner  * ice_reset - Perform different types of reset
127571d10453SEric Joyner  * @hw: pointer to the hardware structure
127671d10453SEric Joyner  * @req: reset request
127771d10453SEric Joyner  *
127871d10453SEric Joyner  * This function triggers a reset as specified by the req parameter.
127971d10453SEric Joyner  *
128071d10453SEric Joyner  * Note:
128171d10453SEric Joyner  * If anything other than a PF reset is triggered, PXE mode is restored.
128271d10453SEric Joyner  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
128371d10453SEric Joyner  * interface has been restored in the rebuild flow.
128471d10453SEric Joyner  */
128571d10453SEric Joyner enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
128671d10453SEric Joyner {
128771d10453SEric Joyner 	u32 val = 0;
128871d10453SEric Joyner 
128971d10453SEric Joyner 	switch (req) {
129071d10453SEric Joyner 	case ICE_RESET_PFR:
129171d10453SEric Joyner 		return ice_pf_reset(hw);
129271d10453SEric Joyner 	case ICE_RESET_CORER:
129371d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
129471d10453SEric Joyner 		val = GLGEN_RTRIG_CORER_M;
129571d10453SEric Joyner 		break;
129671d10453SEric Joyner 	case ICE_RESET_GLOBR:
129771d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
129871d10453SEric Joyner 		val = GLGEN_RTRIG_GLOBR_M;
129971d10453SEric Joyner 		break;
130071d10453SEric Joyner 	default:
130171d10453SEric Joyner 		return ICE_ERR_PARAM;
130271d10453SEric Joyner 	}
130371d10453SEric Joyner 
130471d10453SEric Joyner 	val |= rd32(hw, GLGEN_RTRIG);
130571d10453SEric Joyner 	wr32(hw, GLGEN_RTRIG, val);
130671d10453SEric Joyner 	ice_flush(hw);
130771d10453SEric Joyner 
130871d10453SEric Joyner 	/* wait for the FW to be ready */
130971d10453SEric Joyner 	return ice_check_reset(hw);
131071d10453SEric Joyner }
131171d10453SEric Joyner 
131271d10453SEric Joyner /**
131371d10453SEric Joyner  * ice_copy_rxq_ctx_to_hw
131471d10453SEric Joyner  * @hw: pointer to the hardware structure
131571d10453SEric Joyner  * @ice_rxq_ctx: pointer to the rxq context
131671d10453SEric Joyner  * @rxq_index: the index of the Rx queue
131771d10453SEric Joyner  *
131871d10453SEric Joyner  * Copies rxq context from dense structure to HW register space
131971d10453SEric Joyner  */
132071d10453SEric Joyner static enum ice_status
132171d10453SEric Joyner ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
132271d10453SEric Joyner {
132371d10453SEric Joyner 	u8 i;
132471d10453SEric Joyner 
132571d10453SEric Joyner 	if (!ice_rxq_ctx)
132671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
132771d10453SEric Joyner 
132871d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
132971d10453SEric Joyner 		return ICE_ERR_PARAM;
133071d10453SEric Joyner 
133171d10453SEric Joyner 	/* Copy each dword separately to HW */
133271d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
133371d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index),
133471d10453SEric Joyner 		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
133571d10453SEric Joyner 
133671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
133771d10453SEric Joyner 			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
133871d10453SEric Joyner 	}
133971d10453SEric Joyner 
134071d10453SEric Joyner 	return ICE_SUCCESS;
134171d10453SEric Joyner }
134271d10453SEric Joyner 
134371d10453SEric Joyner /* LAN Rx Queue Context */
134471d10453SEric Joyner static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
134571d10453SEric Joyner 	/* Field		Width	LSB */
134671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
134771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
134871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
134971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
135071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
135171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
135271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
135371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
135471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
135571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
135671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
135771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
135871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
135971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
136071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
136171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
136271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
136371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
136471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
136571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
136671d10453SEric Joyner 	{ 0 }
136771d10453SEric Joyner };
136871d10453SEric Joyner 
136971d10453SEric Joyner /**
137071d10453SEric Joyner  * ice_write_rxq_ctx
137171d10453SEric Joyner  * @hw: pointer to the hardware structure
137271d10453SEric Joyner  * @rlan_ctx: pointer to the rxq context
137371d10453SEric Joyner  * @rxq_index: the index of the Rx queue
137471d10453SEric Joyner  *
137571d10453SEric Joyner  * Converts rxq context from sparse to dense structure and then writes
137671d10453SEric Joyner  * it to HW register space and enables the hardware to prefetch descriptors
137771d10453SEric Joyner  * instead of only fetching them on demand
137871d10453SEric Joyner  */
137971d10453SEric Joyner enum ice_status
138071d10453SEric Joyner ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
138171d10453SEric Joyner 		  u32 rxq_index)
138271d10453SEric Joyner {
138371d10453SEric Joyner 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
138471d10453SEric Joyner 
138571d10453SEric Joyner 	if (!rlan_ctx)
138671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
138771d10453SEric Joyner 
138871d10453SEric Joyner 	rlan_ctx->prefena = 1;
138971d10453SEric Joyner 
13907d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
139171d10453SEric Joyner 	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
139271d10453SEric Joyner }
139371d10453SEric Joyner 
139471d10453SEric Joyner /**
139571d10453SEric Joyner  * ice_clear_rxq_ctx
139671d10453SEric Joyner  * @hw: pointer to the hardware structure
139771d10453SEric Joyner  * @rxq_index: the index of the Rx queue to clear
139871d10453SEric Joyner  *
139971d10453SEric Joyner  * Clears rxq context in HW register space
140071d10453SEric Joyner  */
140171d10453SEric Joyner enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index)
140271d10453SEric Joyner {
140371d10453SEric Joyner 	u8 i;
140471d10453SEric Joyner 
140571d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
140671d10453SEric Joyner 		return ICE_ERR_PARAM;
140771d10453SEric Joyner 
140871d10453SEric Joyner 	/* Clear each dword register separately */
140971d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++)
141071d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index), 0);
141171d10453SEric Joyner 
141271d10453SEric Joyner 	return ICE_SUCCESS;
141371d10453SEric Joyner }
141471d10453SEric Joyner 
141571d10453SEric Joyner /* LAN Tx Queue Context */
141671d10453SEric Joyner const struct ice_ctx_ele ice_tlan_ctx_info[] = {
141771d10453SEric Joyner 				    /* Field			Width	LSB */
141871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
141971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
142071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
142171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
142271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
142371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
142471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
142571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
142671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
142771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
142871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
142971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
143071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
143171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
143271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
143371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
143471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
143571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
143671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
143771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
143871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
143971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
144071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
144171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
144271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
144371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
144471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
144571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
144671d10453SEric Joyner 	{ 0 }
144771d10453SEric Joyner };
144871d10453SEric Joyner 
144971d10453SEric Joyner /**
145071d10453SEric Joyner  * ice_copy_tx_cmpltnq_ctx_to_hw
145171d10453SEric Joyner  * @hw: pointer to the hardware structure
145271d10453SEric Joyner  * @ice_tx_cmpltnq_ctx: pointer to the Tx completion queue context
145371d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
145471d10453SEric Joyner  *
145571d10453SEric Joyner  * Copies Tx completion queue context from dense structure to HW register space
145671d10453SEric Joyner  */
145771d10453SEric Joyner static enum ice_status
145871d10453SEric Joyner ice_copy_tx_cmpltnq_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_cmpltnq_ctx,
145971d10453SEric Joyner 			      u32 tx_cmpltnq_index)
146071d10453SEric Joyner {
146171d10453SEric Joyner 	u8 i;
146271d10453SEric Joyner 
146371d10453SEric Joyner 	if (!ice_tx_cmpltnq_ctx)
146471d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
146571d10453SEric Joyner 
146671d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
146771d10453SEric Joyner 		return ICE_ERR_PARAM;
146871d10453SEric Joyner 
146971d10453SEric Joyner 	/* Copy each dword separately to HW */
147071d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++) {
147171d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index),
147271d10453SEric Joyner 		     *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
147371d10453SEric Joyner 
147471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "cmpltnqdata[%d]: %08X\n", i,
147571d10453SEric Joyner 			  *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
147671d10453SEric Joyner 	}
147771d10453SEric Joyner 
147871d10453SEric Joyner 	return ICE_SUCCESS;
147971d10453SEric Joyner }
148071d10453SEric Joyner 
148171d10453SEric Joyner /* LAN Tx Completion Queue Context */
148271d10453SEric Joyner static const struct ice_ctx_ele ice_tx_cmpltnq_ctx_info[] = {
148371d10453SEric Joyner 				       /* Field			Width   LSB */
148471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, base,			57,	0),
148571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, q_len,		18,	64),
148671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, generation,		1,	96),
148771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, wrt_ptr,		22,	97),
148871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, pf_num,		3,	128),
148971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_num,		10,	131),
149071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_type,		2,	141),
149171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, tph_desc_wr,		1,	160),
149271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cpuid,		8,	161),
149371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cmpltn_cache,		512,	192),
149471d10453SEric Joyner 	{ 0 }
149571d10453SEric Joyner };
149671d10453SEric Joyner 
149771d10453SEric Joyner /**
149871d10453SEric Joyner  * ice_write_tx_cmpltnq_ctx
149971d10453SEric Joyner  * @hw: pointer to the hardware structure
150071d10453SEric Joyner  * @tx_cmpltnq_ctx: pointer to the completion queue context
150171d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
150271d10453SEric Joyner  *
150371d10453SEric Joyner  * Converts completion queue context from sparse to dense structure and then
150471d10453SEric Joyner  * writes it to HW register space
150571d10453SEric Joyner  */
150671d10453SEric Joyner enum ice_status
150771d10453SEric Joyner ice_write_tx_cmpltnq_ctx(struct ice_hw *hw,
150871d10453SEric Joyner 			 struct ice_tx_cmpltnq_ctx *tx_cmpltnq_ctx,
150971d10453SEric Joyner 			 u32 tx_cmpltnq_index)
151071d10453SEric Joyner {
151171d10453SEric Joyner 	u8 ctx_buf[ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
151271d10453SEric Joyner 
15137d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info);
151471d10453SEric Joyner 	return ice_copy_tx_cmpltnq_ctx_to_hw(hw, ctx_buf, tx_cmpltnq_index);
151571d10453SEric Joyner }
151671d10453SEric Joyner 
151771d10453SEric Joyner /**
151871d10453SEric Joyner  * ice_clear_tx_cmpltnq_ctx
151971d10453SEric Joyner  * @hw: pointer to the hardware structure
152071d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue to clear
152171d10453SEric Joyner  *
152271d10453SEric Joyner  * Clears Tx completion queue context in HW register space
152371d10453SEric Joyner  */
152471d10453SEric Joyner enum ice_status
152571d10453SEric Joyner ice_clear_tx_cmpltnq_ctx(struct ice_hw *hw, u32 tx_cmpltnq_index)
152671d10453SEric Joyner {
152771d10453SEric Joyner 	u8 i;
152871d10453SEric Joyner 
152971d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
153071d10453SEric Joyner 		return ICE_ERR_PARAM;
153171d10453SEric Joyner 
153271d10453SEric Joyner 	/* Clear each dword register separately */
153371d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++)
153471d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index), 0);
153571d10453SEric Joyner 
153671d10453SEric Joyner 	return ICE_SUCCESS;
153771d10453SEric Joyner }
153871d10453SEric Joyner 
153971d10453SEric Joyner /**
154071d10453SEric Joyner  * ice_copy_tx_drbell_q_ctx_to_hw
154171d10453SEric Joyner  * @hw: pointer to the hardware structure
154271d10453SEric Joyner  * @ice_tx_drbell_q_ctx: pointer to the doorbell queue context
154371d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
154471d10453SEric Joyner  *
154571d10453SEric Joyner  * Copies doorbell queue context from dense structure to HW register space
154671d10453SEric Joyner  */
154771d10453SEric Joyner static enum ice_status
154871d10453SEric Joyner ice_copy_tx_drbell_q_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_drbell_q_ctx,
154971d10453SEric Joyner 			       u32 tx_drbell_q_index)
155071d10453SEric Joyner {
155171d10453SEric Joyner 	u8 i;
155271d10453SEric Joyner 
155371d10453SEric Joyner 	if (!ice_tx_drbell_q_ctx)
155471d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
155571d10453SEric Joyner 
155671d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
155771d10453SEric Joyner 		return ICE_ERR_PARAM;
155871d10453SEric Joyner 
155971d10453SEric Joyner 	/* Copy each dword separately to HW */
156071d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++) {
156171d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index),
156271d10453SEric Joyner 		     *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
156371d10453SEric Joyner 
156471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "tx_drbell_qdata[%d]: %08X\n", i,
156571d10453SEric Joyner 			  *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
156671d10453SEric Joyner 	}
156771d10453SEric Joyner 
156871d10453SEric Joyner 	return ICE_SUCCESS;
156971d10453SEric Joyner }
157071d10453SEric Joyner 
157171d10453SEric Joyner /* LAN Tx Doorbell Queue Context info */
157271d10453SEric Joyner static const struct ice_ctx_ele ice_tx_drbell_q_ctx_info[] = {
157371d10453SEric Joyner 					/* Field		Width   LSB */
157471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, base,		57,	0),
157571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, ring_len,		13,	64),
157671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, pf_num,		3,	80),
157771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vf_num,		8,	84),
157871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vmvf_type,		2,	94),
157971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, cpuid,		8,	96),
158071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_rd,		1,	104),
158171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_wr,		1,	108),
158271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, db_q_en,		1,	112),
158371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_head,		13,	128),
158471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_tail,		13,	144),
158571d10453SEric Joyner 	{ 0 }
158671d10453SEric Joyner };
158771d10453SEric Joyner 
158871d10453SEric Joyner /**
158971d10453SEric Joyner  * ice_write_tx_drbell_q_ctx
159071d10453SEric Joyner  * @hw: pointer to the hardware structure
159171d10453SEric Joyner  * @tx_drbell_q_ctx: pointer to the doorbell queue context
159271d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
159371d10453SEric Joyner  *
159471d10453SEric Joyner  * Converts doorbell queue context from sparse to dense structure and then
159571d10453SEric Joyner  * writes it to HW register space
159671d10453SEric Joyner  */
159771d10453SEric Joyner enum ice_status
159871d10453SEric Joyner ice_write_tx_drbell_q_ctx(struct ice_hw *hw,
159971d10453SEric Joyner 			  struct ice_tx_drbell_q_ctx *tx_drbell_q_ctx,
160071d10453SEric Joyner 			  u32 tx_drbell_q_index)
160171d10453SEric Joyner {
160271d10453SEric Joyner 	u8 ctx_buf[ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
160371d10453SEric Joyner 
16047d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_drbell_q_ctx, ctx_buf,
16057d7af7f8SEric Joyner 		    ice_tx_drbell_q_ctx_info);
160671d10453SEric Joyner 	return ice_copy_tx_drbell_q_ctx_to_hw(hw, ctx_buf, tx_drbell_q_index);
160771d10453SEric Joyner }
160871d10453SEric Joyner 
160971d10453SEric Joyner /**
161071d10453SEric Joyner  * ice_clear_tx_drbell_q_ctx
161171d10453SEric Joyner  * @hw: pointer to the hardware structure
161271d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue to clear
161371d10453SEric Joyner  *
161471d10453SEric Joyner  * Clears doorbell queue context in HW register space
161571d10453SEric Joyner  */
161671d10453SEric Joyner enum ice_status
161771d10453SEric Joyner ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index)
161871d10453SEric Joyner {
161971d10453SEric Joyner 	u8 i;
162071d10453SEric Joyner 
162171d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
162271d10453SEric Joyner 		return ICE_ERR_PARAM;
162371d10453SEric Joyner 
162471d10453SEric Joyner 	/* Clear each dword register separately */
162571d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++)
162671d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index), 0);
162771d10453SEric Joyner 
162871d10453SEric Joyner 	return ICE_SUCCESS;
162971d10453SEric Joyner }
163071d10453SEric Joyner 
163171d10453SEric Joyner /* FW Admin Queue command wrappers */
163271d10453SEric Joyner 
163371d10453SEric Joyner /**
16349cf1841cSEric Joyner  * ice_should_retry_sq_send_cmd
16359cf1841cSEric Joyner  * @opcode: AQ opcode
16369cf1841cSEric Joyner  *
16379cf1841cSEric Joyner  * Decide if we should retry the send command routine for the ATQ, depending
16389cf1841cSEric Joyner  * on the opcode.
16399cf1841cSEric Joyner  */
16409cf1841cSEric Joyner static bool ice_should_retry_sq_send_cmd(u16 opcode)
16419cf1841cSEric Joyner {
16429cf1841cSEric Joyner 	switch (opcode) {
16439cf1841cSEric Joyner 	case ice_aqc_opc_dnl_get_status:
16449cf1841cSEric Joyner 	case ice_aqc_opc_dnl_run:
16459cf1841cSEric Joyner 	case ice_aqc_opc_dnl_call:
16469cf1841cSEric Joyner 	case ice_aqc_opc_dnl_read_sto:
16479cf1841cSEric Joyner 	case ice_aqc_opc_dnl_write_sto:
16489cf1841cSEric Joyner 	case ice_aqc_opc_dnl_set_breakpoints:
16499cf1841cSEric Joyner 	case ice_aqc_opc_dnl_read_log:
16509cf1841cSEric Joyner 	case ice_aqc_opc_get_link_topo:
16519cf1841cSEric Joyner 	case ice_aqc_opc_done_alt_write:
16529cf1841cSEric Joyner 	case ice_aqc_opc_lldp_stop:
16539cf1841cSEric Joyner 	case ice_aqc_opc_lldp_start:
16549cf1841cSEric Joyner 	case ice_aqc_opc_lldp_filter_ctrl:
16559cf1841cSEric Joyner 		return true;
16569cf1841cSEric Joyner 	}
16579cf1841cSEric Joyner 
16589cf1841cSEric Joyner 	return false;
16599cf1841cSEric Joyner }
16609cf1841cSEric Joyner 
16619cf1841cSEric Joyner /**
16629cf1841cSEric Joyner  * ice_sq_send_cmd_retry - send command to Control Queue (ATQ)
16639cf1841cSEric Joyner  * @hw: pointer to the HW struct
16649cf1841cSEric Joyner  * @cq: pointer to the specific Control queue
16659cf1841cSEric Joyner  * @desc: prefilled descriptor describing the command
16669cf1841cSEric Joyner  * @buf: buffer to use for indirect commands (or NULL for direct commands)
16679cf1841cSEric Joyner  * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
16689cf1841cSEric Joyner  * @cd: pointer to command details structure
16699cf1841cSEric Joyner  *
16709cf1841cSEric Joyner  * Retry sending the FW Admin Queue command, multiple times, to the FW Admin
16719cf1841cSEric Joyner  * Queue if the EBUSY AQ error is returned.
16729cf1841cSEric Joyner  */
16739cf1841cSEric Joyner static enum ice_status
16749cf1841cSEric Joyner ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
16759cf1841cSEric Joyner 		      struct ice_aq_desc *desc, void *buf, u16 buf_size,
16769cf1841cSEric Joyner 		      struct ice_sq_cd *cd)
16779cf1841cSEric Joyner {
16789cf1841cSEric Joyner 	struct ice_aq_desc desc_cpy;
16799cf1841cSEric Joyner 	enum ice_status status;
16809cf1841cSEric Joyner 	bool is_cmd_for_retry;
16819cf1841cSEric Joyner 	u8 *buf_cpy = NULL;
16829cf1841cSEric Joyner 	u8 idx = 0;
16839cf1841cSEric Joyner 	u16 opcode;
16849cf1841cSEric Joyner 
16859cf1841cSEric Joyner 	opcode = LE16_TO_CPU(desc->opcode);
16869cf1841cSEric Joyner 	is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode);
16879cf1841cSEric Joyner 	ice_memset(&desc_cpy, 0, sizeof(desc_cpy), ICE_NONDMA_MEM);
16889cf1841cSEric Joyner 
16899cf1841cSEric Joyner 	if (is_cmd_for_retry) {
16909cf1841cSEric Joyner 		if (buf) {
16919cf1841cSEric Joyner 			buf_cpy = (u8 *)ice_malloc(hw, buf_size);
16929cf1841cSEric Joyner 			if (!buf_cpy)
16939cf1841cSEric Joyner 				return ICE_ERR_NO_MEMORY;
16949cf1841cSEric Joyner 		}
16959cf1841cSEric Joyner 
16969cf1841cSEric Joyner 		ice_memcpy(&desc_cpy, desc, sizeof(desc_cpy),
16979cf1841cSEric Joyner 			   ICE_NONDMA_TO_NONDMA);
16989cf1841cSEric Joyner 	}
16999cf1841cSEric Joyner 
17009cf1841cSEric Joyner 	do {
17019cf1841cSEric Joyner 		status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd);
17029cf1841cSEric Joyner 
17039cf1841cSEric Joyner 		if (!is_cmd_for_retry || status == ICE_SUCCESS ||
17049cf1841cSEric Joyner 		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
17059cf1841cSEric Joyner 			break;
17069cf1841cSEric Joyner 
17079cf1841cSEric Joyner 		if (buf_cpy)
17089cf1841cSEric Joyner 			ice_memcpy(buf, buf_cpy, buf_size,
17099cf1841cSEric Joyner 				   ICE_NONDMA_TO_NONDMA);
17109cf1841cSEric Joyner 
17119cf1841cSEric Joyner 		ice_memcpy(desc, &desc_cpy, sizeof(desc_cpy),
17129cf1841cSEric Joyner 			   ICE_NONDMA_TO_NONDMA);
17139cf1841cSEric Joyner 
17149cf1841cSEric Joyner 		ice_msec_delay(ICE_SQ_SEND_DELAY_TIME_MS, false);
17159cf1841cSEric Joyner 
17169cf1841cSEric Joyner 	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
17179cf1841cSEric Joyner 
17189cf1841cSEric Joyner 	if (buf_cpy)
17199cf1841cSEric Joyner 		ice_free(hw, buf_cpy);
17209cf1841cSEric Joyner 
17219cf1841cSEric Joyner 	return status;
17229cf1841cSEric Joyner }
17239cf1841cSEric Joyner 
17249cf1841cSEric Joyner /**
172571d10453SEric Joyner  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
172671d10453SEric Joyner  * @hw: pointer to the HW struct
172771d10453SEric Joyner  * @desc: descriptor describing the command
172871d10453SEric Joyner  * @buf: buffer to use for indirect commands (NULL for direct commands)
172971d10453SEric Joyner  * @buf_size: size of buffer for indirect commands (0 for direct commands)
173071d10453SEric Joyner  * @cd: pointer to command details structure
173171d10453SEric Joyner  *
173271d10453SEric Joyner  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
173371d10453SEric Joyner  */
173471d10453SEric Joyner enum ice_status
173571d10453SEric Joyner ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
173671d10453SEric Joyner 		u16 buf_size, struct ice_sq_cd *cd)
173771d10453SEric Joyner {
17389cf1841cSEric Joyner 	return ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);
173971d10453SEric Joyner }
174071d10453SEric Joyner 
174171d10453SEric Joyner /**
174271d10453SEric Joyner  * ice_aq_get_fw_ver
174371d10453SEric Joyner  * @hw: pointer to the HW struct
174471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
174571d10453SEric Joyner  *
174671d10453SEric Joyner  * Get the firmware version (0x0001) from the admin queue commands
174771d10453SEric Joyner  */
174871d10453SEric Joyner enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
174971d10453SEric Joyner {
175071d10453SEric Joyner 	struct ice_aqc_get_ver *resp;
175171d10453SEric Joyner 	struct ice_aq_desc desc;
175271d10453SEric Joyner 	enum ice_status status;
175371d10453SEric Joyner 
175471d10453SEric Joyner 	resp = &desc.params.get_ver;
175571d10453SEric Joyner 
175671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
175771d10453SEric Joyner 
175871d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
175971d10453SEric Joyner 
176071d10453SEric Joyner 	if (!status) {
176171d10453SEric Joyner 		hw->fw_branch = resp->fw_branch;
176271d10453SEric Joyner 		hw->fw_maj_ver = resp->fw_major;
176371d10453SEric Joyner 		hw->fw_min_ver = resp->fw_minor;
176471d10453SEric Joyner 		hw->fw_patch = resp->fw_patch;
176571d10453SEric Joyner 		hw->fw_build = LE32_TO_CPU(resp->fw_build);
176671d10453SEric Joyner 		hw->api_branch = resp->api_branch;
176771d10453SEric Joyner 		hw->api_maj_ver = resp->api_major;
176871d10453SEric Joyner 		hw->api_min_ver = resp->api_minor;
176971d10453SEric Joyner 		hw->api_patch = resp->api_patch;
177071d10453SEric Joyner 	}
177171d10453SEric Joyner 
177271d10453SEric Joyner 	return status;
177371d10453SEric Joyner }
177471d10453SEric Joyner 
177571d10453SEric Joyner /**
177671d10453SEric Joyner  * ice_aq_send_driver_ver
177771d10453SEric Joyner  * @hw: pointer to the HW struct
177871d10453SEric Joyner  * @dv: driver's major, minor version
177971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
178071d10453SEric Joyner  *
178171d10453SEric Joyner  * Send the driver version (0x0002) to the firmware
178271d10453SEric Joyner  */
178371d10453SEric Joyner enum ice_status
178471d10453SEric Joyner ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
178571d10453SEric Joyner 		       struct ice_sq_cd *cd)
178671d10453SEric Joyner {
178771d10453SEric Joyner 	struct ice_aqc_driver_ver *cmd;
178871d10453SEric Joyner 	struct ice_aq_desc desc;
178971d10453SEric Joyner 	u16 len;
179071d10453SEric Joyner 
179171d10453SEric Joyner 	cmd = &desc.params.driver_ver;
179271d10453SEric Joyner 
179371d10453SEric Joyner 	if (!dv)
179471d10453SEric Joyner 		return ICE_ERR_PARAM;
179571d10453SEric Joyner 
179671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
179771d10453SEric Joyner 
179871d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
179971d10453SEric Joyner 	cmd->major_ver = dv->major_ver;
180071d10453SEric Joyner 	cmd->minor_ver = dv->minor_ver;
180171d10453SEric Joyner 	cmd->build_ver = dv->build_ver;
180271d10453SEric Joyner 	cmd->subbuild_ver = dv->subbuild_ver;
180371d10453SEric Joyner 
180471d10453SEric Joyner 	len = 0;
180571d10453SEric Joyner 	while (len < sizeof(dv->driver_string) &&
180671d10453SEric Joyner 	       IS_ASCII(dv->driver_string[len]) && dv->driver_string[len])
180771d10453SEric Joyner 		len++;
180871d10453SEric Joyner 
180971d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
181071d10453SEric Joyner }
181171d10453SEric Joyner 
181271d10453SEric Joyner /**
181371d10453SEric Joyner  * ice_aq_q_shutdown
181471d10453SEric Joyner  * @hw: pointer to the HW struct
181571d10453SEric Joyner  * @unloading: is the driver unloading itself
181671d10453SEric Joyner  *
181771d10453SEric Joyner  * Tell the Firmware that we're shutting down the AdminQ and whether
181871d10453SEric Joyner  * or not the driver is unloading as well (0x0003).
181971d10453SEric Joyner  */
182071d10453SEric Joyner enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
182171d10453SEric Joyner {
182271d10453SEric Joyner 	struct ice_aqc_q_shutdown *cmd;
182371d10453SEric Joyner 	struct ice_aq_desc desc;
182471d10453SEric Joyner 
182571d10453SEric Joyner 	cmd = &desc.params.q_shutdown;
182671d10453SEric Joyner 
182771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
182871d10453SEric Joyner 
182971d10453SEric Joyner 	if (unloading)
183071d10453SEric Joyner 		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
183171d10453SEric Joyner 
183271d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
183371d10453SEric Joyner }
183471d10453SEric Joyner 
183571d10453SEric Joyner /**
183671d10453SEric Joyner  * ice_aq_req_res
183771d10453SEric Joyner  * @hw: pointer to the HW struct
183871d10453SEric Joyner  * @res: resource ID
183971d10453SEric Joyner  * @access: access type
184071d10453SEric Joyner  * @sdp_number: resource number
184171d10453SEric Joyner  * @timeout: the maximum time in ms that the driver may hold the resource
184271d10453SEric Joyner  * @cd: pointer to command details structure or NULL
184371d10453SEric Joyner  *
184471d10453SEric Joyner  * Requests common resource using the admin queue commands (0x0008).
184571d10453SEric Joyner  * When attempting to acquire the Global Config Lock, the driver can
184671d10453SEric Joyner  * learn of three states:
184771d10453SEric Joyner  *  1) ICE_SUCCESS -        acquired lock, and can perform download package
184871d10453SEric Joyner  *  2) ICE_ERR_AQ_ERROR -   did not get lock, driver should fail to load
184971d10453SEric Joyner  *  3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
185071d10453SEric Joyner  *                          successfully downloaded the package; the driver does
185171d10453SEric Joyner  *                          not have to download the package and can continue
185271d10453SEric Joyner  *                          loading
185371d10453SEric Joyner  *
185471d10453SEric Joyner  * Note that if the caller is in an acquire lock, perform action, release lock
185571d10453SEric Joyner  * phase of operation, it is possible that the FW may detect a timeout and issue
185671d10453SEric Joyner  * a CORER. In this case, the driver will receive a CORER interrupt and will
185771d10453SEric Joyner  * have to determine its cause. The calling thread that is handling this flow
185871d10453SEric Joyner  * will likely get an error propagated back to it indicating the Download
185971d10453SEric Joyner  * Package, Update Package or the Release Resource AQ commands timed out.
186071d10453SEric Joyner  */
186171d10453SEric Joyner static enum ice_status
186271d10453SEric Joyner ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
186371d10453SEric Joyner 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
186471d10453SEric Joyner 	       struct ice_sq_cd *cd)
186571d10453SEric Joyner {
186671d10453SEric Joyner 	struct ice_aqc_req_res *cmd_resp;
186771d10453SEric Joyner 	struct ice_aq_desc desc;
186871d10453SEric Joyner 	enum ice_status status;
186971d10453SEric Joyner 
187071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
187171d10453SEric Joyner 
187271d10453SEric Joyner 	cmd_resp = &desc.params.res_owner;
187371d10453SEric Joyner 
187471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
187571d10453SEric Joyner 
187671d10453SEric Joyner 	cmd_resp->res_id = CPU_TO_LE16(res);
187771d10453SEric Joyner 	cmd_resp->access_type = CPU_TO_LE16(access);
187871d10453SEric Joyner 	cmd_resp->res_number = CPU_TO_LE32(sdp_number);
187971d10453SEric Joyner 	cmd_resp->timeout = CPU_TO_LE32(*timeout);
188071d10453SEric Joyner 	*timeout = 0;
188171d10453SEric Joyner 
188271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
188371d10453SEric Joyner 
188471d10453SEric Joyner 	/* The completion specifies the maximum time in ms that the driver
188571d10453SEric Joyner 	 * may hold the resource in the Timeout field.
188671d10453SEric Joyner 	 */
188771d10453SEric Joyner 
188871d10453SEric Joyner 	/* Global config lock response utilizes an additional status field.
188971d10453SEric Joyner 	 *
189071d10453SEric Joyner 	 * If the Global config lock resource is held by some other driver, the
189171d10453SEric Joyner 	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
189271d10453SEric Joyner 	 * and the timeout field indicates the maximum time the current owner
189371d10453SEric Joyner 	 * of the resource has to free it.
189471d10453SEric Joyner 	 */
189571d10453SEric Joyner 	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
189671d10453SEric Joyner 		if (LE16_TO_CPU(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
189771d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
189871d10453SEric Joyner 			return ICE_SUCCESS;
189971d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
190071d10453SEric Joyner 			   ICE_AQ_RES_GLBL_IN_PROG) {
190171d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
190271d10453SEric Joyner 			return ICE_ERR_AQ_ERROR;
190371d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
190471d10453SEric Joyner 			   ICE_AQ_RES_GLBL_DONE) {
190571d10453SEric Joyner 			return ICE_ERR_AQ_NO_WORK;
190671d10453SEric Joyner 		}
190771d10453SEric Joyner 
190871d10453SEric Joyner 		/* invalid FW response, force a timeout immediately */
190971d10453SEric Joyner 		*timeout = 0;
191071d10453SEric Joyner 		return ICE_ERR_AQ_ERROR;
191171d10453SEric Joyner 	}
191271d10453SEric Joyner 
191371d10453SEric Joyner 	/* If the resource is held by some other driver, the command completes
191471d10453SEric Joyner 	 * with a busy return value and the timeout field indicates the maximum
191571d10453SEric Joyner 	 * time the current owner of the resource has to free it.
191671d10453SEric Joyner 	 */
191771d10453SEric Joyner 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
191871d10453SEric Joyner 		*timeout = LE32_TO_CPU(cmd_resp->timeout);
191971d10453SEric Joyner 
192071d10453SEric Joyner 	return status;
192171d10453SEric Joyner }
192271d10453SEric Joyner 
192371d10453SEric Joyner /**
192471d10453SEric Joyner  * ice_aq_release_res
192571d10453SEric Joyner  * @hw: pointer to the HW struct
192671d10453SEric Joyner  * @res: resource ID
192771d10453SEric Joyner  * @sdp_number: resource number
192871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
192971d10453SEric Joyner  *
193071d10453SEric Joyner  * release common resource using the admin queue commands (0x0009)
193171d10453SEric Joyner  */
193271d10453SEric Joyner static enum ice_status
193371d10453SEric Joyner ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
193471d10453SEric Joyner 		   struct ice_sq_cd *cd)
193571d10453SEric Joyner {
193671d10453SEric Joyner 	struct ice_aqc_req_res *cmd;
193771d10453SEric Joyner 	struct ice_aq_desc desc;
193871d10453SEric Joyner 
193971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
194071d10453SEric Joyner 
194171d10453SEric Joyner 	cmd = &desc.params.res_owner;
194271d10453SEric Joyner 
194371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
194471d10453SEric Joyner 
194571d10453SEric Joyner 	cmd->res_id = CPU_TO_LE16(res);
194671d10453SEric Joyner 	cmd->res_number = CPU_TO_LE32(sdp_number);
194771d10453SEric Joyner 
194871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
194971d10453SEric Joyner }
195071d10453SEric Joyner 
195171d10453SEric Joyner /**
195271d10453SEric Joyner  * ice_acquire_res
195371d10453SEric Joyner  * @hw: pointer to the HW structure
195471d10453SEric Joyner  * @res: resource ID
195571d10453SEric Joyner  * @access: access type (read or write)
195671d10453SEric Joyner  * @timeout: timeout in milliseconds
195771d10453SEric Joyner  *
195871d10453SEric Joyner  * This function will attempt to acquire the ownership of a resource.
195971d10453SEric Joyner  */
196071d10453SEric Joyner enum ice_status
196171d10453SEric Joyner ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
196271d10453SEric Joyner 		enum ice_aq_res_access_type access, u32 timeout)
196371d10453SEric Joyner {
196471d10453SEric Joyner #define ICE_RES_POLLING_DELAY_MS	10
196571d10453SEric Joyner 	u32 delay = ICE_RES_POLLING_DELAY_MS;
196671d10453SEric Joyner 	u32 time_left = timeout;
196771d10453SEric Joyner 	enum ice_status status;
196871d10453SEric Joyner 
196971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
197071d10453SEric Joyner 
197171d10453SEric Joyner 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
197271d10453SEric Joyner 
197371d10453SEric Joyner 	/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
197471d10453SEric Joyner 	 * previously acquired the resource and performed any necessary updates;
197571d10453SEric Joyner 	 * in this case the caller does not obtain the resource and has no
197671d10453SEric Joyner 	 * further work to do.
197771d10453SEric Joyner 	 */
197871d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK)
197971d10453SEric Joyner 		goto ice_acquire_res_exit;
198071d10453SEric Joyner 
198171d10453SEric Joyner 	if (status)
19827d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access);
198371d10453SEric Joyner 
198471d10453SEric Joyner 	/* If necessary, poll until the current lock owner timeouts */
198571d10453SEric Joyner 	timeout = time_left;
198671d10453SEric Joyner 	while (status && timeout && time_left) {
198771d10453SEric Joyner 		ice_msec_delay(delay, true);
198871d10453SEric Joyner 		timeout = (timeout > delay) ? timeout - delay : 0;
198971d10453SEric Joyner 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
199071d10453SEric Joyner 
199171d10453SEric Joyner 		if (status == ICE_ERR_AQ_NO_WORK)
199271d10453SEric Joyner 			/* lock free, but no work to do */
199371d10453SEric Joyner 			break;
199471d10453SEric Joyner 
199571d10453SEric Joyner 		if (!status)
199671d10453SEric Joyner 			/* lock acquired */
199771d10453SEric Joyner 			break;
199871d10453SEric Joyner 	}
199971d10453SEric Joyner 	if (status && status != ICE_ERR_AQ_NO_WORK)
200071d10453SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
200171d10453SEric Joyner 
200271d10453SEric Joyner ice_acquire_res_exit:
200371d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK) {
200471d10453SEric Joyner 		if (access == ICE_RES_WRITE)
20057d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n");
200671d10453SEric Joyner 		else
20077d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "Warning: ICE_ERR_AQ_NO_WORK not expected\n");
200871d10453SEric Joyner 	}
200971d10453SEric Joyner 	return status;
201071d10453SEric Joyner }
201171d10453SEric Joyner 
201271d10453SEric Joyner /**
201371d10453SEric Joyner  * ice_release_res
201471d10453SEric Joyner  * @hw: pointer to the HW structure
201571d10453SEric Joyner  * @res: resource ID
201671d10453SEric Joyner  *
201771d10453SEric Joyner  * This function will release a resource using the proper Admin Command.
201871d10453SEric Joyner  */
201971d10453SEric Joyner void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
202071d10453SEric Joyner {
202171d10453SEric Joyner 	enum ice_status status;
202271d10453SEric Joyner 	u32 total_delay = 0;
202371d10453SEric Joyner 
202471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
202571d10453SEric Joyner 
202671d10453SEric Joyner 	status = ice_aq_release_res(hw, res, 0, NULL);
202771d10453SEric Joyner 
202871d10453SEric Joyner 	/* there are some rare cases when trying to release the resource
202971d10453SEric Joyner 	 * results in an admin queue timeout, so handle them correctly
203071d10453SEric Joyner 	 */
203171d10453SEric Joyner 	while ((status == ICE_ERR_AQ_TIMEOUT) &&
203271d10453SEric Joyner 	       (total_delay < hw->adminq.sq_cmd_timeout)) {
203371d10453SEric Joyner 		ice_msec_delay(1, true);
203471d10453SEric Joyner 		status = ice_aq_release_res(hw, res, 0, NULL);
203571d10453SEric Joyner 		total_delay++;
203671d10453SEric Joyner 	}
203771d10453SEric Joyner }
203871d10453SEric Joyner 
203971d10453SEric Joyner /**
204071d10453SEric Joyner  * ice_aq_alloc_free_res - command to allocate/free resources
204171d10453SEric Joyner  * @hw: pointer to the HW struct
204271d10453SEric Joyner  * @num_entries: number of resource entries in buffer
204371d10453SEric Joyner  * @buf: Indirect buffer to hold data parameters and response
204471d10453SEric Joyner  * @buf_size: size of buffer for indirect commands
204571d10453SEric Joyner  * @opc: pass in the command opcode
204671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
204771d10453SEric Joyner  *
204871d10453SEric Joyner  * Helper function to allocate/free resources using the admin queue commands
204971d10453SEric Joyner  */
205071d10453SEric Joyner enum ice_status
205171d10453SEric Joyner ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
205271d10453SEric Joyner 		      struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
205371d10453SEric Joyner 		      enum ice_adminq_opc opc, struct ice_sq_cd *cd)
205471d10453SEric Joyner {
205571d10453SEric Joyner 	struct ice_aqc_alloc_free_res_cmd *cmd;
205671d10453SEric Joyner 	struct ice_aq_desc desc;
205771d10453SEric Joyner 
205871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
205971d10453SEric Joyner 
206071d10453SEric Joyner 	cmd = &desc.params.sw_res_ctrl;
206171d10453SEric Joyner 
206271d10453SEric Joyner 	if (!buf)
206371d10453SEric Joyner 		return ICE_ERR_PARAM;
206471d10453SEric Joyner 
2065d08b8680SEric Joyner 	if (buf_size < FLEX_ARRAY_SIZE(buf, elem, num_entries))
206671d10453SEric Joyner 		return ICE_ERR_PARAM;
206771d10453SEric Joyner 
206871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
206971d10453SEric Joyner 
207071d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
207171d10453SEric Joyner 
207271d10453SEric Joyner 	cmd->num_entries = CPU_TO_LE16(num_entries);
207371d10453SEric Joyner 
207471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
207571d10453SEric Joyner }
207671d10453SEric Joyner 
207771d10453SEric Joyner /**
207871d10453SEric Joyner  * ice_alloc_hw_res - allocate resource
207971d10453SEric Joyner  * @hw: pointer to the HW struct
208071d10453SEric Joyner  * @type: type of resource
208171d10453SEric Joyner  * @num: number of resources to allocate
208271d10453SEric Joyner  * @btm: allocate from bottom
208371d10453SEric Joyner  * @res: pointer to array that will receive the resources
208471d10453SEric Joyner  */
208571d10453SEric Joyner enum ice_status
208671d10453SEric Joyner ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
208771d10453SEric Joyner {
208871d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
208971d10453SEric Joyner 	enum ice_status status;
209071d10453SEric Joyner 	u16 buf_len;
209171d10453SEric Joyner 
20927d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
20937d7af7f8SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
209471d10453SEric Joyner 	if (!buf)
209571d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
209671d10453SEric Joyner 
209771d10453SEric Joyner 	/* Prepare buffer to allocate resource. */
209871d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
209971d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
210071d10453SEric Joyner 				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
210171d10453SEric Joyner 	if (btm)
210271d10453SEric Joyner 		buf->res_type |= CPU_TO_LE16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
210371d10453SEric Joyner 
210471d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
210571d10453SEric Joyner 				       ice_aqc_opc_alloc_res, NULL);
210671d10453SEric Joyner 	if (status)
210771d10453SEric Joyner 		goto ice_alloc_res_exit;
210871d10453SEric Joyner 
21097d7af7f8SEric Joyner 	ice_memcpy(res, buf->elem, sizeof(*buf->elem) * num,
211071d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
211171d10453SEric Joyner 
211271d10453SEric Joyner ice_alloc_res_exit:
211371d10453SEric Joyner 	ice_free(hw, buf);
211471d10453SEric Joyner 	return status;
211571d10453SEric Joyner }
211671d10453SEric Joyner 
211771d10453SEric Joyner /**
211871d10453SEric Joyner  * ice_free_hw_res - free allocated HW resource
211971d10453SEric Joyner  * @hw: pointer to the HW struct
212071d10453SEric Joyner  * @type: type of resource to free
212171d10453SEric Joyner  * @num: number of resources
212271d10453SEric Joyner  * @res: pointer to array that contains the resources to free
212371d10453SEric Joyner  */
21247d7af7f8SEric Joyner enum ice_status ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
212571d10453SEric Joyner {
212671d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
212771d10453SEric Joyner 	enum ice_status status;
212871d10453SEric Joyner 	u16 buf_len;
212971d10453SEric Joyner 
21307d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
213171d10453SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
213271d10453SEric Joyner 	if (!buf)
213371d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
213471d10453SEric Joyner 
213571d10453SEric Joyner 	/* Prepare buffer to free resource. */
213671d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
213771d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type);
21387d7af7f8SEric Joyner 	ice_memcpy(buf->elem, res, sizeof(*buf->elem) * num,
213971d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
214071d10453SEric Joyner 
214171d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, num, buf, buf_len,
214271d10453SEric Joyner 				       ice_aqc_opc_free_res, NULL);
214371d10453SEric Joyner 	if (status)
214471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
214571d10453SEric Joyner 
214671d10453SEric Joyner 	ice_free(hw, buf);
214771d10453SEric Joyner 	return status;
214871d10453SEric Joyner }
214971d10453SEric Joyner 
215071d10453SEric Joyner /**
215171d10453SEric Joyner  * ice_get_num_per_func - determine number of resources per PF
215271d10453SEric Joyner  * @hw: pointer to the HW structure
215371d10453SEric Joyner  * @max: value to be evenly split between each PF
215471d10453SEric Joyner  *
215571d10453SEric Joyner  * Determine the number of valid functions by going through the bitmap returned
215671d10453SEric Joyner  * from parsing capabilities and use this to calculate the number of resources
215771d10453SEric Joyner  * per PF based on the max value passed in.
215871d10453SEric Joyner  */
215971d10453SEric Joyner static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
216071d10453SEric Joyner {
216171d10453SEric Joyner 	u8 funcs;
216271d10453SEric Joyner 
216371d10453SEric Joyner #define ICE_CAPS_VALID_FUNCS_M	0xFF
216471d10453SEric Joyner 	funcs = ice_hweight8(hw->dev_caps.common_cap.valid_functions &
216571d10453SEric Joyner 			     ICE_CAPS_VALID_FUNCS_M);
216671d10453SEric Joyner 
216771d10453SEric Joyner 	if (!funcs)
216871d10453SEric Joyner 		return 0;
216971d10453SEric Joyner 
217071d10453SEric Joyner 	return max / funcs;
217171d10453SEric Joyner }
217271d10453SEric Joyner 
217371d10453SEric Joyner /**
217471d10453SEric Joyner  * ice_print_led_caps - print LED capabilities
217571d10453SEric Joyner  * @hw: pointer to the ice_hw instance
217671d10453SEric Joyner  * @caps: pointer to common caps instance
217771d10453SEric Joyner  * @prefix: string to prefix when printing
21789cf1841cSEric Joyner  * @dbg: set to indicate debug print
217971d10453SEric Joyner  */
218071d10453SEric Joyner static void
218171d10453SEric Joyner ice_print_led_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
21829cf1841cSEric Joyner 		   char const *prefix, bool dbg)
218371d10453SEric Joyner {
218471d10453SEric Joyner 	u8 i;
218571d10453SEric Joyner 
21869cf1841cSEric Joyner 	if (dbg)
218771d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: led_pin_num = %d\n", prefix,
218871d10453SEric Joyner 			  caps->led_pin_num);
218971d10453SEric Joyner 	else
219071d10453SEric Joyner 		ice_info(hw, "%s: led_pin_num = %d\n", prefix,
219171d10453SEric Joyner 			 caps->led_pin_num);
219271d10453SEric Joyner 
219371d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_LED; i++) {
219471d10453SEric Joyner 		if (!caps->led[i])
219571d10453SEric Joyner 			continue;
219671d10453SEric Joyner 
21979cf1841cSEric Joyner 		if (dbg)
219871d10453SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = %d\n",
219971d10453SEric Joyner 				  prefix, i, caps->led[i]);
220071d10453SEric Joyner 		else
220171d10453SEric Joyner 			ice_info(hw, "%s: led[%d] = %d\n", prefix, i,
220271d10453SEric Joyner 				 caps->led[i]);
220371d10453SEric Joyner 	}
220471d10453SEric Joyner }
220571d10453SEric Joyner 
220671d10453SEric Joyner /**
220771d10453SEric Joyner  * ice_print_sdp_caps - print SDP capabilities
220871d10453SEric Joyner  * @hw: pointer to the ice_hw instance
220971d10453SEric Joyner  * @caps: pointer to common caps instance
221071d10453SEric Joyner  * @prefix: string to prefix when printing
22119cf1841cSEric Joyner  * @dbg: set to indicate debug print
221271d10453SEric Joyner  */
221371d10453SEric Joyner static void
221471d10453SEric Joyner ice_print_sdp_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
22159cf1841cSEric Joyner 		   char const *prefix, bool dbg)
221671d10453SEric Joyner {
221771d10453SEric Joyner 	u8 i;
221871d10453SEric Joyner 
22199cf1841cSEric Joyner 	if (dbg)
222071d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sdp_pin_num = %d\n", prefix,
222171d10453SEric Joyner 			  caps->sdp_pin_num);
222271d10453SEric Joyner 	else
222371d10453SEric Joyner 		ice_info(hw, "%s: sdp_pin_num = %d\n", prefix,
222471d10453SEric Joyner 			 caps->sdp_pin_num);
222571d10453SEric Joyner 
222671d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_SDP; i++) {
222771d10453SEric Joyner 		if (!caps->sdp[i])
222871d10453SEric Joyner 			continue;
222971d10453SEric Joyner 
22309cf1841cSEric Joyner 		if (dbg)
223171d10453SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = %d\n",
223271d10453SEric Joyner 				  prefix, i, caps->sdp[i]);
223371d10453SEric Joyner 		else
223471d10453SEric Joyner 			ice_info(hw, "%s: sdp[%d] = %d\n", prefix,
223571d10453SEric Joyner 				 i, caps->sdp[i]);
223671d10453SEric Joyner 	}
223771d10453SEric Joyner }
223871d10453SEric Joyner 
223971d10453SEric Joyner /**
22407d7af7f8SEric Joyner  * ice_parse_common_caps - parse common device/function capabilities
224171d10453SEric Joyner  * @hw: pointer to the HW struct
22427d7af7f8SEric Joyner  * @caps: pointer to common capabilities structure
22437d7af7f8SEric Joyner  * @elem: the capability element to parse
22447d7af7f8SEric Joyner  * @prefix: message prefix for tracing capabilities
224571d10453SEric Joyner  *
22467d7af7f8SEric Joyner  * Given a capability element, extract relevant details into the common
22477d7af7f8SEric Joyner  * capability structure.
22487d7af7f8SEric Joyner  *
22497d7af7f8SEric Joyner  * Returns: true if the capability matches one of the common capability ids,
22507d7af7f8SEric Joyner  * false otherwise.
225171d10453SEric Joyner  */
22527d7af7f8SEric Joyner static bool
22537d7af7f8SEric Joyner ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
22547d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
225571d10453SEric Joyner {
22567d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(elem->logical_id);
22577d7af7f8SEric Joyner 	u32 phys_id = LE32_TO_CPU(elem->phys_id);
22587d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(elem->number);
22597d7af7f8SEric Joyner 	u16 cap = LE16_TO_CPU(elem->cap);
22607d7af7f8SEric Joyner 	bool found = true;
226171d10453SEric Joyner 
226271d10453SEric Joyner 	switch (cap) {
226371d10453SEric Joyner 	case ICE_AQC_CAPS_SWITCHING_MODE:
226471d10453SEric Joyner 		caps->switching_mode = number;
22657d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: switching_mode = %d\n", prefix,
226671d10453SEric Joyner 			  caps->switching_mode);
226771d10453SEric Joyner 		break;
226871d10453SEric Joyner 	case ICE_AQC_CAPS_MANAGEABILITY_MODE:
226971d10453SEric Joyner 		caps->mgmt_mode = number;
227071d10453SEric Joyner 		caps->mgmt_protocols_mctp = logical_id;
22717d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_mode = %d\n", prefix,
227271d10453SEric Joyner 			  caps->mgmt_mode);
22737d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_protocols_mctp = %d\n", prefix,
227471d10453SEric Joyner 			  caps->mgmt_protocols_mctp);
227571d10453SEric Joyner 		break;
227671d10453SEric Joyner 	case ICE_AQC_CAPS_OS2BMC:
227771d10453SEric Joyner 		caps->os2bmc = number;
22787d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: os2bmc = %d\n", prefix, caps->os2bmc);
227971d10453SEric Joyner 		break;
228071d10453SEric Joyner 	case ICE_AQC_CAPS_VALID_FUNCTIONS:
228171d10453SEric Joyner 		caps->valid_functions = number;
22827d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix,
228371d10453SEric Joyner 			  caps->valid_functions);
228471d10453SEric Joyner 		break;
228571d10453SEric Joyner 	case ICE_AQC_CAPS_SRIOV:
228671d10453SEric Joyner 		caps->sr_iov_1_1 = (number == 1);
22877d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix,
228871d10453SEric Joyner 			  caps->sr_iov_1_1);
228971d10453SEric Joyner 		break;
229071d10453SEric Joyner 	case ICE_AQC_CAPS_802_1QBG:
229171d10453SEric Joyner 		caps->evb_802_1_qbg = (number == 1);
22927d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbg = %d\n", prefix, number);
229371d10453SEric Joyner 		break;
229471d10453SEric Joyner 	case ICE_AQC_CAPS_802_1BR:
229571d10453SEric Joyner 		caps->evb_802_1_qbh = (number == 1);
22967d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbh = %d\n", prefix, number);
229771d10453SEric Joyner 		break;
229871d10453SEric Joyner 	case ICE_AQC_CAPS_DCB:
229971d10453SEric Joyner 		caps->dcb = (number == 1);
230071d10453SEric Joyner 		caps->active_tc_bitmap = logical_id;
230171d10453SEric Joyner 		caps->maxtc = phys_id;
23027d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb);
23037d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix,
230471d10453SEric Joyner 			  caps->active_tc_bitmap);
23057d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc);
230671d10453SEric Joyner 		break;
230771d10453SEric Joyner 	case ICE_AQC_CAPS_ISCSI:
230871d10453SEric Joyner 		caps->iscsi = (number == 1);
23097d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: iscsi = %d\n", prefix, caps->iscsi);
231071d10453SEric Joyner 		break;
231171d10453SEric Joyner 	case ICE_AQC_CAPS_RSS:
231271d10453SEric Joyner 		caps->rss_table_size = number;
231371d10453SEric Joyner 		caps->rss_table_entry_width = logical_id;
23147d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix,
231571d10453SEric Joyner 			  caps->rss_table_size);
23167d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix,
231771d10453SEric Joyner 			  caps->rss_table_entry_width);
231871d10453SEric Joyner 		break;
231971d10453SEric Joyner 	case ICE_AQC_CAPS_RXQS:
232071d10453SEric Joyner 		caps->num_rxq = number;
232171d10453SEric Joyner 		caps->rxq_first_id = phys_id;
23227d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix,
232371d10453SEric Joyner 			  caps->num_rxq);
23247d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix,
232571d10453SEric Joyner 			  caps->rxq_first_id);
232671d10453SEric Joyner 		break;
232771d10453SEric Joyner 	case ICE_AQC_CAPS_TXQS:
232871d10453SEric Joyner 		caps->num_txq = number;
232971d10453SEric Joyner 		caps->txq_first_id = phys_id;
23307d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix,
233171d10453SEric Joyner 			  caps->num_txq);
23327d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix,
233371d10453SEric Joyner 			  caps->txq_first_id);
233471d10453SEric Joyner 		break;
233571d10453SEric Joyner 	case ICE_AQC_CAPS_MSIX:
233671d10453SEric Joyner 		caps->num_msix_vectors = number;
233771d10453SEric Joyner 		caps->msix_vector_first_id = phys_id;
23387d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix,
233971d10453SEric Joyner 			  caps->num_msix_vectors);
23407d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
234171d10453SEric Joyner 			  caps->msix_vector_first_id);
234271d10453SEric Joyner 		break;
234371d10453SEric Joyner 	case ICE_AQC_CAPS_NVM_VER:
234471d10453SEric Joyner 		break;
234571d10453SEric Joyner 	case ICE_AQC_CAPS_NVM_MGMT:
2346d08b8680SEric Joyner 		caps->sec_rev_disabled =
2347d08b8680SEric Joyner 			(number & ICE_NVM_MGMT_SEC_REV_DISABLED) ?
2348d08b8680SEric Joyner 			true : false;
2349d08b8680SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sec_rev_disabled = %d\n", prefix,
2350d08b8680SEric Joyner 			  caps->sec_rev_disabled);
2351d08b8680SEric Joyner 		caps->update_disabled =
2352d08b8680SEric Joyner 			(number & ICE_NVM_MGMT_UPDATE_DISABLED) ?
2353d08b8680SEric Joyner 			true : false;
2354d08b8680SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: update_disabled = %d\n", prefix,
2355d08b8680SEric Joyner 			  caps->update_disabled);
235671d10453SEric Joyner 		caps->nvm_unified_update =
235771d10453SEric Joyner 			(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
235871d10453SEric Joyner 			true : false;
23597d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
236071d10453SEric Joyner 			  caps->nvm_unified_update);
236171d10453SEric Joyner 		break;
236271d10453SEric Joyner 	case ICE_AQC_CAPS_CEM:
236371d10453SEric Joyner 		caps->mgmt_cem = (number == 1);
23647d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_cem = %d\n", prefix,
236571d10453SEric Joyner 			  caps->mgmt_cem);
236671d10453SEric Joyner 		break;
236771d10453SEric Joyner 	case ICE_AQC_CAPS_LED:
236871d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_LED) {
236971d10453SEric Joyner 			caps->led[phys_id] = true;
237071d10453SEric Joyner 			caps->led_pin_num++;
23717d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = 1\n", prefix, phys_id);
237271d10453SEric Joyner 		}
237371d10453SEric Joyner 		break;
237471d10453SEric Joyner 	case ICE_AQC_CAPS_SDP:
237571d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_SDP) {
237671d10453SEric Joyner 			caps->sdp[phys_id] = true;
237771d10453SEric Joyner 			caps->sdp_pin_num++;
23787d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = 1\n", prefix, phys_id);
237971d10453SEric Joyner 		}
238071d10453SEric Joyner 		break;
238171d10453SEric Joyner 	case ICE_AQC_CAPS_WR_CSR_PROT:
238271d10453SEric Joyner 		caps->wr_csr_prot = number;
238371d10453SEric Joyner 		caps->wr_csr_prot |= (u64)logical_id << 32;
23847d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wr_csr_prot = 0x%llX\n", prefix,
238571d10453SEric Joyner 			  (unsigned long long)caps->wr_csr_prot);
238671d10453SEric Joyner 		break;
238771d10453SEric Joyner 	case ICE_AQC_CAPS_WOL_PROXY:
238871d10453SEric Joyner 		caps->num_wol_proxy_fltr = number;
238971d10453SEric Joyner 		caps->wol_proxy_vsi_seid = logical_id;
239071d10453SEric Joyner 		caps->apm_wol_support = !!(phys_id & ICE_WOL_SUPPORT_M);
239171d10453SEric Joyner 		caps->acpi_prog_mthd = !!(phys_id &
239271d10453SEric Joyner 					  ICE_ACPI_PROG_MTHD_M);
239371d10453SEric Joyner 		caps->proxy_support = !!(phys_id & ICE_PROXY_SUPPORT_M);
23947d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_wol_proxy_fltr = %d\n", prefix,
239571d10453SEric Joyner 			  caps->num_wol_proxy_fltr);
23967d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wol_proxy_vsi_seid = %d\n", prefix,
239771d10453SEric Joyner 			  caps->wol_proxy_vsi_seid);
2398*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: apm_wol_support = %d\n",
2399*56429daeSEric Joyner 			  prefix, caps->apm_wol_support);
240071d10453SEric Joyner 		break;
240171d10453SEric Joyner 	case ICE_AQC_CAPS_MAX_MTU:
240271d10453SEric Joyner 		caps->max_mtu = number;
240371d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
240471d10453SEric Joyner 			  prefix, caps->max_mtu);
240571d10453SEric Joyner 		break;
2406*56429daeSEric Joyner 	case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
2407*56429daeSEric Joyner 		caps->pcie_reset_avoidance = (number > 0);
2408*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2409*56429daeSEric Joyner 			  "%s: pcie_reset_avoidance = %d\n", prefix,
2410*56429daeSEric Joyner 			  caps->pcie_reset_avoidance);
2411*56429daeSEric Joyner 		break;
2412*56429daeSEric Joyner 	case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
2413*56429daeSEric Joyner 		caps->reset_restrict_support = (number == 1);
2414*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2415*56429daeSEric Joyner 			  "%s: reset_restrict_support = %d\n", prefix,
2416*56429daeSEric Joyner 			  caps->reset_restrict_support);
2417*56429daeSEric Joyner 		break;
2418*56429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0:
2419*56429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1:
2420*56429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2:
2421*56429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3:
2422*56429daeSEric Joyner 	{
2423*56429daeSEric Joyner 		u8 index = cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0;
2424*56429daeSEric Joyner 
2425*56429daeSEric Joyner 		caps->ext_topo_dev_img_ver_high[index] = number;
2426*56429daeSEric Joyner 		caps->ext_topo_dev_img_ver_low[index] = logical_id;
2427*56429daeSEric Joyner 		caps->ext_topo_dev_img_part_num[index] =
2428*56429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
2429*56429daeSEric Joyner 			ICE_EXT_TOPO_DEV_IMG_PART_NUM_S;
2430*56429daeSEric Joyner 		caps->ext_topo_dev_img_load_en[index] =
2431*56429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
2432*56429daeSEric Joyner 		caps->ext_topo_dev_img_prog_en[index] =
2433*56429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
2434*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2435*56429daeSEric Joyner 			  "%s: ext_topo_dev_img_ver_high[%d] = %d\n",
2436*56429daeSEric Joyner 			  prefix, index,
2437*56429daeSEric Joyner 			  caps->ext_topo_dev_img_ver_high[index]);
2438*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2439*56429daeSEric Joyner 			  "%s: ext_topo_dev_img_ver_low[%d] = %d\n",
2440*56429daeSEric Joyner 			  prefix, index,
2441*56429daeSEric Joyner 			  caps->ext_topo_dev_img_ver_low[index]);
2442*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2443*56429daeSEric Joyner 			  "%s: ext_topo_dev_img_part_num[%d] = %d\n",
2444*56429daeSEric Joyner 			  prefix, index,
2445*56429daeSEric Joyner 			  caps->ext_topo_dev_img_part_num[index]);
2446*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2447*56429daeSEric Joyner 			  "%s: ext_topo_dev_img_load_en[%d] = %d\n",
2448*56429daeSEric Joyner 			  prefix, index,
2449*56429daeSEric Joyner 			  caps->ext_topo_dev_img_load_en[index]);
2450*56429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2451*56429daeSEric Joyner 			  "%s: ext_topo_dev_img_prog_en[%d] = %d\n",
2452*56429daeSEric Joyner 			  prefix, index,
2453*56429daeSEric Joyner 			  caps->ext_topo_dev_img_prog_en[index]);
2454*56429daeSEric Joyner 		break;
2455*56429daeSEric Joyner 	}
245671d10453SEric Joyner 	default:
24577d7af7f8SEric Joyner 		/* Not one of the recognized common capabilities */
24587d7af7f8SEric Joyner 		found = false;
245971d10453SEric Joyner 	}
246071d10453SEric Joyner 
24617d7af7f8SEric Joyner 	return found;
24627d7af7f8SEric Joyner }
246371d10453SEric Joyner 
24647d7af7f8SEric Joyner /**
24657d7af7f8SEric Joyner  * ice_recalc_port_limited_caps - Recalculate port limited capabilities
24667d7af7f8SEric Joyner  * @hw: pointer to the HW structure
24677d7af7f8SEric Joyner  * @caps: pointer to capabilities structure to fix
24687d7af7f8SEric Joyner  *
24697d7af7f8SEric Joyner  * Re-calculate the capabilities that are dependent on the number of physical
24707d7af7f8SEric Joyner  * ports; i.e. some features are not supported or function differently on
24717d7af7f8SEric Joyner  * devices with more than 4 ports.
24727d7af7f8SEric Joyner  */
24737d7af7f8SEric Joyner static void
24747d7af7f8SEric Joyner ice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
24757d7af7f8SEric Joyner {
24767d7af7f8SEric Joyner 	/* This assumes device capabilities are always scanned before function
24777d7af7f8SEric Joyner 	 * capabilities during the initialization flow.
247871d10453SEric Joyner 	 */
247971d10453SEric Joyner 	if (hw->dev_caps.num_funcs > 4) {
248071d10453SEric Joyner 		/* Max 4 TCs per port */
248171d10453SEric Joyner 		caps->maxtc = 4;
24827d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %d (based on #ports)\n",
248371d10453SEric Joyner 			  caps->maxtc);
248471d10453SEric Joyner 	}
248571d10453SEric Joyner }
248671d10453SEric Joyner 
248771d10453SEric Joyner /**
24887d7af7f8SEric Joyner  * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
248971d10453SEric Joyner  * @hw: pointer to the HW struct
24907d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
24917d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
24927d7af7f8SEric Joyner  *
24937d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VF.
24947d7af7f8SEric Joyner  */
24957d7af7f8SEric Joyner static void
24967d7af7f8SEric Joyner ice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
24977d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
24987d7af7f8SEric Joyner {
24997d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
25007d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(cap->logical_id);
25017d7af7f8SEric Joyner 
25027d7af7f8SEric Joyner 	func_p->num_allocd_vfs = number;
25037d7af7f8SEric Joyner 	func_p->vf_base_id = logical_id;
25047d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n",
25057d7af7f8SEric Joyner 		  func_p->num_allocd_vfs);
25067d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n",
25077d7af7f8SEric Joyner 		  func_p->vf_base_id);
25087d7af7f8SEric Joyner }
25097d7af7f8SEric Joyner 
25107d7af7f8SEric Joyner /**
25117d7af7f8SEric Joyner  * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
25127d7af7f8SEric Joyner  * @hw: pointer to the HW struct
25137d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
25147d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
25157d7af7f8SEric Joyner  *
25167d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VSI.
25177d7af7f8SEric Joyner  */
25187d7af7f8SEric Joyner static void
25197d7af7f8SEric Joyner ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
25207d7af7f8SEric Joyner 			struct ice_aqc_list_caps_elem *cap)
25217d7af7f8SEric Joyner {
25227d7af7f8SEric Joyner 	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
25237d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n",
25247d7af7f8SEric Joyner 		  LE32_TO_CPU(cap->number));
25257d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n",
25267d7af7f8SEric Joyner 		  func_p->guar_num_vsi);
25277d7af7f8SEric Joyner }
25287d7af7f8SEric Joyner 
25297d7af7f8SEric Joyner /**
25307d7af7f8SEric Joyner  * ice_parse_func_caps - Parse function capabilities
25317d7af7f8SEric Joyner  * @hw: pointer to the HW struct
25327d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
25337d7af7f8SEric Joyner  * @buf: buffer containing the function capability records
25347d7af7f8SEric Joyner  * @cap_count: the number of capabilities
25357d7af7f8SEric Joyner  *
25367d7af7f8SEric Joyner  * Helper function to parse function (0x000A) capabilities list. For
25377d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
25387d7af7f8SEric Joyner  * ice_parse_common_caps.
25397d7af7f8SEric Joyner  *
25407d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
25417d7af7f8SEric Joyner  * data into the function capabilities structured.
25427d7af7f8SEric Joyner  */
25437d7af7f8SEric Joyner static void
25447d7af7f8SEric Joyner ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
25457d7af7f8SEric Joyner 		    void *buf, u32 cap_count)
25467d7af7f8SEric Joyner {
25477d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
25487d7af7f8SEric Joyner 	u32 i;
25497d7af7f8SEric Joyner 
25507d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
25517d7af7f8SEric Joyner 
25527d7af7f8SEric Joyner 	ice_memset(func_p, 0, sizeof(*func_p), ICE_NONDMA_MEM);
25537d7af7f8SEric Joyner 
25547d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
25557d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
25567d7af7f8SEric Joyner 		bool found;
25577d7af7f8SEric Joyner 
25587d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &func_p->common_cap,
25597d7af7f8SEric Joyner 					      &cap_resp[i], "func caps");
25607d7af7f8SEric Joyner 
25617d7af7f8SEric Joyner 		switch (cap) {
25627d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
25637d7af7f8SEric Joyner 			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
25647d7af7f8SEric Joyner 			break;
25657d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
25667d7af7f8SEric Joyner 			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
25677d7af7f8SEric Joyner 			break;
25687d7af7f8SEric Joyner 		default:
25697d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
25707d7af7f8SEric Joyner 			if (!found)
25717d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n",
25727d7af7f8SEric Joyner 					  i, cap);
25737d7af7f8SEric Joyner 			break;
25747d7af7f8SEric Joyner 		}
25757d7af7f8SEric Joyner 	}
25767d7af7f8SEric Joyner 
25777d7af7f8SEric Joyner 	ice_print_led_caps(hw, &func_p->common_cap, "func caps", true);
25787d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &func_p->common_cap, "func caps", true);
25797d7af7f8SEric Joyner 
25807d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
25817d7af7f8SEric Joyner }
25827d7af7f8SEric Joyner 
25837d7af7f8SEric Joyner /**
25847d7af7f8SEric Joyner  * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
25857d7af7f8SEric Joyner  * @hw: pointer to the HW struct
25867d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
25877d7af7f8SEric Joyner  * @cap: capability element to parse
25887d7af7f8SEric Joyner  *
25897d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
25907d7af7f8SEric Joyner  */
25917d7af7f8SEric Joyner static void
25927d7af7f8SEric Joyner ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
25937d7af7f8SEric Joyner 			      struct ice_aqc_list_caps_elem *cap)
25947d7af7f8SEric Joyner {
25957d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
25967d7af7f8SEric Joyner 
25977d7af7f8SEric Joyner 	dev_p->num_funcs = ice_hweight32(number);
25987d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
25997d7af7f8SEric Joyner 		  dev_p->num_funcs);
2600*56429daeSEric Joyner 
26017d7af7f8SEric Joyner }
26027d7af7f8SEric Joyner 
26037d7af7f8SEric Joyner /**
26047d7af7f8SEric Joyner  * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
26057d7af7f8SEric Joyner  * @hw: pointer to the HW struct
26067d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
26077d7af7f8SEric Joyner  * @cap: capability element to parse
26087d7af7f8SEric Joyner  *
26097d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VF for device capabilities.
26107d7af7f8SEric Joyner  */
26117d7af7f8SEric Joyner static void
26127d7af7f8SEric Joyner ice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
26137d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *cap)
26147d7af7f8SEric Joyner {
26157d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
26167d7af7f8SEric Joyner 
26177d7af7f8SEric Joyner 	dev_p->num_vfs_exposed = number;
26187d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n",
26197d7af7f8SEric Joyner 		  dev_p->num_vfs_exposed);
26207d7af7f8SEric Joyner }
26217d7af7f8SEric Joyner 
26227d7af7f8SEric Joyner /**
26237d7af7f8SEric Joyner  * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
26247d7af7f8SEric Joyner  * @hw: pointer to the HW struct
26257d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
26267d7af7f8SEric Joyner  * @cap: capability element to parse
26277d7af7f8SEric Joyner  *
26287d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VSI for device capabilities.
26297d7af7f8SEric Joyner  */
26307d7af7f8SEric Joyner static void
26317d7af7f8SEric Joyner ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
26327d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
26337d7af7f8SEric Joyner {
26347d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
26357d7af7f8SEric Joyner 
26367d7af7f8SEric Joyner 	dev_p->num_vsi_allocd_to_host = number;
26377d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n",
26387d7af7f8SEric Joyner 		  dev_p->num_vsi_allocd_to_host);
26397d7af7f8SEric Joyner }
26407d7af7f8SEric Joyner 
26417d7af7f8SEric Joyner /**
26427d7af7f8SEric Joyner  * ice_parse_dev_caps - Parse device capabilities
26437d7af7f8SEric Joyner  * @hw: pointer to the HW struct
26447d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
26457d7af7f8SEric Joyner  * @buf: buffer containing the device capability records
26467d7af7f8SEric Joyner  * @cap_count: the number of capabilities
26477d7af7f8SEric Joyner  *
26487d7af7f8SEric Joyner  * Helper device to parse device (0x000B) capabilities list. For
26497d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
26507d7af7f8SEric Joyner  * ice_parse_common_caps.
26517d7af7f8SEric Joyner  *
26527d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
26537d7af7f8SEric Joyner  * data into the device capabilities structured.
26547d7af7f8SEric Joyner  */
26557d7af7f8SEric Joyner static void
26567d7af7f8SEric Joyner ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
26577d7af7f8SEric Joyner 		   void *buf, u32 cap_count)
26587d7af7f8SEric Joyner {
26597d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
26607d7af7f8SEric Joyner 	u32 i;
26617d7af7f8SEric Joyner 
26627d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
26637d7af7f8SEric Joyner 
26647d7af7f8SEric Joyner 	ice_memset(dev_p, 0, sizeof(*dev_p), ICE_NONDMA_MEM);
26657d7af7f8SEric Joyner 
26667d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
26677d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
26687d7af7f8SEric Joyner 		bool found;
26697d7af7f8SEric Joyner 
26707d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &dev_p->common_cap,
26717d7af7f8SEric Joyner 					      &cap_resp[i], "dev caps");
26727d7af7f8SEric Joyner 
26737d7af7f8SEric Joyner 		switch (cap) {
26747d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VALID_FUNCTIONS:
26757d7af7f8SEric Joyner 			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
26767d7af7f8SEric Joyner 			break;
26777d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
26787d7af7f8SEric Joyner 			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
26797d7af7f8SEric Joyner 			break;
26807d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
26817d7af7f8SEric Joyner 			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
26827d7af7f8SEric Joyner 			break;
26837d7af7f8SEric Joyner 		default:
26847d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
26857d7af7f8SEric Joyner 			if (!found)
26867d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%d]: 0x%x\n",
26877d7af7f8SEric Joyner 					  i, cap);
26887d7af7f8SEric Joyner 			break;
26897d7af7f8SEric Joyner 		}
26907d7af7f8SEric Joyner 	}
26917d7af7f8SEric Joyner 
26927d7af7f8SEric Joyner 	ice_print_led_caps(hw, &dev_p->common_cap, "dev caps", true);
26937d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &dev_p->common_cap, "dev caps", true);
26947d7af7f8SEric Joyner 
26957d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
26967d7af7f8SEric Joyner }
26977d7af7f8SEric Joyner 
26987d7af7f8SEric Joyner /**
26997d7af7f8SEric Joyner  * ice_aq_list_caps - query function/device capabilities
27007d7af7f8SEric Joyner  * @hw: pointer to the HW struct
27017d7af7f8SEric Joyner  * @buf: a buffer to hold the capabilities
27027d7af7f8SEric Joyner  * @buf_size: size of the buffer
27037d7af7f8SEric Joyner  * @cap_count: if not NULL, set to the number of capabilities reported
27047d7af7f8SEric Joyner  * @opc: capabilities type to discover, device or function
270571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
270671d10453SEric Joyner  *
27077d7af7f8SEric Joyner  * Get the function (0x000A) or device (0x000B) capabilities description from
27087d7af7f8SEric Joyner  * firmware and store it in the buffer.
27097d7af7f8SEric Joyner  *
27107d7af7f8SEric Joyner  * If the cap_count pointer is not NULL, then it is set to the number of
27117d7af7f8SEric Joyner  * capabilities firmware will report. Note that if the buffer size is too
27127d7af7f8SEric Joyner  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
27137d7af7f8SEric Joyner  * cap_count will still be updated in this case. It is recommended that the
27147d7af7f8SEric Joyner  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
27157d7af7f8SEric Joyner  * firmware could return) to avoid this.
271671d10453SEric Joyner  */
27177d7af7f8SEric Joyner static enum ice_status
27187d7af7f8SEric Joyner ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
271971d10453SEric Joyner 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
272071d10453SEric Joyner {
272171d10453SEric Joyner 	struct ice_aqc_list_caps *cmd;
272271d10453SEric Joyner 	struct ice_aq_desc desc;
272371d10453SEric Joyner 	enum ice_status status;
272471d10453SEric Joyner 
272571d10453SEric Joyner 	cmd = &desc.params.get_cap;
272671d10453SEric Joyner 
272771d10453SEric Joyner 	if (opc != ice_aqc_opc_list_func_caps &&
272871d10453SEric Joyner 	    opc != ice_aqc_opc_list_dev_caps)
272971d10453SEric Joyner 		return ICE_ERR_PARAM;
273071d10453SEric Joyner 
273171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
273271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
27337d7af7f8SEric Joyner 
27347d7af7f8SEric Joyner 	if (cap_count)
273571d10453SEric Joyner 		*cap_count = LE32_TO_CPU(cmd->count);
27367d7af7f8SEric Joyner 
273771d10453SEric Joyner 	return status;
273871d10453SEric Joyner }
273971d10453SEric Joyner 
274071d10453SEric Joyner /**
27417d7af7f8SEric Joyner  * ice_discover_dev_caps - Read and extract device capabilities
274271d10453SEric Joyner  * @hw: pointer to the hardware structure
27437d7af7f8SEric Joyner  * @dev_caps: pointer to device capabilities structure
27447d7af7f8SEric Joyner  *
27457d7af7f8SEric Joyner  * Read the device capabilities and extract them into the dev_caps structure
27467d7af7f8SEric Joyner  * for later use.
274771d10453SEric Joyner  */
274871d10453SEric Joyner static enum ice_status
27497d7af7f8SEric Joyner ice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
275071d10453SEric Joyner {
275171d10453SEric Joyner 	enum ice_status status;
27527d7af7f8SEric Joyner 	u32 cap_count = 0;
275371d10453SEric Joyner 	void *cbuf;
275471d10453SEric Joyner 
27557d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
275671d10453SEric Joyner 	if (!cbuf)
275771d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
275871d10453SEric Joyner 
27597d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
27607d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
27617d7af7f8SEric Joyner 	 * possible size that firmware can return.
27627d7af7f8SEric Joyner 	 */
27637d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
27647d7af7f8SEric Joyner 
27657d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
27667d7af7f8SEric Joyner 				  ice_aqc_opc_list_dev_caps, NULL);
27677d7af7f8SEric Joyner 	if (!status)
27687d7af7f8SEric Joyner 		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
276971d10453SEric Joyner 	ice_free(hw, cbuf);
277071d10453SEric Joyner 
27717d7af7f8SEric Joyner 	return status;
27727d7af7f8SEric Joyner }
277371d10453SEric Joyner 
27747d7af7f8SEric Joyner /**
27757d7af7f8SEric Joyner  * ice_discover_func_caps - Read and extract function capabilities
27767d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
27777d7af7f8SEric Joyner  * @func_caps: pointer to function capabilities structure
27787d7af7f8SEric Joyner  *
27797d7af7f8SEric Joyner  * Read the function capabilities and extract them into the func_caps structure
27807d7af7f8SEric Joyner  * for later use.
27817d7af7f8SEric Joyner  */
27827d7af7f8SEric Joyner static enum ice_status
27837d7af7f8SEric Joyner ice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
27847d7af7f8SEric Joyner {
27857d7af7f8SEric Joyner 	enum ice_status status;
27867d7af7f8SEric Joyner 	u32 cap_count = 0;
27877d7af7f8SEric Joyner 	void *cbuf;
27887d7af7f8SEric Joyner 
27897d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
27907d7af7f8SEric Joyner 	if (!cbuf)
27917d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
27927d7af7f8SEric Joyner 
27937d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
27947d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
27957d7af7f8SEric Joyner 	 * possible size that firmware can return.
27967d7af7f8SEric Joyner 	 */
27977d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
27987d7af7f8SEric Joyner 
27997d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
28007d7af7f8SEric Joyner 				  ice_aqc_opc_list_func_caps, NULL);
28017d7af7f8SEric Joyner 	if (!status)
28027d7af7f8SEric Joyner 		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
28037d7af7f8SEric Joyner 	ice_free(hw, cbuf);
280471d10453SEric Joyner 
280571d10453SEric Joyner 	return status;
280671d10453SEric Joyner }
280771d10453SEric Joyner 
280871d10453SEric Joyner /**
280971d10453SEric Joyner  * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
281071d10453SEric Joyner  * @hw: pointer to the hardware structure
281171d10453SEric Joyner  */
281271d10453SEric Joyner void ice_set_safe_mode_caps(struct ice_hw *hw)
281371d10453SEric Joyner {
281471d10453SEric Joyner 	struct ice_hw_func_caps *func_caps = &hw->func_caps;
281571d10453SEric Joyner 	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
2816d08b8680SEric Joyner 	struct ice_hw_common_caps cached_caps;
281771d10453SEric Joyner 	u32 num_funcs;
281871d10453SEric Joyner 
281971d10453SEric Joyner 	/* cache some func_caps values that should be restored after memset */
2820d08b8680SEric Joyner 	cached_caps = func_caps->common_cap;
282171d10453SEric Joyner 
282271d10453SEric Joyner 	/* unset func capabilities */
282371d10453SEric Joyner 	memset(func_caps, 0, sizeof(*func_caps));
282471d10453SEric Joyner 
2825d08b8680SEric Joyner #define ICE_RESTORE_FUNC_CAP(name) \
2826d08b8680SEric Joyner 	func_caps->common_cap.name = cached_caps.name
2827d08b8680SEric Joyner 
282871d10453SEric Joyner 	/* restore cached values */
2829d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(valid_functions);
2830d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(txq_first_id);
2831d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(rxq_first_id);
2832d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
2833d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(max_mtu);
2834d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(nvm_unified_update);
283571d10453SEric Joyner 
283671d10453SEric Joyner 	/* one Tx and one Rx queue in safe mode */
283771d10453SEric Joyner 	func_caps->common_cap.num_rxq = 1;
283871d10453SEric Joyner 	func_caps->common_cap.num_txq = 1;
283971d10453SEric Joyner 
284071d10453SEric Joyner 	/* two MSIX vectors, one for traffic and one for misc causes */
284171d10453SEric Joyner 	func_caps->common_cap.num_msix_vectors = 2;
284271d10453SEric Joyner 	func_caps->guar_num_vsi = 1;
284371d10453SEric Joyner 
284471d10453SEric Joyner 	/* cache some dev_caps values that should be restored after memset */
2845d08b8680SEric Joyner 	cached_caps = dev_caps->common_cap;
284671d10453SEric Joyner 	num_funcs = dev_caps->num_funcs;
284771d10453SEric Joyner 
284871d10453SEric Joyner 	/* unset dev capabilities */
284971d10453SEric Joyner 	memset(dev_caps, 0, sizeof(*dev_caps));
285071d10453SEric Joyner 
2851d08b8680SEric Joyner #define ICE_RESTORE_DEV_CAP(name) \
2852d08b8680SEric Joyner 	dev_caps->common_cap.name = cached_caps.name
2853d08b8680SEric Joyner 
285471d10453SEric Joyner 	/* restore cached values */
2855d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(valid_functions);
2856d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(txq_first_id);
2857d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(rxq_first_id);
2858d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(msix_vector_first_id);
2859d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(max_mtu);
2860d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(nvm_unified_update);
286171d10453SEric Joyner 	dev_caps->num_funcs = num_funcs;
286271d10453SEric Joyner 
286371d10453SEric Joyner 	/* one Tx and one Rx queue per function in safe mode */
286471d10453SEric Joyner 	dev_caps->common_cap.num_rxq = num_funcs;
286571d10453SEric Joyner 	dev_caps->common_cap.num_txq = num_funcs;
286671d10453SEric Joyner 
286771d10453SEric Joyner 	/* two MSIX vectors per function */
286871d10453SEric Joyner 	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
286971d10453SEric Joyner }
287071d10453SEric Joyner 
287171d10453SEric Joyner /**
287271d10453SEric Joyner  * ice_get_caps - get info about the HW
287371d10453SEric Joyner  * @hw: pointer to the hardware structure
287471d10453SEric Joyner  */
287571d10453SEric Joyner enum ice_status ice_get_caps(struct ice_hw *hw)
287671d10453SEric Joyner {
287771d10453SEric Joyner 	enum ice_status status;
287871d10453SEric Joyner 
28797d7af7f8SEric Joyner 	status = ice_discover_dev_caps(hw, &hw->dev_caps);
28807d7af7f8SEric Joyner 	if (status)
288171d10453SEric Joyner 		return status;
28827d7af7f8SEric Joyner 
28837d7af7f8SEric Joyner 	return ice_discover_func_caps(hw, &hw->func_caps);
288471d10453SEric Joyner }
288571d10453SEric Joyner 
288671d10453SEric Joyner /**
288771d10453SEric Joyner  * ice_aq_manage_mac_write - manage MAC address write command
288871d10453SEric Joyner  * @hw: pointer to the HW struct
288971d10453SEric Joyner  * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
289071d10453SEric Joyner  * @flags: flags to control write behavior
289171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
289271d10453SEric Joyner  *
289371d10453SEric Joyner  * This function is used to write MAC address to the NVM (0x0108).
289471d10453SEric Joyner  */
289571d10453SEric Joyner enum ice_status
289671d10453SEric Joyner ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
289771d10453SEric Joyner 			struct ice_sq_cd *cd)
289871d10453SEric Joyner {
289971d10453SEric Joyner 	struct ice_aqc_manage_mac_write *cmd;
290071d10453SEric Joyner 	struct ice_aq_desc desc;
290171d10453SEric Joyner 
290271d10453SEric Joyner 	cmd = &desc.params.mac_write;
290371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
290471d10453SEric Joyner 
290571d10453SEric Joyner 	cmd->flags = flags;
2906d08b8680SEric Joyner 	ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_NONDMA);
290771d10453SEric Joyner 
290871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
290971d10453SEric Joyner }
291071d10453SEric Joyner 
291171d10453SEric Joyner /**
291271d10453SEric Joyner  * ice_aq_clear_pxe_mode
291371d10453SEric Joyner  * @hw: pointer to the HW struct
291471d10453SEric Joyner  *
291571d10453SEric Joyner  * Tell the firmware that the driver is taking over from PXE (0x0110).
291671d10453SEric Joyner  */
291771d10453SEric Joyner static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw)
291871d10453SEric Joyner {
291971d10453SEric Joyner 	struct ice_aq_desc desc;
292071d10453SEric Joyner 
292171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
292271d10453SEric Joyner 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
292371d10453SEric Joyner 
292471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
292571d10453SEric Joyner }
292671d10453SEric Joyner 
292771d10453SEric Joyner /**
292871d10453SEric Joyner  * ice_clear_pxe_mode - clear pxe operations mode
292971d10453SEric Joyner  * @hw: pointer to the HW struct
293071d10453SEric Joyner  *
293171d10453SEric Joyner  * Make sure all PXE mode settings are cleared, including things
293271d10453SEric Joyner  * like descriptor fetch/write-back mode.
293371d10453SEric Joyner  */
293471d10453SEric Joyner void ice_clear_pxe_mode(struct ice_hw *hw)
293571d10453SEric Joyner {
293671d10453SEric Joyner 	if (ice_check_sq_alive(hw, &hw->adminq))
293771d10453SEric Joyner 		ice_aq_clear_pxe_mode(hw);
293871d10453SEric Joyner }
293971d10453SEric Joyner 
294071d10453SEric Joyner /**
294171d10453SEric Joyner  * ice_aq_set_port_params - set physical port parameters.
294271d10453SEric Joyner  * @pi: pointer to the port info struct
294371d10453SEric Joyner  * @bad_frame_vsi: defines the VSI to which bad frames are forwarded
294471d10453SEric Joyner  * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI
294571d10453SEric Joyner  * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded
294671d10453SEric Joyner  * @double_vlan: if set double VLAN is enabled
294771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
294871d10453SEric Joyner  *
294971d10453SEric Joyner  * Set Physical port parameters (0x0203)
295071d10453SEric Joyner  */
295171d10453SEric Joyner enum ice_status
295271d10453SEric Joyner ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
295371d10453SEric Joyner 		       bool save_bad_pac, bool pad_short_pac, bool double_vlan,
295471d10453SEric Joyner 		       struct ice_sq_cd *cd)
295571d10453SEric Joyner 
295671d10453SEric Joyner {
295771d10453SEric Joyner 	struct ice_aqc_set_port_params *cmd;
295871d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
295971d10453SEric Joyner 	struct ice_aq_desc desc;
296071d10453SEric Joyner 	u16 cmd_flags = 0;
296171d10453SEric Joyner 
296271d10453SEric Joyner 	cmd = &desc.params.set_port_params;
296371d10453SEric Joyner 
296471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
296571d10453SEric Joyner 	cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi);
296671d10453SEric Joyner 	if (save_bad_pac)
296771d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS;
296871d10453SEric Joyner 	if (pad_short_pac)
296971d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS;
297071d10453SEric Joyner 	if (double_vlan)
297171d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
297271d10453SEric Joyner 	cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
297371d10453SEric Joyner 
297471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
297571d10453SEric Joyner }
297671d10453SEric Joyner 
297771d10453SEric Joyner /**
2978*56429daeSEric Joyner  * ice_is_100m_speed_supported
2979*56429daeSEric Joyner  * @hw: pointer to the HW struct
2980*56429daeSEric Joyner  *
2981*56429daeSEric Joyner  * returns true if 100M speeds are supported by the device,
2982*56429daeSEric Joyner  * false otherwise.
2983*56429daeSEric Joyner  */
2984*56429daeSEric Joyner bool ice_is_100m_speed_supported(struct ice_hw *hw)
2985*56429daeSEric Joyner {
2986*56429daeSEric Joyner 	switch (hw->device_id) {
2987*56429daeSEric Joyner 	case ICE_DEV_ID_E822C_10G_BASE_T:
2988*56429daeSEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
2989*56429daeSEric Joyner 	case ICE_DEV_ID_E822L_10G_BASE_T:
2990*56429daeSEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
2991*56429daeSEric Joyner 	case ICE_DEV_ID_E823L_10G_BASE_T:
2992*56429daeSEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
2993*56429daeSEric Joyner 		return true;
2994*56429daeSEric Joyner 	default:
2995*56429daeSEric Joyner 		return false;
2996*56429daeSEric Joyner 	}
2997*56429daeSEric Joyner }
2998*56429daeSEric Joyner 
2999*56429daeSEric Joyner /**
300071d10453SEric Joyner  * ice_get_link_speed_based_on_phy_type - returns link speed
300171d10453SEric Joyner  * @phy_type_low: lower part of phy_type
300271d10453SEric Joyner  * @phy_type_high: higher part of phy_type
300371d10453SEric Joyner  *
300471d10453SEric Joyner  * This helper function will convert an entry in PHY type structure
300571d10453SEric Joyner  * [phy_type_low, phy_type_high] to its corresponding link speed.
300671d10453SEric Joyner  * Note: In the structure of [phy_type_low, phy_type_high], there should
300771d10453SEric Joyner  * be one bit set, as this function will convert one PHY type to its
300871d10453SEric Joyner  * speed.
300971d10453SEric Joyner  * If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
301071d10453SEric Joyner  * If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
301171d10453SEric Joyner  */
301271d10453SEric Joyner static u16
301371d10453SEric Joyner ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
301471d10453SEric Joyner {
301571d10453SEric Joyner 	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
301671d10453SEric Joyner 	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
301771d10453SEric Joyner 
301871d10453SEric Joyner 	switch (phy_type_low) {
301971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100BASE_TX:
302071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100M_SGMII:
302171d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
302271d10453SEric Joyner 		break;
302371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_T:
302471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_SX:
302571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_LX:
302671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_KX:
302771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1G_SGMII:
302871d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
302971d10453SEric Joyner 		break;
303071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_T:
303171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_X:
303271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_KX:
303371d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
303471d10453SEric Joyner 		break;
303571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_T:
303671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_KR:
303771d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
303871d10453SEric Joyner 		break;
303971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_T:
304071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
304171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_SR:
304271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_LR:
304371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
304471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
304571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
304671d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
304771d10453SEric Joyner 		break;
304871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_T:
304971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR:
305071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
305171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
305271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_SR:
305371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_LR:
305471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR:
305571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
305671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
305771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
305871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
305971d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
306071d10453SEric Joyner 		break;
306171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
306271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
306371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
306471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
306571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
306671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI:
306771d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
306871d10453SEric Joyner 		break;
306971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
307071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
307171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
307271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
307371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
307471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2:
307571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
307671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2:
307771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CP:
307871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR:
307971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_FR:
308071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR:
308171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
308271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
308371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1:
308471d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
308571d10453SEric Joyner 		break;
308671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
308771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
308871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
308971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
309071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
309171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4:
309271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
309371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4:
309471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
309571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
309671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
309771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
309871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_DR:
309971d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
310071d10453SEric Joyner 		break;
310171d10453SEric Joyner 	default:
310271d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
310371d10453SEric Joyner 		break;
310471d10453SEric Joyner 	}
310571d10453SEric Joyner 
310671d10453SEric Joyner 	switch (phy_type_high) {
310771d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
310871d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
310971d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
311071d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
311171d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2:
311271d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
311371d10453SEric Joyner 		break;
311471d10453SEric Joyner 	default:
311571d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
311671d10453SEric Joyner 		break;
311771d10453SEric Joyner 	}
311871d10453SEric Joyner 
311971d10453SEric Joyner 	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
312071d10453SEric Joyner 	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
312171d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
312271d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
312371d10453SEric Joyner 		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
312471d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
312571d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
312671d10453SEric Joyner 		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
312771d10453SEric Joyner 		return speed_phy_type_low;
312871d10453SEric Joyner 	else
312971d10453SEric Joyner 		return speed_phy_type_high;
313071d10453SEric Joyner }
313171d10453SEric Joyner 
313271d10453SEric Joyner /**
313371d10453SEric Joyner  * ice_update_phy_type
313471d10453SEric Joyner  * @phy_type_low: pointer to the lower part of phy_type
313571d10453SEric Joyner  * @phy_type_high: pointer to the higher part of phy_type
313671d10453SEric Joyner  * @link_speeds_bitmap: targeted link speeds bitmap
313771d10453SEric Joyner  *
313871d10453SEric Joyner  * Note: For the link_speeds_bitmap structure, you can check it at
313971d10453SEric Joyner  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
314071d10453SEric Joyner  * link_speeds_bitmap include multiple speeds.
314171d10453SEric Joyner  *
314271d10453SEric Joyner  * Each entry in this [phy_type_low, phy_type_high] structure will
314371d10453SEric Joyner  * present a certain link speed. This helper function will turn on bits
314471d10453SEric Joyner  * in [phy_type_low, phy_type_high] structure based on the value of
314571d10453SEric Joyner  * link_speeds_bitmap input parameter.
314671d10453SEric Joyner  */
314771d10453SEric Joyner void
314871d10453SEric Joyner ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
314971d10453SEric Joyner 		    u16 link_speeds_bitmap)
315071d10453SEric Joyner {
315171d10453SEric Joyner 	u64 pt_high;
315271d10453SEric Joyner 	u64 pt_low;
315371d10453SEric Joyner 	int index;
315471d10453SEric Joyner 	u16 speed;
315571d10453SEric Joyner 
315671d10453SEric Joyner 	/* We first check with low part of phy_type */
315771d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
315871d10453SEric Joyner 		pt_low = BIT_ULL(index);
315971d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
316071d10453SEric Joyner 
316171d10453SEric Joyner 		if (link_speeds_bitmap & speed)
316271d10453SEric Joyner 			*phy_type_low |= BIT_ULL(index);
316371d10453SEric Joyner 	}
316471d10453SEric Joyner 
316571d10453SEric Joyner 	/* We then check with high part of phy_type */
316671d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
316771d10453SEric Joyner 		pt_high = BIT_ULL(index);
316871d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
316971d10453SEric Joyner 
317071d10453SEric Joyner 		if (link_speeds_bitmap & speed)
317171d10453SEric Joyner 			*phy_type_high |= BIT_ULL(index);
317271d10453SEric Joyner 	}
317371d10453SEric Joyner }
317471d10453SEric Joyner 
317571d10453SEric Joyner /**
317671d10453SEric Joyner  * ice_aq_set_phy_cfg
317771d10453SEric Joyner  * @hw: pointer to the HW struct
317871d10453SEric Joyner  * @pi: port info structure of the interested logical port
317971d10453SEric Joyner  * @cfg: structure with PHY configuration data to be set
318071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
318171d10453SEric Joyner  *
318271d10453SEric Joyner  * Set the various PHY configuration parameters supported on the Port.
318371d10453SEric Joyner  * One or more of the Set PHY config parameters may be ignored in an MFP
318471d10453SEric Joyner  * mode as the PF may not have the privilege to set some of the PHY Config
318571d10453SEric Joyner  * parameters. This status will be indicated by the command response (0x0601).
318671d10453SEric Joyner  */
318771d10453SEric Joyner enum ice_status
318871d10453SEric Joyner ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
318971d10453SEric Joyner 		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
319071d10453SEric Joyner {
319171d10453SEric Joyner 	struct ice_aq_desc desc;
319271d10453SEric Joyner 	enum ice_status status;
319371d10453SEric Joyner 
319471d10453SEric Joyner 	if (!cfg)
319571d10453SEric Joyner 		return ICE_ERR_PARAM;
319671d10453SEric Joyner 
319771d10453SEric Joyner 	/* Ensure that only valid bits of cfg->caps can be turned on. */
319871d10453SEric Joyner 	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
31997d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
320071d10453SEric Joyner 			  cfg->caps);
320171d10453SEric Joyner 
320271d10453SEric Joyner 		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
320371d10453SEric Joyner 	}
320471d10453SEric Joyner 
320571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
320671d10453SEric Joyner 	desc.params.set_phy.lport_num = pi->lport;
320771d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
320871d10453SEric Joyner 
32097d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
321071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
321171d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_low));
321271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
321371d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_high));
321471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", cfg->caps);
321571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
321671d10453SEric Joyner 		  cfg->low_power_ctrl_an);
321771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", cfg->eee_cap);
321871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n", cfg->eeer_value);
32197d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_fec_opt = 0x%x\n",
32207d7af7f8SEric Joyner 		  cfg->link_fec_opt);
322171d10453SEric Joyner 
322271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
322371d10453SEric Joyner 
32247d7af7f8SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
32257d7af7f8SEric Joyner 		status = ICE_SUCCESS;
32267d7af7f8SEric Joyner 
322771d10453SEric Joyner 	if (!status)
322871d10453SEric Joyner 		pi->phy.curr_user_phy_cfg = *cfg;
322971d10453SEric Joyner 
323071d10453SEric Joyner 	return status;
323171d10453SEric Joyner }
323271d10453SEric Joyner 
323371d10453SEric Joyner /**
323471d10453SEric Joyner  * ice_update_link_info - update status of the HW network link
323571d10453SEric Joyner  * @pi: port info structure of the interested logical port
323671d10453SEric Joyner  */
323771d10453SEric Joyner enum ice_status ice_update_link_info(struct ice_port_info *pi)
323871d10453SEric Joyner {
323971d10453SEric Joyner 	struct ice_link_status *li;
324071d10453SEric Joyner 	enum ice_status status;
324171d10453SEric Joyner 
324271d10453SEric Joyner 	if (!pi)
324371d10453SEric Joyner 		return ICE_ERR_PARAM;
324471d10453SEric Joyner 
324571d10453SEric Joyner 	li = &pi->phy.link_info;
324671d10453SEric Joyner 
324771d10453SEric Joyner 	status = ice_aq_get_link_info(pi, true, NULL, NULL);
324871d10453SEric Joyner 	if (status)
324971d10453SEric Joyner 		return status;
325071d10453SEric Joyner 
325171d10453SEric Joyner 	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
325271d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
325371d10453SEric Joyner 		struct ice_hw *hw;
325471d10453SEric Joyner 
325571d10453SEric Joyner 		hw = pi->hw;
325671d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
325771d10453SEric Joyner 			ice_malloc(hw, sizeof(*pcaps));
325871d10453SEric Joyner 		if (!pcaps)
325971d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
326071d10453SEric Joyner 
32619cf1841cSEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
326271d10453SEric Joyner 					     pcaps, NULL);
326371d10453SEric Joyner 
3264d08b8680SEric Joyner 		if (status == ICE_SUCCESS)
3265d08b8680SEric Joyner 			ice_memcpy(li->module_type, &pcaps->module_type,
3266d08b8680SEric Joyner 				   sizeof(li->module_type),
3267d08b8680SEric Joyner 				   ICE_NONDMA_TO_NONDMA);
3268d08b8680SEric Joyner 
326971d10453SEric Joyner 		ice_free(hw, pcaps);
327071d10453SEric Joyner 	}
327171d10453SEric Joyner 
327271d10453SEric Joyner 	return status;
327371d10453SEric Joyner }
327471d10453SEric Joyner 
327571d10453SEric Joyner /**
327671d10453SEric Joyner  * ice_cache_phy_user_req
327771d10453SEric Joyner  * @pi: port information structure
327871d10453SEric Joyner  * @cache_data: PHY logging data
327971d10453SEric Joyner  * @cache_mode: PHY logging mode
328071d10453SEric Joyner  *
328171d10453SEric Joyner  * Log the user request on (FC, FEC, SPEED) for later user.
328271d10453SEric Joyner  */
328371d10453SEric Joyner static void
328471d10453SEric Joyner ice_cache_phy_user_req(struct ice_port_info *pi,
328571d10453SEric Joyner 		       struct ice_phy_cache_mode_data cache_data,
328671d10453SEric Joyner 		       enum ice_phy_cache_mode cache_mode)
328771d10453SEric Joyner {
328871d10453SEric Joyner 	if (!pi)
328971d10453SEric Joyner 		return;
329071d10453SEric Joyner 
329171d10453SEric Joyner 	switch (cache_mode) {
329271d10453SEric Joyner 	case ICE_FC_MODE:
329371d10453SEric Joyner 		pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
329471d10453SEric Joyner 		break;
329571d10453SEric Joyner 	case ICE_SPEED_MODE:
329671d10453SEric Joyner 		pi->phy.curr_user_speed_req =
329771d10453SEric Joyner 			cache_data.data.curr_user_speed_req;
329871d10453SEric Joyner 		break;
329971d10453SEric Joyner 	case ICE_FEC_MODE:
330071d10453SEric Joyner 		pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
330171d10453SEric Joyner 		break;
330271d10453SEric Joyner 	default:
330371d10453SEric Joyner 		break;
330471d10453SEric Joyner 	}
330571d10453SEric Joyner }
330671d10453SEric Joyner 
330771d10453SEric Joyner /**
330871d10453SEric Joyner  * ice_caps_to_fc_mode
330971d10453SEric Joyner  * @caps: PHY capabilities
331071d10453SEric Joyner  *
331171d10453SEric Joyner  * Convert PHY FC capabilities to ice FC mode
331271d10453SEric Joyner  */
331371d10453SEric Joyner enum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
331471d10453SEric Joyner {
331571d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
331671d10453SEric Joyner 	    caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
331771d10453SEric Joyner 		return ICE_FC_FULL;
331871d10453SEric Joyner 
331971d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
332071d10453SEric Joyner 		return ICE_FC_TX_PAUSE;
332171d10453SEric Joyner 
332271d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
332371d10453SEric Joyner 		return ICE_FC_RX_PAUSE;
332471d10453SEric Joyner 
332571d10453SEric Joyner 	return ICE_FC_NONE;
332671d10453SEric Joyner }
332771d10453SEric Joyner 
332871d10453SEric Joyner /**
332971d10453SEric Joyner  * ice_caps_to_fec_mode
333071d10453SEric Joyner  * @caps: PHY capabilities
333171d10453SEric Joyner  * @fec_options: Link FEC options
333271d10453SEric Joyner  *
333371d10453SEric Joyner  * Convert PHY FEC capabilities to ice FEC mode
333471d10453SEric Joyner  */
333571d10453SEric Joyner enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
333671d10453SEric Joyner {
333771d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_AUTO_FEC)
333871d10453SEric Joyner 		return ICE_FEC_AUTO;
333971d10453SEric Joyner 
334071d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
334171d10453SEric Joyner 			   ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
334271d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
334371d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_REQ))
334471d10453SEric Joyner 		return ICE_FEC_BASER;
334571d10453SEric Joyner 
334671d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
334771d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_544_REQ |
334871d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
334971d10453SEric Joyner 		return ICE_FEC_RS;
335071d10453SEric Joyner 
335171d10453SEric Joyner 	return ICE_FEC_NONE;
335271d10453SEric Joyner }
335371d10453SEric Joyner 
335471d10453SEric Joyner /**
33557d7af7f8SEric Joyner  * ice_cfg_phy_fc - Configure PHY FC data based on FC mode
335671d10453SEric Joyner  * @pi: port information structure
33577d7af7f8SEric Joyner  * @cfg: PHY configuration data to set FC mode
33587d7af7f8SEric Joyner  * @req_mode: FC mode to configure
335971d10453SEric Joyner  */
33607d7af7f8SEric Joyner static enum ice_status
33617d7af7f8SEric Joyner ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
33627d7af7f8SEric Joyner 	       enum ice_fc_mode req_mode)
336371d10453SEric Joyner {
336471d10453SEric Joyner 	struct ice_phy_cache_mode_data cache_data;
33657d7af7f8SEric Joyner 	u8 pause_mask = 0x0;
33667d7af7f8SEric Joyner 
33677d7af7f8SEric Joyner 	if (!pi || !cfg)
33687d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
33697d7af7f8SEric Joyner 	switch (req_mode) {
33707d7af7f8SEric Joyner 	case ICE_FC_AUTO:
33717d7af7f8SEric Joyner 	{
337271d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
337371d10453SEric Joyner 		enum ice_status status;
337471d10453SEric Joyner 
337571d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
33767d7af7f8SEric Joyner 			ice_malloc(pi->hw, sizeof(*pcaps));
337771d10453SEric Joyner 		if (!pcaps)
337871d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
337971d10453SEric Joyner 		/* Query the value of FC that both the NIC and attached media
338071d10453SEric Joyner 		 * can do.
338171d10453SEric Joyner 		 */
33829cf1841cSEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
338371d10453SEric Joyner 					     pcaps, NULL);
338471d10453SEric Joyner 		if (status) {
33857d7af7f8SEric Joyner 			ice_free(pi->hw, pcaps);
33867d7af7f8SEric Joyner 			return status;
338771d10453SEric Joyner 		}
338871d10453SEric Joyner 
338971d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE;
339071d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE;
33917d7af7f8SEric Joyner 
33927d7af7f8SEric Joyner 		ice_free(pi->hw, pcaps);
339371d10453SEric Joyner 		break;
33947d7af7f8SEric Joyner 	}
339571d10453SEric Joyner 	case ICE_FC_FULL:
339671d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
339771d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
339871d10453SEric Joyner 		break;
339971d10453SEric Joyner 	case ICE_FC_RX_PAUSE:
340071d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
340171d10453SEric Joyner 		break;
340271d10453SEric Joyner 	case ICE_FC_TX_PAUSE:
340371d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
340471d10453SEric Joyner 		break;
340571d10453SEric Joyner 	default:
340671d10453SEric Joyner 		break;
340771d10453SEric Joyner 	}
340871d10453SEric Joyner 
34097d7af7f8SEric Joyner 	/* clear the old pause settings */
34107d7af7f8SEric Joyner 	cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
34117d7af7f8SEric Joyner 		ICE_AQC_PHY_EN_RX_LINK_PAUSE);
34127d7af7f8SEric Joyner 
34137d7af7f8SEric Joyner 	/* set the new capabilities */
34147d7af7f8SEric Joyner 	cfg->caps |= pause_mask;
34157d7af7f8SEric Joyner 
34167d7af7f8SEric Joyner 	/* Cache user FC request */
34177d7af7f8SEric Joyner 	cache_data.data.curr_user_fc_req = req_mode;
34187d7af7f8SEric Joyner 	ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
34197d7af7f8SEric Joyner 
34207d7af7f8SEric Joyner 	return ICE_SUCCESS;
34217d7af7f8SEric Joyner }
34227d7af7f8SEric Joyner 
34237d7af7f8SEric Joyner /**
34247d7af7f8SEric Joyner  * ice_set_fc
34257d7af7f8SEric Joyner  * @pi: port information structure
34267d7af7f8SEric Joyner  * @aq_failures: pointer to status code, specific to ice_set_fc routine
34277d7af7f8SEric Joyner  * @ena_auto_link_update: enable automatic link update
34287d7af7f8SEric Joyner  *
34297d7af7f8SEric Joyner  * Set the requested flow control mode.
34307d7af7f8SEric Joyner  */
34317d7af7f8SEric Joyner enum ice_status
34327d7af7f8SEric Joyner ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
34337d7af7f8SEric Joyner {
34347d7af7f8SEric Joyner 	struct ice_aqc_set_phy_cfg_data  cfg = { 0 };
34357d7af7f8SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
34367d7af7f8SEric Joyner 	enum ice_status status;
34377d7af7f8SEric Joyner 	struct ice_hw *hw;
34387d7af7f8SEric Joyner 
34397d7af7f8SEric Joyner 	if (!pi || !aq_failures)
34407d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
34417d7af7f8SEric Joyner 
34427d7af7f8SEric Joyner 	*aq_failures = 0;
34437d7af7f8SEric Joyner 	hw = pi->hw;
34447d7af7f8SEric Joyner 
34457d7af7f8SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
34467d7af7f8SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
34477d7af7f8SEric Joyner 	if (!pcaps)
34487d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
34497d7af7f8SEric Joyner 
345071d10453SEric Joyner 	/* Get the current PHY config */
34519cf1841cSEric Joyner 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG,
34529cf1841cSEric Joyner 				     pcaps, NULL);
34539cf1841cSEric Joyner 
345471d10453SEric Joyner 	if (status) {
345571d10453SEric Joyner 		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
345671d10453SEric Joyner 		goto out;
345771d10453SEric Joyner 	}
345871d10453SEric Joyner 
345971d10453SEric Joyner 	ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
346071d10453SEric Joyner 
34617d7af7f8SEric Joyner 	/* Configure the set PHY data */
34627d7af7f8SEric Joyner 	status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
34637d7af7f8SEric Joyner 	if (status) {
34647d7af7f8SEric Joyner 		if (status != ICE_ERR_BAD_PTR)
34657d7af7f8SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
346671d10453SEric Joyner 
34677d7af7f8SEric Joyner 		goto out;
34687d7af7f8SEric Joyner 	}
346971d10453SEric Joyner 
347071d10453SEric Joyner 	/* If the capabilities have changed, then set the new config */
347171d10453SEric Joyner 	if (cfg.caps != pcaps->caps) {
347271d10453SEric Joyner 		int retry_count, retry_max = 10;
347371d10453SEric Joyner 
347471d10453SEric Joyner 		/* Auto restart link so settings take effect */
347571d10453SEric Joyner 		if (ena_auto_link_update)
347671d10453SEric Joyner 			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
347771d10453SEric Joyner 
347871d10453SEric Joyner 		status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
347971d10453SEric Joyner 		if (status) {
348071d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
348171d10453SEric Joyner 			goto out;
348271d10453SEric Joyner 		}
348371d10453SEric Joyner 
348471d10453SEric Joyner 		/* Update the link info
348571d10453SEric Joyner 		 * It sometimes takes a really long time for link to
348671d10453SEric Joyner 		 * come back from the atomic reset. Thus, we wait a
348771d10453SEric Joyner 		 * little bit.
348871d10453SEric Joyner 		 */
348971d10453SEric Joyner 		for (retry_count = 0; retry_count < retry_max; retry_count++) {
349071d10453SEric Joyner 			status = ice_update_link_info(pi);
349171d10453SEric Joyner 
349271d10453SEric Joyner 			if (status == ICE_SUCCESS)
349371d10453SEric Joyner 				break;
349471d10453SEric Joyner 
349571d10453SEric Joyner 			ice_msec_delay(100, true);
349671d10453SEric Joyner 		}
349771d10453SEric Joyner 
349871d10453SEric Joyner 		if (status)
349971d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
350071d10453SEric Joyner 	}
350171d10453SEric Joyner 
350271d10453SEric Joyner out:
350371d10453SEric Joyner 	ice_free(hw, pcaps);
350471d10453SEric Joyner 	return status;
350571d10453SEric Joyner }
350671d10453SEric Joyner 
350771d10453SEric Joyner /**
350871d10453SEric Joyner  * ice_phy_caps_equals_cfg
350971d10453SEric Joyner  * @phy_caps: PHY capabilities
351071d10453SEric Joyner  * @phy_cfg: PHY configuration
351171d10453SEric Joyner  *
351271d10453SEric Joyner  * Helper function to determine if PHY capabilities matches PHY
351371d10453SEric Joyner  * configuration
351471d10453SEric Joyner  */
351571d10453SEric Joyner bool
351671d10453SEric Joyner ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
351771d10453SEric Joyner 			struct ice_aqc_set_phy_cfg_data *phy_cfg)
351871d10453SEric Joyner {
351971d10453SEric Joyner 	u8 caps_mask, cfg_mask;
352071d10453SEric Joyner 
352171d10453SEric Joyner 	if (!phy_caps || !phy_cfg)
352271d10453SEric Joyner 		return false;
352371d10453SEric Joyner 
352471d10453SEric Joyner 	/* These bits are not common between capabilities and configuration.
352571d10453SEric Joyner 	 * Do not use them to determine equality.
352671d10453SEric Joyner 	 */
352771d10453SEric Joyner 	caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
352871d10453SEric Joyner 					      ICE_AQC_PHY_EN_MOD_QUAL);
352971d10453SEric Joyner 	cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
353071d10453SEric Joyner 
353171d10453SEric Joyner 	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
353271d10453SEric Joyner 	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
353371d10453SEric Joyner 	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
353471d10453SEric Joyner 	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
353571d10453SEric Joyner 	    phy_caps->eee_cap != phy_cfg->eee_cap ||
353671d10453SEric Joyner 	    phy_caps->eeer_value != phy_cfg->eeer_value ||
353771d10453SEric Joyner 	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
353871d10453SEric Joyner 		return false;
353971d10453SEric Joyner 
354071d10453SEric Joyner 	return true;
354171d10453SEric Joyner }
354271d10453SEric Joyner 
354371d10453SEric Joyner /**
354471d10453SEric Joyner  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
354571d10453SEric Joyner  * @pi: port information structure
3546*56429daeSEric Joyner  * @caps: PHY ability structure to copy data from
354771d10453SEric Joyner  * @cfg: PHY configuration structure to copy data to
354871d10453SEric Joyner  *
354971d10453SEric Joyner  * Helper function to copy AQC PHY get ability data to PHY set configuration
355071d10453SEric Joyner  * data structure
355171d10453SEric Joyner  */
355271d10453SEric Joyner void
355371d10453SEric Joyner ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
355471d10453SEric Joyner 			 struct ice_aqc_get_phy_caps_data *caps,
355571d10453SEric Joyner 			 struct ice_aqc_set_phy_cfg_data *cfg)
355671d10453SEric Joyner {
355771d10453SEric Joyner 	if (!pi || !caps || !cfg)
355871d10453SEric Joyner 		return;
355971d10453SEric Joyner 
356071d10453SEric Joyner 	ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
356171d10453SEric Joyner 	cfg->phy_type_low = caps->phy_type_low;
356271d10453SEric Joyner 	cfg->phy_type_high = caps->phy_type_high;
356371d10453SEric Joyner 	cfg->caps = caps->caps;
356471d10453SEric Joyner 	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
356571d10453SEric Joyner 	cfg->eee_cap = caps->eee_cap;
356671d10453SEric Joyner 	cfg->eeer_value = caps->eeer_value;
356771d10453SEric Joyner 	cfg->link_fec_opt = caps->link_fec_options;
356871d10453SEric Joyner 	cfg->module_compliance_enforcement =
356971d10453SEric Joyner 		caps->module_compliance_enforcement;
357071d10453SEric Joyner }
357171d10453SEric Joyner 
357271d10453SEric Joyner /**
357371d10453SEric Joyner  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
357471d10453SEric Joyner  * @pi: port information structure
357571d10453SEric Joyner  * @cfg: PHY configuration data to set FEC mode
357671d10453SEric Joyner  * @fec: FEC mode to configure
357771d10453SEric Joyner  */
357871d10453SEric Joyner enum ice_status
357971d10453SEric Joyner ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
358071d10453SEric Joyner 		enum ice_fec_mode fec)
358171d10453SEric Joyner {
358271d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
358371d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
358471d10453SEric Joyner 	struct ice_hw *hw;
358571d10453SEric Joyner 
358671d10453SEric Joyner 	if (!pi || !cfg)
358771d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
358871d10453SEric Joyner 
358971d10453SEric Joyner 	hw = pi->hw;
359071d10453SEric Joyner 
359171d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
359271d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
359371d10453SEric Joyner 	if (!pcaps)
359471d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
359571d10453SEric Joyner 
35969cf1841cSEric Joyner 	status = ice_aq_get_phy_caps(pi, false,
35979cf1841cSEric Joyner 				     (ice_fw_supports_report_dflt_cfg(hw) ?
35989cf1841cSEric Joyner 				      ICE_AQC_REPORT_DFLT_CFG :
35999cf1841cSEric Joyner 				      ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);
36009cf1841cSEric Joyner 
360171d10453SEric Joyner 	if (status)
360271d10453SEric Joyner 		goto out;
360371d10453SEric Joyner 
36047d7af7f8SEric Joyner 	cfg->caps |= (pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC);
36057d7af7f8SEric Joyner 	cfg->link_fec_opt = pcaps->link_fec_options;
36067d7af7f8SEric Joyner 
360771d10453SEric Joyner 	switch (fec) {
360871d10453SEric Joyner 	case ICE_FEC_BASER:
360971d10453SEric Joyner 		/* Clear RS bits, and AND BASE-R ability
361071d10453SEric Joyner 		 * bits and OR request bits.
361171d10453SEric Joyner 		 */
361271d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
361371d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
361471d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
361571d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_REQ;
361671d10453SEric Joyner 		break;
361771d10453SEric Joyner 	case ICE_FEC_RS:
361871d10453SEric Joyner 		/* Clear BASE-R bits, and AND RS ability
361971d10453SEric Joyner 		 * bits and OR request bits.
362071d10453SEric Joyner 		 */
362171d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
362271d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
362371d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_RS_544_REQ;
362471d10453SEric Joyner 		break;
362571d10453SEric Joyner 	case ICE_FEC_NONE:
362671d10453SEric Joyner 		/* Clear all FEC option bits. */
362771d10453SEric Joyner 		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
362871d10453SEric Joyner 		break;
362971d10453SEric Joyner 	case ICE_FEC_AUTO:
363071d10453SEric Joyner 		/* AND auto FEC bit, and all caps bits. */
363171d10453SEric Joyner 		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
363271d10453SEric Joyner 		cfg->link_fec_opt |= pcaps->link_fec_options;
363371d10453SEric Joyner 		break;
363471d10453SEric Joyner 	default:
363571d10453SEric Joyner 		status = ICE_ERR_PARAM;
363671d10453SEric Joyner 		break;
363771d10453SEric Joyner 	}
363871d10453SEric Joyner 
36399cf1841cSEric Joyner 	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw) &&
36409cf1841cSEric Joyner 	    !ice_fw_supports_report_dflt_cfg(pi->hw)) {
364171d10453SEric Joyner 		struct ice_link_default_override_tlv tlv;
364271d10453SEric Joyner 
364371d10453SEric Joyner 		if (ice_get_link_default_override(&tlv, pi))
364471d10453SEric Joyner 			goto out;
364571d10453SEric Joyner 
364671d10453SEric Joyner 		if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
364771d10453SEric Joyner 		    (tlv.options & ICE_LINK_OVERRIDE_EN))
364871d10453SEric Joyner 			cfg->link_fec_opt = tlv.fec_options;
364971d10453SEric Joyner 	}
365071d10453SEric Joyner 
365171d10453SEric Joyner out:
365271d10453SEric Joyner 	ice_free(hw, pcaps);
365371d10453SEric Joyner 
365471d10453SEric Joyner 	return status;
365571d10453SEric Joyner }
365671d10453SEric Joyner 
365771d10453SEric Joyner /**
365871d10453SEric Joyner  * ice_get_link_status - get status of the HW network link
365971d10453SEric Joyner  * @pi: port information structure
366071d10453SEric Joyner  * @link_up: pointer to bool (true/false = linkup/linkdown)
366171d10453SEric Joyner  *
366271d10453SEric Joyner  * Variable link_up is true if link is up, false if link is down.
366371d10453SEric Joyner  * The variable link_up is invalid if status is non zero. As a
366471d10453SEric Joyner  * result of this call, link status reporting becomes enabled
366571d10453SEric Joyner  */
366671d10453SEric Joyner enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up)
366771d10453SEric Joyner {
366871d10453SEric Joyner 	struct ice_phy_info *phy_info;
366971d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
367071d10453SEric Joyner 
367171d10453SEric Joyner 	if (!pi || !link_up)
367271d10453SEric Joyner 		return ICE_ERR_PARAM;
367371d10453SEric Joyner 
367471d10453SEric Joyner 	phy_info = &pi->phy;
367571d10453SEric Joyner 
367671d10453SEric Joyner 	if (phy_info->get_link_info) {
367771d10453SEric Joyner 		status = ice_update_link_info(pi);
367871d10453SEric Joyner 
367971d10453SEric Joyner 		if (status)
36807d7af7f8SEric Joyner 			ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n",
368171d10453SEric Joyner 				  status);
368271d10453SEric Joyner 	}
368371d10453SEric Joyner 
368471d10453SEric Joyner 	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
368571d10453SEric Joyner 
368671d10453SEric Joyner 	return status;
368771d10453SEric Joyner }
368871d10453SEric Joyner 
368971d10453SEric Joyner /**
369071d10453SEric Joyner  * ice_aq_set_link_restart_an
369171d10453SEric Joyner  * @pi: pointer to the port information structure
369271d10453SEric Joyner  * @ena_link: if true: enable link, if false: disable link
369371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
369471d10453SEric Joyner  *
369571d10453SEric Joyner  * Sets up the link and restarts the Auto-Negotiation over the link.
369671d10453SEric Joyner  */
369771d10453SEric Joyner enum ice_status
369871d10453SEric Joyner ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
369971d10453SEric Joyner 			   struct ice_sq_cd *cd)
370071d10453SEric Joyner {
370171d10453SEric Joyner 	struct ice_aqc_restart_an *cmd;
370271d10453SEric Joyner 	struct ice_aq_desc desc;
370371d10453SEric Joyner 
370471d10453SEric Joyner 	cmd = &desc.params.restart_an;
370571d10453SEric Joyner 
370671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
370771d10453SEric Joyner 
370871d10453SEric Joyner 	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
370971d10453SEric Joyner 	cmd->lport_num = pi->lport;
371071d10453SEric Joyner 	if (ena_link)
371171d10453SEric Joyner 		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
371271d10453SEric Joyner 	else
371371d10453SEric Joyner 		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
371471d10453SEric Joyner 
371571d10453SEric Joyner 	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
371671d10453SEric Joyner }
371771d10453SEric Joyner 
371871d10453SEric Joyner /**
371971d10453SEric Joyner  * ice_aq_set_event_mask
372071d10453SEric Joyner  * @hw: pointer to the HW struct
372171d10453SEric Joyner  * @port_num: port number of the physical function
372271d10453SEric Joyner  * @mask: event mask to be set
372371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
372471d10453SEric Joyner  *
372571d10453SEric Joyner  * Set event mask (0x0613)
372671d10453SEric Joyner  */
372771d10453SEric Joyner enum ice_status
372871d10453SEric Joyner ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
372971d10453SEric Joyner 		      struct ice_sq_cd *cd)
373071d10453SEric Joyner {
373171d10453SEric Joyner 	struct ice_aqc_set_event_mask *cmd;
373271d10453SEric Joyner 	struct ice_aq_desc desc;
373371d10453SEric Joyner 
373471d10453SEric Joyner 	cmd = &desc.params.set_event_mask;
373571d10453SEric Joyner 
373671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
373771d10453SEric Joyner 
373871d10453SEric Joyner 	cmd->lport_num = port_num;
373971d10453SEric Joyner 
374071d10453SEric Joyner 	cmd->event_mask = CPU_TO_LE16(mask);
374171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
374271d10453SEric Joyner }
374371d10453SEric Joyner 
374471d10453SEric Joyner /**
374571d10453SEric Joyner  * ice_aq_set_mac_loopback
374671d10453SEric Joyner  * @hw: pointer to the HW struct
374771d10453SEric Joyner  * @ena_lpbk: Enable or Disable loopback
374871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
374971d10453SEric Joyner  *
375071d10453SEric Joyner  * Enable/disable loopback on a given port
375171d10453SEric Joyner  */
375271d10453SEric Joyner enum ice_status
375371d10453SEric Joyner ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
375471d10453SEric Joyner {
375571d10453SEric Joyner 	struct ice_aqc_set_mac_lb *cmd;
375671d10453SEric Joyner 	struct ice_aq_desc desc;
375771d10453SEric Joyner 
375871d10453SEric Joyner 	cmd = &desc.params.set_mac_lb;
375971d10453SEric Joyner 
376071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
376171d10453SEric Joyner 	if (ena_lpbk)
376271d10453SEric Joyner 		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
376371d10453SEric Joyner 
376471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
376571d10453SEric Joyner }
376671d10453SEric Joyner 
376771d10453SEric Joyner /**
376871d10453SEric Joyner  * ice_aq_set_port_id_led
376971d10453SEric Joyner  * @pi: pointer to the port information
377071d10453SEric Joyner  * @is_orig_mode: is this LED set to original mode (by the net-list)
377171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
377271d10453SEric Joyner  *
377371d10453SEric Joyner  * Set LED value for the given port (0x06e9)
377471d10453SEric Joyner  */
377571d10453SEric Joyner enum ice_status
377671d10453SEric Joyner ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
377771d10453SEric Joyner 		       struct ice_sq_cd *cd)
377871d10453SEric Joyner {
377971d10453SEric Joyner 	struct ice_aqc_set_port_id_led *cmd;
378071d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
378171d10453SEric Joyner 	struct ice_aq_desc desc;
378271d10453SEric Joyner 
378371d10453SEric Joyner 	cmd = &desc.params.set_port_id_led;
378471d10453SEric Joyner 
378571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
378671d10453SEric Joyner 
378771d10453SEric Joyner 	if (is_orig_mode)
378871d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
378971d10453SEric Joyner 	else
379071d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
379171d10453SEric Joyner 
379271d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
379371d10453SEric Joyner }
379471d10453SEric Joyner 
379571d10453SEric Joyner /**
379671d10453SEric Joyner  * ice_aq_sff_eeprom
379771d10453SEric Joyner  * @hw: pointer to the HW struct
379871d10453SEric Joyner  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
379971d10453SEric Joyner  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
380071d10453SEric Joyner  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
380171d10453SEric Joyner  * @page: QSFP page
380271d10453SEric Joyner  * @set_page: set or ignore the page
380371d10453SEric Joyner  * @data: pointer to data buffer to be read/written to the I2C device.
380471d10453SEric Joyner  * @length: 1-16 for read, 1 for write.
380571d10453SEric Joyner  * @write: 0 read, 1 for write.
380671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
380771d10453SEric Joyner  *
380871d10453SEric Joyner  * Read/Write SFF EEPROM (0x06EE)
380971d10453SEric Joyner  */
381071d10453SEric Joyner enum ice_status
381171d10453SEric Joyner ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
381271d10453SEric Joyner 		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
381371d10453SEric Joyner 		  bool write, struct ice_sq_cd *cd)
381471d10453SEric Joyner {
381571d10453SEric Joyner 	struct ice_aqc_sff_eeprom *cmd;
381671d10453SEric Joyner 	struct ice_aq_desc desc;
381771d10453SEric Joyner 	enum ice_status status;
381871d10453SEric Joyner 
381971d10453SEric Joyner 	if (!data || (mem_addr & 0xff00))
382071d10453SEric Joyner 		return ICE_ERR_PARAM;
382171d10453SEric Joyner 
382271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
382371d10453SEric Joyner 	cmd = &desc.params.read_write_sff_param;
3824d08b8680SEric Joyner 	desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD);
382571d10453SEric Joyner 	cmd->lport_num = (u8)(lport & 0xff);
382671d10453SEric Joyner 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
382771d10453SEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(((bus_addr >> 1) &
382871d10453SEric Joyner 					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
382971d10453SEric Joyner 					((set_page <<
383071d10453SEric Joyner 					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
383171d10453SEric Joyner 					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
383271d10453SEric Joyner 	cmd->i2c_mem_addr = CPU_TO_LE16(mem_addr & 0xff);
383371d10453SEric Joyner 	cmd->eeprom_page = CPU_TO_LE16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
383471d10453SEric Joyner 	if (write)
383571d10453SEric Joyner 		cmd->i2c_bus_addr |= CPU_TO_LE16(ICE_AQC_SFF_IS_WRITE);
383671d10453SEric Joyner 
383771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
383871d10453SEric Joyner 	return status;
383971d10453SEric Joyner }
384071d10453SEric Joyner 
384171d10453SEric Joyner /**
3842*56429daeSEric Joyner  * ice_aq_prog_topo_dev_nvm
3843*56429daeSEric Joyner  * @hw: pointer to the hardware structure
3844*56429daeSEric Joyner  * @topo_params: pointer to structure storing topology parameters for a device
3845*56429daeSEric Joyner  * @cd: pointer to command details structure or NULL
3846*56429daeSEric Joyner  *
3847*56429daeSEric Joyner  * Program Topology Device NVM (0x06F2)
3848*56429daeSEric Joyner  *
3849*56429daeSEric Joyner  */
3850*56429daeSEric Joyner enum ice_status
3851*56429daeSEric Joyner ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
3852*56429daeSEric Joyner 			 struct ice_aqc_link_topo_params *topo_params,
3853*56429daeSEric Joyner 			 struct ice_sq_cd *cd)
3854*56429daeSEric Joyner {
3855*56429daeSEric Joyner 	struct ice_aqc_prog_topo_dev_nvm *cmd;
3856*56429daeSEric Joyner 	struct ice_aq_desc desc;
3857*56429daeSEric Joyner 
3858*56429daeSEric Joyner 	cmd = &desc.params.prog_topo_dev_nvm;
3859*56429daeSEric Joyner 
3860*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm);
3861*56429daeSEric Joyner 
3862*56429daeSEric Joyner 	ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
3863*56429daeSEric Joyner 		   ICE_NONDMA_TO_NONDMA);
3864*56429daeSEric Joyner 
3865*56429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
3866*56429daeSEric Joyner }
3867*56429daeSEric Joyner 
3868*56429daeSEric Joyner /**
3869*56429daeSEric Joyner  * ice_aq_read_topo_dev_nvm
3870*56429daeSEric Joyner  * @hw: pointer to the hardware structure
3871*56429daeSEric Joyner  * @topo_params: pointer to structure storing topology parameters for a device
3872*56429daeSEric Joyner  * @start_address: byte offset in the topology device NVM
3873*56429daeSEric Joyner  * @data: pointer to data buffer
3874*56429daeSEric Joyner  * @data_size: number of bytes to be read from the topology device NVM
3875*56429daeSEric Joyner  * @cd: pointer to command details structure or NULL
3876*56429daeSEric Joyner  * Read Topology Device NVM (0x06F3)
3877*56429daeSEric Joyner  *
3878*56429daeSEric Joyner  */
3879*56429daeSEric Joyner enum ice_status
3880*56429daeSEric Joyner ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
3881*56429daeSEric Joyner 			 struct ice_aqc_link_topo_params *topo_params,
3882*56429daeSEric Joyner 			 u32 start_address, u8 *data, u8 data_size,
3883*56429daeSEric Joyner 			 struct ice_sq_cd *cd)
3884*56429daeSEric Joyner {
3885*56429daeSEric Joyner 	struct ice_aqc_read_topo_dev_nvm *cmd;
3886*56429daeSEric Joyner 	struct ice_aq_desc desc;
3887*56429daeSEric Joyner 	enum ice_status status;
3888*56429daeSEric Joyner 
3889*56429daeSEric Joyner 	if (!data || data_size == 0 ||
3890*56429daeSEric Joyner 	    data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
3891*56429daeSEric Joyner 		return ICE_ERR_PARAM;
3892*56429daeSEric Joyner 
3893*56429daeSEric Joyner 	cmd = &desc.params.read_topo_dev_nvm;
3894*56429daeSEric Joyner 
3895*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm);
3896*56429daeSEric Joyner 
3897*56429daeSEric Joyner 	desc.datalen = data_size;
3898*56429daeSEric Joyner 	ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
3899*56429daeSEric Joyner 		   ICE_NONDMA_TO_NONDMA);
3900*56429daeSEric Joyner 	cmd->start_address = CPU_TO_LE32(start_address);
3901*56429daeSEric Joyner 
3902*56429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
3903*56429daeSEric Joyner 	if (status)
3904*56429daeSEric Joyner 		return status;
3905*56429daeSEric Joyner 
3906*56429daeSEric Joyner 	ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA);
3907*56429daeSEric Joyner 
3908*56429daeSEric Joyner 	return ICE_SUCCESS;
3909*56429daeSEric Joyner }
3910*56429daeSEric Joyner 
3911*56429daeSEric Joyner /**
391271d10453SEric Joyner  * __ice_aq_get_set_rss_lut
391371d10453SEric Joyner  * @hw: pointer to the hardware structure
3914d08b8680SEric Joyner  * @params: RSS LUT parameters
391571d10453SEric Joyner  * @set: set true to set the table, false to get the table
391671d10453SEric Joyner  *
391771d10453SEric Joyner  * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
391871d10453SEric Joyner  */
391971d10453SEric Joyner static enum ice_status
3920d08b8680SEric Joyner __ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, bool set)
392171d10453SEric Joyner {
3922d08b8680SEric Joyner 	u16 flags = 0, vsi_id, lut_type, lut_size, glob_lut_idx, vsi_handle;
392371d10453SEric Joyner 	struct ice_aqc_get_set_rss_lut *cmd_resp;
392471d10453SEric Joyner 	struct ice_aq_desc desc;
392571d10453SEric Joyner 	enum ice_status status;
3926d08b8680SEric Joyner 	u8 *lut;
3927d08b8680SEric Joyner 
3928d08b8680SEric Joyner 	if (!params)
3929d08b8680SEric Joyner 		return ICE_ERR_PARAM;
3930d08b8680SEric Joyner 
3931d08b8680SEric Joyner 	vsi_handle = params->vsi_handle;
3932d08b8680SEric Joyner 	lut = params->lut;
3933d08b8680SEric Joyner 
3934d08b8680SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
3935d08b8680SEric Joyner 		return ICE_ERR_PARAM;
3936d08b8680SEric Joyner 
3937d08b8680SEric Joyner 	lut_size = params->lut_size;
3938d08b8680SEric Joyner 	lut_type = params->lut_type;
3939d08b8680SEric Joyner 	glob_lut_idx = params->global_lut_id;
3940d08b8680SEric Joyner 	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
394171d10453SEric Joyner 
394271d10453SEric Joyner 	cmd_resp = &desc.params.get_set_rss_lut;
394371d10453SEric Joyner 
394471d10453SEric Joyner 	if (set) {
394571d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut);
394671d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
394771d10453SEric Joyner 	} else {
394871d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut);
394971d10453SEric Joyner 	}
395071d10453SEric Joyner 
395171d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
395271d10453SEric Joyner 					 ICE_AQC_GSET_RSS_LUT_VSI_ID_S) &
395371d10453SEric Joyner 					ICE_AQC_GSET_RSS_LUT_VSI_ID_M) |
395471d10453SEric Joyner 				       ICE_AQC_GSET_RSS_LUT_VSI_VALID);
395571d10453SEric Joyner 
395671d10453SEric Joyner 	switch (lut_type) {
395771d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI:
395871d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF:
395971d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL:
396071d10453SEric Joyner 		flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) &
396171d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M);
396271d10453SEric Joyner 		break;
396371d10453SEric Joyner 	default:
396471d10453SEric Joyner 		status = ICE_ERR_PARAM;
396571d10453SEric Joyner 		goto ice_aq_get_set_rss_lut_exit;
396671d10453SEric Joyner 	}
396771d10453SEric Joyner 
396871d10453SEric Joyner 	if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) {
396971d10453SEric Joyner 		flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) &
397071d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M);
397171d10453SEric Joyner 
397271d10453SEric Joyner 		if (!set)
397371d10453SEric Joyner 			goto ice_aq_get_set_rss_lut_send;
397471d10453SEric Joyner 	} else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
397571d10453SEric Joyner 		if (!set)
397671d10453SEric Joyner 			goto ice_aq_get_set_rss_lut_send;
397771d10453SEric Joyner 	} else {
397871d10453SEric Joyner 		goto ice_aq_get_set_rss_lut_send;
397971d10453SEric Joyner 	}
398071d10453SEric Joyner 
398171d10453SEric Joyner 	/* LUT size is only valid for Global and PF table types */
398271d10453SEric Joyner 	switch (lut_size) {
398371d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128:
398471d10453SEric Joyner 		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG <<
398571d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
398671d10453SEric Joyner 			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
398771d10453SEric Joyner 		break;
398871d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512:
398971d10453SEric Joyner 		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG <<
399071d10453SEric Joyner 			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
399171d10453SEric Joyner 			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
399271d10453SEric Joyner 		break;
399371d10453SEric Joyner 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K:
399471d10453SEric Joyner 		if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
399571d10453SEric Joyner 			flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG <<
399671d10453SEric Joyner 				  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
399771d10453SEric Joyner 				 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
399871d10453SEric Joyner 			break;
399971d10453SEric Joyner 		}
400071d10453SEric Joyner 		/* fall-through */
400171d10453SEric Joyner 	default:
400271d10453SEric Joyner 		status = ICE_ERR_PARAM;
400371d10453SEric Joyner 		goto ice_aq_get_set_rss_lut_exit;
400471d10453SEric Joyner 	}
400571d10453SEric Joyner 
400671d10453SEric Joyner ice_aq_get_set_rss_lut_send:
400771d10453SEric Joyner 	cmd_resp->flags = CPU_TO_LE16(flags);
400871d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
400971d10453SEric Joyner 
401071d10453SEric Joyner ice_aq_get_set_rss_lut_exit:
401171d10453SEric Joyner 	return status;
401271d10453SEric Joyner }
401371d10453SEric Joyner 
401471d10453SEric Joyner /**
401571d10453SEric Joyner  * ice_aq_get_rss_lut
401671d10453SEric Joyner  * @hw: pointer to the hardware structure
4017d08b8680SEric Joyner  * @get_params: RSS LUT parameters used to specify which RSS LUT to get
401871d10453SEric Joyner  *
401971d10453SEric Joyner  * get the RSS lookup table, PF or VSI type
402071d10453SEric Joyner  */
402171d10453SEric Joyner enum ice_status
4022d08b8680SEric Joyner ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)
402371d10453SEric Joyner {
4024d08b8680SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, get_params, false);
402571d10453SEric Joyner }
402671d10453SEric Joyner 
402771d10453SEric Joyner /**
402871d10453SEric Joyner  * ice_aq_set_rss_lut
402971d10453SEric Joyner  * @hw: pointer to the hardware structure
4030d08b8680SEric Joyner  * @set_params: RSS LUT parameters used to specify how to set the RSS LUT
403171d10453SEric Joyner  *
403271d10453SEric Joyner  * set the RSS lookup table, PF or VSI type
403371d10453SEric Joyner  */
403471d10453SEric Joyner enum ice_status
4035d08b8680SEric Joyner ice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)
403671d10453SEric Joyner {
4037d08b8680SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, set_params, true);
403871d10453SEric Joyner }
403971d10453SEric Joyner 
404071d10453SEric Joyner /**
404171d10453SEric Joyner  * __ice_aq_get_set_rss_key
404271d10453SEric Joyner  * @hw: pointer to the HW struct
404371d10453SEric Joyner  * @vsi_id: VSI FW index
404471d10453SEric Joyner  * @key: pointer to key info struct
404571d10453SEric Joyner  * @set: set true to set the key, false to get the key
404671d10453SEric Joyner  *
404771d10453SEric Joyner  * get (0x0B04) or set (0x0B02) the RSS key per VSI
404871d10453SEric Joyner  */
404971d10453SEric Joyner static enum
405071d10453SEric Joyner ice_status __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
405171d10453SEric Joyner 				    struct ice_aqc_get_set_rss_keys *key,
405271d10453SEric Joyner 				    bool set)
405371d10453SEric Joyner {
405471d10453SEric Joyner 	struct ice_aqc_get_set_rss_key *cmd_resp;
405571d10453SEric Joyner 	u16 key_size = sizeof(*key);
405671d10453SEric Joyner 	struct ice_aq_desc desc;
405771d10453SEric Joyner 
405871d10453SEric Joyner 	cmd_resp = &desc.params.get_set_rss_key;
405971d10453SEric Joyner 
406071d10453SEric Joyner 	if (set) {
406171d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
406271d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
406371d10453SEric Joyner 	} else {
406471d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
406571d10453SEric Joyner 	}
406671d10453SEric Joyner 
406771d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
406871d10453SEric Joyner 					 ICE_AQC_GSET_RSS_KEY_VSI_ID_S) &
406971d10453SEric Joyner 					ICE_AQC_GSET_RSS_KEY_VSI_ID_M) |
407071d10453SEric Joyner 				       ICE_AQC_GSET_RSS_KEY_VSI_VALID);
407171d10453SEric Joyner 
407271d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
407371d10453SEric Joyner }
407471d10453SEric Joyner 
407571d10453SEric Joyner /**
407671d10453SEric Joyner  * ice_aq_get_rss_key
407771d10453SEric Joyner  * @hw: pointer to the HW struct
407871d10453SEric Joyner  * @vsi_handle: software VSI handle
407971d10453SEric Joyner  * @key: pointer to key info struct
408071d10453SEric Joyner  *
408171d10453SEric Joyner  * get the RSS key per VSI
408271d10453SEric Joyner  */
408371d10453SEric Joyner enum ice_status
408471d10453SEric Joyner ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
408571d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *key)
408671d10453SEric Joyner {
408771d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
408871d10453SEric Joyner 		return ICE_ERR_PARAM;
408971d10453SEric Joyner 
409071d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
409171d10453SEric Joyner 					key, false);
409271d10453SEric Joyner }
409371d10453SEric Joyner 
409471d10453SEric Joyner /**
409571d10453SEric Joyner  * ice_aq_set_rss_key
409671d10453SEric Joyner  * @hw: pointer to the HW struct
409771d10453SEric Joyner  * @vsi_handle: software VSI handle
409871d10453SEric Joyner  * @keys: pointer to key info struct
409971d10453SEric Joyner  *
410071d10453SEric Joyner  * set the RSS key per VSI
410171d10453SEric Joyner  */
410271d10453SEric Joyner enum ice_status
410371d10453SEric Joyner ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
410471d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *keys)
410571d10453SEric Joyner {
410671d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
410771d10453SEric Joyner 		return ICE_ERR_PARAM;
410871d10453SEric Joyner 
410971d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
411071d10453SEric Joyner 					keys, true);
411171d10453SEric Joyner }
411271d10453SEric Joyner 
411371d10453SEric Joyner /**
411471d10453SEric Joyner  * ice_aq_add_lan_txq
411571d10453SEric Joyner  * @hw: pointer to the hardware structure
411671d10453SEric Joyner  * @num_qgrps: Number of added queue groups
411771d10453SEric Joyner  * @qg_list: list of queue groups to be added
411871d10453SEric Joyner  * @buf_size: size of buffer for indirect command
411971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
412071d10453SEric Joyner  *
412171d10453SEric Joyner  * Add Tx LAN queue (0x0C30)
412271d10453SEric Joyner  *
412371d10453SEric Joyner  * NOTE:
412471d10453SEric Joyner  * Prior to calling add Tx LAN queue:
412571d10453SEric Joyner  * Initialize the following as part of the Tx queue context:
412671d10453SEric Joyner  * Completion queue ID if the queue uses Completion queue, Quanta profile,
412771d10453SEric Joyner  * Cache profile and Packet shaper profile.
412871d10453SEric Joyner  *
412971d10453SEric Joyner  * After add Tx LAN queue AQ command is completed:
413071d10453SEric Joyner  * Interrupts should be associated with specific queues,
413171d10453SEric Joyner  * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
413271d10453SEric Joyner  * flow.
413371d10453SEric Joyner  */
413471d10453SEric Joyner enum ice_status
413571d10453SEric Joyner ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
413671d10453SEric Joyner 		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
413771d10453SEric Joyner 		   struct ice_sq_cd *cd)
413871d10453SEric Joyner {
413971d10453SEric Joyner 	struct ice_aqc_add_tx_qgrp *list;
414071d10453SEric Joyner 	struct ice_aqc_add_txqs *cmd;
414171d10453SEric Joyner 	struct ice_aq_desc desc;
41427d7af7f8SEric Joyner 	u16 i, sum_size = 0;
414371d10453SEric Joyner 
414471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
414571d10453SEric Joyner 
414671d10453SEric Joyner 	cmd = &desc.params.add_txqs;
414771d10453SEric Joyner 
414871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
414971d10453SEric Joyner 
415071d10453SEric Joyner 	if (!qg_list)
415171d10453SEric Joyner 		return ICE_ERR_PARAM;
415271d10453SEric Joyner 
415371d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
415471d10453SEric Joyner 		return ICE_ERR_PARAM;
415571d10453SEric Joyner 
41567d7af7f8SEric Joyner 	for (i = 0, list = qg_list; i < num_qgrps; i++) {
41577d7af7f8SEric Joyner 		sum_size += ice_struct_size(list, txqs, list->num_txqs);
41587d7af7f8SEric Joyner 		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
41597d7af7f8SEric Joyner 						      list->num_txqs);
416071d10453SEric Joyner 	}
416171d10453SEric Joyner 
41627d7af7f8SEric Joyner 	if (buf_size != sum_size)
416371d10453SEric Joyner 		return ICE_ERR_PARAM;
416471d10453SEric Joyner 
416571d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
416671d10453SEric Joyner 
416771d10453SEric Joyner 	cmd->num_qgrps = num_qgrps;
416871d10453SEric Joyner 
416971d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
417071d10453SEric Joyner }
417171d10453SEric Joyner 
417271d10453SEric Joyner /**
417371d10453SEric Joyner  * ice_aq_dis_lan_txq
417471d10453SEric Joyner  * @hw: pointer to the hardware structure
417571d10453SEric Joyner  * @num_qgrps: number of groups in the list
417671d10453SEric Joyner  * @qg_list: the list of groups to disable
417771d10453SEric Joyner  * @buf_size: the total size of the qg_list buffer in bytes
417871d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
417971d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
418071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
418171d10453SEric Joyner  *
418271d10453SEric Joyner  * Disable LAN Tx queue (0x0C31)
418371d10453SEric Joyner  */
418471d10453SEric Joyner static enum ice_status
418571d10453SEric Joyner ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
418671d10453SEric Joyner 		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
418771d10453SEric Joyner 		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
418871d10453SEric Joyner 		   struct ice_sq_cd *cd)
418971d10453SEric Joyner {
41907d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *item;
419171d10453SEric Joyner 	struct ice_aqc_dis_txqs *cmd;
419271d10453SEric Joyner 	struct ice_aq_desc desc;
419371d10453SEric Joyner 	enum ice_status status;
419471d10453SEric Joyner 	u16 i, sz = 0;
419571d10453SEric Joyner 
419671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
419771d10453SEric Joyner 	cmd = &desc.params.dis_txqs;
419871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
419971d10453SEric Joyner 
420071d10453SEric Joyner 	/* qg_list can be NULL only in VM/VF reset flow */
420171d10453SEric Joyner 	if (!qg_list && !rst_src)
420271d10453SEric Joyner 		return ICE_ERR_PARAM;
420371d10453SEric Joyner 
420471d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
420571d10453SEric Joyner 		return ICE_ERR_PARAM;
420671d10453SEric Joyner 
420771d10453SEric Joyner 	cmd->num_entries = num_qgrps;
420871d10453SEric Joyner 
420971d10453SEric Joyner 	cmd->vmvf_and_timeout = CPU_TO_LE16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
421071d10453SEric Joyner 					    ICE_AQC_Q_DIS_TIMEOUT_M);
421171d10453SEric Joyner 
421271d10453SEric Joyner 	switch (rst_src) {
421371d10453SEric Joyner 	case ICE_VM_RESET:
421471d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
421571d10453SEric Joyner 		cmd->vmvf_and_timeout |=
421671d10453SEric Joyner 			CPU_TO_LE16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
421771d10453SEric Joyner 		break;
421871d10453SEric Joyner 	case ICE_VF_RESET:
421971d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
422071d10453SEric Joyner 		/* In this case, FW expects vmvf_num to be absolute VF ID */
422171d10453SEric Joyner 		cmd->vmvf_and_timeout |=
422271d10453SEric Joyner 			CPU_TO_LE16((vmvf_num + hw->func_caps.vf_base_id) &
422371d10453SEric Joyner 				    ICE_AQC_Q_DIS_VMVF_NUM_M);
422471d10453SEric Joyner 		break;
422571d10453SEric Joyner 	case ICE_NO_RESET:
422671d10453SEric Joyner 	default:
422771d10453SEric Joyner 		break;
422871d10453SEric Joyner 	}
422971d10453SEric Joyner 
423071d10453SEric Joyner 	/* flush pipe on time out */
423171d10453SEric Joyner 	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
423271d10453SEric Joyner 	/* If no queue group info, we are in a reset flow. Issue the AQ */
423371d10453SEric Joyner 	if (!qg_list)
423471d10453SEric Joyner 		goto do_aq;
423571d10453SEric Joyner 
423671d10453SEric Joyner 	/* set RD bit to indicate that command buffer is provided by the driver
423771d10453SEric Joyner 	 * and it needs to be read by the firmware
423871d10453SEric Joyner 	 */
423971d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
424071d10453SEric Joyner 
42417d7af7f8SEric Joyner 	for (i = 0, item = qg_list; i < num_qgrps; i++) {
42427d7af7f8SEric Joyner 		u16 item_size = ice_struct_size(item, q_id, item->num_qs);
424371d10453SEric Joyner 
424471d10453SEric Joyner 		/* If the num of queues is even, add 2 bytes of padding */
42457d7af7f8SEric Joyner 		if ((item->num_qs % 2) == 0)
42467d7af7f8SEric Joyner 			item_size += 2;
42477d7af7f8SEric Joyner 
42487d7af7f8SEric Joyner 		sz += item_size;
42497d7af7f8SEric Joyner 
42507d7af7f8SEric Joyner 		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
425171d10453SEric Joyner 	}
425271d10453SEric Joyner 
425371d10453SEric Joyner 	if (buf_size != sz)
425471d10453SEric Joyner 		return ICE_ERR_PARAM;
425571d10453SEric Joyner 
425671d10453SEric Joyner do_aq:
425771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
425871d10453SEric Joyner 	if (status) {
425971d10453SEric Joyner 		if (!qg_list)
426071d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
426171d10453SEric Joyner 				  vmvf_num, hw->adminq.sq_last_status);
426271d10453SEric Joyner 		else
426371d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
426471d10453SEric Joyner 				  LE16_TO_CPU(qg_list[0].q_id[0]),
426571d10453SEric Joyner 				  hw->adminq.sq_last_status);
426671d10453SEric Joyner 	}
426771d10453SEric Joyner 	return status;
426871d10453SEric Joyner }
426971d10453SEric Joyner 
427071d10453SEric Joyner /**
427171d10453SEric Joyner  * ice_aq_move_recfg_lan_txq
427271d10453SEric Joyner  * @hw: pointer to the hardware structure
427371d10453SEric Joyner  * @num_qs: number of queues to move/reconfigure
427471d10453SEric Joyner  * @is_move: true if this operation involves node movement
427571d10453SEric Joyner  * @is_tc_change: true if this operation involves a TC change
427671d10453SEric Joyner  * @subseq_call: true if this operation is a subsequent call
427771d10453SEric Joyner  * @flush_pipe: on timeout, true to flush pipe, false to return EAGAIN
427871d10453SEric Joyner  * @timeout: timeout in units of 100 usec (valid values 0-50)
427971d10453SEric Joyner  * @blocked_cgds: out param, bitmap of CGDs that timed out if returning EAGAIN
428071d10453SEric Joyner  * @buf: struct containing src/dest TEID and per-queue info
428171d10453SEric Joyner  * @buf_size: size of buffer for indirect command
428271d10453SEric Joyner  * @txqs_moved: out param, number of queues successfully moved
428371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
428471d10453SEric Joyner  *
428571d10453SEric Joyner  * Move / Reconfigure Tx LAN queues (0x0C32)
428671d10453SEric Joyner  */
428771d10453SEric Joyner enum ice_status
428871d10453SEric Joyner ice_aq_move_recfg_lan_txq(struct ice_hw *hw, u8 num_qs, bool is_move,
428971d10453SEric Joyner 			  bool is_tc_change, bool subseq_call, bool flush_pipe,
429071d10453SEric Joyner 			  u8 timeout, u32 *blocked_cgds,
429171d10453SEric Joyner 			  struct ice_aqc_move_txqs_data *buf, u16 buf_size,
429271d10453SEric Joyner 			  u8 *txqs_moved, struct ice_sq_cd *cd)
429371d10453SEric Joyner {
429471d10453SEric Joyner 	struct ice_aqc_move_txqs *cmd;
429571d10453SEric Joyner 	struct ice_aq_desc desc;
429671d10453SEric Joyner 	enum ice_status status;
429771d10453SEric Joyner 
429871d10453SEric Joyner 	cmd = &desc.params.move_txqs;
429971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_move_recfg_txqs);
430071d10453SEric Joyner 
430171d10453SEric Joyner #define ICE_LAN_TXQ_MOVE_TIMEOUT_MAX 50
430271d10453SEric Joyner 	if (timeout > ICE_LAN_TXQ_MOVE_TIMEOUT_MAX)
430371d10453SEric Joyner 		return ICE_ERR_PARAM;
430471d10453SEric Joyner 
430571d10453SEric Joyner 	if (is_tc_change && !flush_pipe && !blocked_cgds)
430671d10453SEric Joyner 		return ICE_ERR_PARAM;
430771d10453SEric Joyner 
430871d10453SEric Joyner 	if (!is_move && !is_tc_change)
430971d10453SEric Joyner 		return ICE_ERR_PARAM;
431071d10453SEric Joyner 
431171d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
431271d10453SEric Joyner 
431371d10453SEric Joyner 	if (is_move)
431471d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_MOVE;
431571d10453SEric Joyner 
431671d10453SEric Joyner 	if (is_tc_change)
431771d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_TC_CHANGE;
431871d10453SEric Joyner 
431971d10453SEric Joyner 	if (subseq_call)
432071d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_SUBSEQ_CALL;
432171d10453SEric Joyner 
432271d10453SEric Joyner 	if (flush_pipe)
432371d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_FLUSH_PIPE;
432471d10453SEric Joyner 
432571d10453SEric Joyner 	cmd->num_qs = num_qs;
432671d10453SEric Joyner 	cmd->timeout = ((timeout << ICE_AQC_Q_CMD_TIMEOUT_S) &
432771d10453SEric Joyner 			ICE_AQC_Q_CMD_TIMEOUT_M);
432871d10453SEric Joyner 
432971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
433071d10453SEric Joyner 
433171d10453SEric Joyner 	if (!status && txqs_moved)
433271d10453SEric Joyner 		*txqs_moved = cmd->num_qs;
433371d10453SEric Joyner 
433471d10453SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EAGAIN &&
433571d10453SEric Joyner 	    is_tc_change && !flush_pipe)
433671d10453SEric Joyner 		*blocked_cgds = LE32_TO_CPU(cmd->blocked_cgds);
433771d10453SEric Joyner 
433871d10453SEric Joyner 	return status;
433971d10453SEric Joyner }
434071d10453SEric Joyner 
434171d10453SEric Joyner /* End of FW Admin Queue command wrappers */
434271d10453SEric Joyner 
434371d10453SEric Joyner /**
434471d10453SEric Joyner  * ice_write_byte - write a byte to a packed context structure
434571d10453SEric Joyner  * @src_ctx:  the context structure to read from
434671d10453SEric Joyner  * @dest_ctx: the context to be written to
434771d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
434871d10453SEric Joyner  */
434971d10453SEric Joyner static void
435071d10453SEric Joyner ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
435171d10453SEric Joyner {
435271d10453SEric Joyner 	u8 src_byte, dest_byte, mask;
435371d10453SEric Joyner 	u8 *from, *dest;
435471d10453SEric Joyner 	u16 shift_width;
435571d10453SEric Joyner 
435671d10453SEric Joyner 	/* copy from the next struct field */
435771d10453SEric Joyner 	from = src_ctx + ce_info->offset;
435871d10453SEric Joyner 
435971d10453SEric Joyner 	/* prepare the bits and mask */
436071d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
436171d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
436271d10453SEric Joyner 
436371d10453SEric Joyner 	src_byte = *from;
436471d10453SEric Joyner 	src_byte &= mask;
436571d10453SEric Joyner 
436671d10453SEric Joyner 	/* shift to correct alignment */
436771d10453SEric Joyner 	mask <<= shift_width;
436871d10453SEric Joyner 	src_byte <<= shift_width;
436971d10453SEric Joyner 
437071d10453SEric Joyner 	/* get the current bits from the target bit string */
437171d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
437271d10453SEric Joyner 
437371d10453SEric Joyner 	ice_memcpy(&dest_byte, dest, sizeof(dest_byte), ICE_DMA_TO_NONDMA);
437471d10453SEric Joyner 
437571d10453SEric Joyner 	dest_byte &= ~mask;	/* get the bits not changing */
437671d10453SEric Joyner 	dest_byte |= src_byte;	/* add in the new bits */
437771d10453SEric Joyner 
437871d10453SEric Joyner 	/* put it all back */
437971d10453SEric Joyner 	ice_memcpy(dest, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA);
438071d10453SEric Joyner }
438171d10453SEric Joyner 
438271d10453SEric Joyner /**
438371d10453SEric Joyner  * ice_write_word - write a word to a packed context structure
438471d10453SEric Joyner  * @src_ctx:  the context structure to read from
438571d10453SEric Joyner  * @dest_ctx: the context to be written to
438671d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
438771d10453SEric Joyner  */
438871d10453SEric Joyner static void
438971d10453SEric Joyner ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
439071d10453SEric Joyner {
439171d10453SEric Joyner 	u16 src_word, mask;
439271d10453SEric Joyner 	__le16 dest_word;
439371d10453SEric Joyner 	u8 *from, *dest;
439471d10453SEric Joyner 	u16 shift_width;
439571d10453SEric Joyner 
439671d10453SEric Joyner 	/* copy from the next struct field */
439771d10453SEric Joyner 	from = src_ctx + ce_info->offset;
439871d10453SEric Joyner 
439971d10453SEric Joyner 	/* prepare the bits and mask */
440071d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
440171d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
440271d10453SEric Joyner 
440371d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
440471d10453SEric Joyner 	 * will be in a different bit position on big endian machines
440571d10453SEric Joyner 	 */
440671d10453SEric Joyner 	src_word = *(u16 *)from;
440771d10453SEric Joyner 	src_word &= mask;
440871d10453SEric Joyner 
440971d10453SEric Joyner 	/* shift to correct alignment */
441071d10453SEric Joyner 	mask <<= shift_width;
441171d10453SEric Joyner 	src_word <<= shift_width;
441271d10453SEric Joyner 
441371d10453SEric Joyner 	/* get the current bits from the target bit string */
441471d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
441571d10453SEric Joyner 
441671d10453SEric Joyner 	ice_memcpy(&dest_word, dest, sizeof(dest_word), ICE_DMA_TO_NONDMA);
441771d10453SEric Joyner 
441871d10453SEric Joyner 	dest_word &= ~(CPU_TO_LE16(mask));	/* get the bits not changing */
441971d10453SEric Joyner 	dest_word |= CPU_TO_LE16(src_word);	/* add in the new bits */
442071d10453SEric Joyner 
442171d10453SEric Joyner 	/* put it all back */
442271d10453SEric Joyner 	ice_memcpy(dest, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA);
442371d10453SEric Joyner }
442471d10453SEric Joyner 
442571d10453SEric Joyner /**
442671d10453SEric Joyner  * ice_write_dword - write a dword to a packed context structure
442771d10453SEric Joyner  * @src_ctx:  the context structure to read from
442871d10453SEric Joyner  * @dest_ctx: the context to be written to
442971d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
443071d10453SEric Joyner  */
443171d10453SEric Joyner static void
443271d10453SEric Joyner ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
443371d10453SEric Joyner {
443471d10453SEric Joyner 	u32 src_dword, mask;
443571d10453SEric Joyner 	__le32 dest_dword;
443671d10453SEric Joyner 	u8 *from, *dest;
443771d10453SEric Joyner 	u16 shift_width;
443871d10453SEric Joyner 
443971d10453SEric Joyner 	/* copy from the next struct field */
444071d10453SEric Joyner 	from = src_ctx + ce_info->offset;
444171d10453SEric Joyner 
444271d10453SEric Joyner 	/* prepare the bits and mask */
444371d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
444471d10453SEric Joyner 
444571d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
444671d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
444771d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
444871d10453SEric Joyner 	 */
444971d10453SEric Joyner 	if (ce_info->width < 32)
445071d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
445171d10453SEric Joyner 	else
445271d10453SEric Joyner 		mask = (u32)~0;
445371d10453SEric Joyner 
445471d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
445571d10453SEric Joyner 	 * will be in a different bit position on big endian machines
445671d10453SEric Joyner 	 */
445771d10453SEric Joyner 	src_dword = *(u32 *)from;
445871d10453SEric Joyner 	src_dword &= mask;
445971d10453SEric Joyner 
446071d10453SEric Joyner 	/* shift to correct alignment */
446171d10453SEric Joyner 	mask <<= shift_width;
446271d10453SEric Joyner 	src_dword <<= shift_width;
446371d10453SEric Joyner 
446471d10453SEric Joyner 	/* get the current bits from the target bit string */
446571d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
446671d10453SEric Joyner 
446771d10453SEric Joyner 	ice_memcpy(&dest_dword, dest, sizeof(dest_dword), ICE_DMA_TO_NONDMA);
446871d10453SEric Joyner 
446971d10453SEric Joyner 	dest_dword &= ~(CPU_TO_LE32(mask));	/* get the bits not changing */
447071d10453SEric Joyner 	dest_dword |= CPU_TO_LE32(src_dword);	/* add in the new bits */
447171d10453SEric Joyner 
447271d10453SEric Joyner 	/* put it all back */
447371d10453SEric Joyner 	ice_memcpy(dest, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA);
447471d10453SEric Joyner }
447571d10453SEric Joyner 
447671d10453SEric Joyner /**
447771d10453SEric Joyner  * ice_write_qword - write a qword to a packed context structure
447871d10453SEric Joyner  * @src_ctx:  the context structure to read from
447971d10453SEric Joyner  * @dest_ctx: the context to be written to
448071d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
448171d10453SEric Joyner  */
448271d10453SEric Joyner static void
448371d10453SEric Joyner ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
448471d10453SEric Joyner {
448571d10453SEric Joyner 	u64 src_qword, mask;
448671d10453SEric Joyner 	__le64 dest_qword;
448771d10453SEric Joyner 	u8 *from, *dest;
448871d10453SEric Joyner 	u16 shift_width;
448971d10453SEric Joyner 
449071d10453SEric Joyner 	/* copy from the next struct field */
449171d10453SEric Joyner 	from = src_ctx + ce_info->offset;
449271d10453SEric Joyner 
449371d10453SEric Joyner 	/* prepare the bits and mask */
449471d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
449571d10453SEric Joyner 
449671d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
449771d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
449871d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
449971d10453SEric Joyner 	 */
450071d10453SEric Joyner 	if (ce_info->width < 64)
450171d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
450271d10453SEric Joyner 	else
450371d10453SEric Joyner 		mask = (u64)~0;
450471d10453SEric Joyner 
450571d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
450671d10453SEric Joyner 	 * will be in a different bit position on big endian machines
450771d10453SEric Joyner 	 */
450871d10453SEric Joyner 	src_qword = *(u64 *)from;
450971d10453SEric Joyner 	src_qword &= mask;
451071d10453SEric Joyner 
451171d10453SEric Joyner 	/* shift to correct alignment */
451271d10453SEric Joyner 	mask <<= shift_width;
451371d10453SEric Joyner 	src_qword <<= shift_width;
451471d10453SEric Joyner 
451571d10453SEric Joyner 	/* get the current bits from the target bit string */
451671d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
451771d10453SEric Joyner 
451871d10453SEric Joyner 	ice_memcpy(&dest_qword, dest, sizeof(dest_qword), ICE_DMA_TO_NONDMA);
451971d10453SEric Joyner 
452071d10453SEric Joyner 	dest_qword &= ~(CPU_TO_LE64(mask));	/* get the bits not changing */
452171d10453SEric Joyner 	dest_qword |= CPU_TO_LE64(src_qword);	/* add in the new bits */
452271d10453SEric Joyner 
452371d10453SEric Joyner 	/* put it all back */
452471d10453SEric Joyner 	ice_memcpy(dest, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA);
452571d10453SEric Joyner }
452671d10453SEric Joyner 
452771d10453SEric Joyner /**
452871d10453SEric Joyner  * ice_set_ctx - set context bits in packed structure
45297d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
453071d10453SEric Joyner  * @src_ctx:  pointer to a generic non-packed context structure
453171d10453SEric Joyner  * @dest_ctx: pointer to memory for the packed structure
453271d10453SEric Joyner  * @ce_info:  a description of the structure to be transformed
453371d10453SEric Joyner  */
453471d10453SEric Joyner enum ice_status
45357d7af7f8SEric Joyner ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
45367d7af7f8SEric Joyner 	    const struct ice_ctx_ele *ce_info)
453771d10453SEric Joyner {
453871d10453SEric Joyner 	int f;
453971d10453SEric Joyner 
454071d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
454171d10453SEric Joyner 		/* We have to deal with each element of the FW response
454271d10453SEric Joyner 		 * using the correct size so that we are correct regardless
454371d10453SEric Joyner 		 * of the endianness of the machine.
454471d10453SEric Joyner 		 */
45457d7af7f8SEric Joyner 		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
45467d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
45477d7af7f8SEric Joyner 				  f, ce_info[f].width, ce_info[f].size_of);
45487d7af7f8SEric Joyner 			continue;
45497d7af7f8SEric Joyner 		}
455071d10453SEric Joyner 		switch (ce_info[f].size_of) {
455171d10453SEric Joyner 		case sizeof(u8):
455271d10453SEric Joyner 			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
455371d10453SEric Joyner 			break;
455471d10453SEric Joyner 		case sizeof(u16):
455571d10453SEric Joyner 			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
455671d10453SEric Joyner 			break;
455771d10453SEric Joyner 		case sizeof(u32):
455871d10453SEric Joyner 			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
455971d10453SEric Joyner 			break;
456071d10453SEric Joyner 		case sizeof(u64):
456171d10453SEric Joyner 			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
456271d10453SEric Joyner 			break;
456371d10453SEric Joyner 		default:
456471d10453SEric Joyner 			return ICE_ERR_INVAL_SIZE;
456571d10453SEric Joyner 		}
456671d10453SEric Joyner 	}
456771d10453SEric Joyner 
456871d10453SEric Joyner 	return ICE_SUCCESS;
456971d10453SEric Joyner }
457071d10453SEric Joyner 
457171d10453SEric Joyner /**
4572*56429daeSEric Joyner  * ice_aq_get_internal_data
4573*56429daeSEric Joyner  * @hw: pointer to the hardware structure
4574*56429daeSEric Joyner  * @cluster_id: specific cluster to dump
4575*56429daeSEric Joyner  * @table_id: table ID within cluster
4576*56429daeSEric Joyner  * @start: index of line in the block to read
4577*56429daeSEric Joyner  * @buf: dump buffer
4578*56429daeSEric Joyner  * @buf_size: dump buffer size
4579*56429daeSEric Joyner  * @ret_buf_size: return buffer size (returned by FW)
4580*56429daeSEric Joyner  * @ret_next_table: next block to read (returned by FW)
4581*56429daeSEric Joyner  * @ret_next_index: next index to read (returned by FW)
4582*56429daeSEric Joyner  * @cd: pointer to command details structure
4583*56429daeSEric Joyner  *
4584*56429daeSEric Joyner  * Get internal FW/HW data (0xFF08) for debug purposes.
4585*56429daeSEric Joyner  */
4586*56429daeSEric Joyner enum ice_status
4587*56429daeSEric Joyner ice_aq_get_internal_data(struct ice_hw *hw, u8 cluster_id, u16 table_id,
4588*56429daeSEric Joyner 			 u32 start, void *buf, u16 buf_size, u16 *ret_buf_size,
4589*56429daeSEric Joyner 			 u16 *ret_next_table, u32 *ret_next_index,
4590*56429daeSEric Joyner 			 struct ice_sq_cd *cd)
4591*56429daeSEric Joyner {
4592*56429daeSEric Joyner 	struct ice_aqc_debug_dump_internals *cmd;
4593*56429daeSEric Joyner 	struct ice_aq_desc desc;
4594*56429daeSEric Joyner 	enum ice_status status;
4595*56429daeSEric Joyner 
4596*56429daeSEric Joyner 	cmd = &desc.params.debug_dump;
4597*56429daeSEric Joyner 
4598*56429daeSEric Joyner 	if (buf_size == 0 || !buf)
4599*56429daeSEric Joyner 		return ICE_ERR_PARAM;
4600*56429daeSEric Joyner 
4601*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_debug_dump_internals);
4602*56429daeSEric Joyner 
4603*56429daeSEric Joyner 	cmd->cluster_id = cluster_id;
4604*56429daeSEric Joyner 	cmd->table_id = CPU_TO_LE16(table_id);
4605*56429daeSEric Joyner 	cmd->idx = CPU_TO_LE32(start);
4606*56429daeSEric Joyner 
4607*56429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
4608*56429daeSEric Joyner 
4609*56429daeSEric Joyner 	if (!status) {
4610*56429daeSEric Joyner 		if (ret_buf_size)
4611*56429daeSEric Joyner 			*ret_buf_size = LE16_TO_CPU(desc.datalen);
4612*56429daeSEric Joyner 		if (ret_next_table)
4613*56429daeSEric Joyner 			*ret_next_table = LE16_TO_CPU(cmd->table_id);
4614*56429daeSEric Joyner 		if (ret_next_index)
4615*56429daeSEric Joyner 			*ret_next_index = LE32_TO_CPU(cmd->idx);
4616*56429daeSEric Joyner 	}
4617*56429daeSEric Joyner 
4618*56429daeSEric Joyner 	return status;
4619*56429daeSEric Joyner }
4620*56429daeSEric Joyner 
4621*56429daeSEric Joyner /**
462271d10453SEric Joyner  * ice_read_byte - read context byte into struct
462371d10453SEric Joyner  * @src_ctx:  the context structure to read from
462471d10453SEric Joyner  * @dest_ctx: the context to be written to
462571d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
462671d10453SEric Joyner  */
462771d10453SEric Joyner static void
462871d10453SEric Joyner ice_read_byte(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
462971d10453SEric Joyner {
463071d10453SEric Joyner 	u8 dest_byte, mask;
463171d10453SEric Joyner 	u8 *src, *target;
463271d10453SEric Joyner 	u16 shift_width;
463371d10453SEric Joyner 
463471d10453SEric Joyner 	/* prepare the bits and mask */
463571d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
463671d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
463771d10453SEric Joyner 
463871d10453SEric Joyner 	/* shift to correct alignment */
463971d10453SEric Joyner 	mask <<= shift_width;
464071d10453SEric Joyner 
464171d10453SEric Joyner 	/* get the current bits from the src bit string */
464271d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
464371d10453SEric Joyner 
464471d10453SEric Joyner 	ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_DMA_TO_NONDMA);
464571d10453SEric Joyner 
464671d10453SEric Joyner 	dest_byte &= ~(mask);
464771d10453SEric Joyner 
464871d10453SEric Joyner 	dest_byte >>= shift_width;
464971d10453SEric Joyner 
465071d10453SEric Joyner 	/* get the address from the struct field */
465171d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
465271d10453SEric Joyner 
465371d10453SEric Joyner 	/* put it back in the struct */
465471d10453SEric Joyner 	ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA);
465571d10453SEric Joyner }
465671d10453SEric Joyner 
465771d10453SEric Joyner /**
465871d10453SEric Joyner  * ice_read_word - read context word into struct
465971d10453SEric Joyner  * @src_ctx:  the context structure to read from
466071d10453SEric Joyner  * @dest_ctx: the context to be written to
466171d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
466271d10453SEric Joyner  */
466371d10453SEric Joyner static void
466471d10453SEric Joyner ice_read_word(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
466571d10453SEric Joyner {
466671d10453SEric Joyner 	u16 dest_word, mask;
466771d10453SEric Joyner 	u8 *src, *target;
466871d10453SEric Joyner 	__le16 src_word;
466971d10453SEric Joyner 	u16 shift_width;
467071d10453SEric Joyner 
467171d10453SEric Joyner 	/* prepare the bits and mask */
467271d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
467371d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
467471d10453SEric Joyner 
467571d10453SEric Joyner 	/* shift to correct alignment */
467671d10453SEric Joyner 	mask <<= shift_width;
467771d10453SEric Joyner 
467871d10453SEric Joyner 	/* get the current bits from the src bit string */
467971d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
468071d10453SEric Joyner 
468171d10453SEric Joyner 	ice_memcpy(&src_word, src, sizeof(src_word), ICE_DMA_TO_NONDMA);
468271d10453SEric Joyner 
468371d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
468471d10453SEric Joyner 	 * correctly
468571d10453SEric Joyner 	 */
468671d10453SEric Joyner 	src_word &= ~(CPU_TO_LE16(mask));
468771d10453SEric Joyner 
468871d10453SEric Joyner 	/* get the data back into host order before shifting */
468971d10453SEric Joyner 	dest_word = LE16_TO_CPU(src_word);
469071d10453SEric Joyner 
469171d10453SEric Joyner 	dest_word >>= shift_width;
469271d10453SEric Joyner 
469371d10453SEric Joyner 	/* get the address from the struct field */
469471d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
469571d10453SEric Joyner 
469671d10453SEric Joyner 	/* put it back in the struct */
469771d10453SEric Joyner 	ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA);
469871d10453SEric Joyner }
469971d10453SEric Joyner 
470071d10453SEric Joyner /**
470171d10453SEric Joyner  * ice_read_dword - read context dword into struct
470271d10453SEric Joyner  * @src_ctx:  the context structure to read from
470371d10453SEric Joyner  * @dest_ctx: the context to be written to
470471d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
470571d10453SEric Joyner  */
470671d10453SEric Joyner static void
470771d10453SEric Joyner ice_read_dword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
470871d10453SEric Joyner {
470971d10453SEric Joyner 	u32 dest_dword, mask;
471071d10453SEric Joyner 	__le32 src_dword;
471171d10453SEric Joyner 	u8 *src, *target;
471271d10453SEric Joyner 	u16 shift_width;
471371d10453SEric Joyner 
471471d10453SEric Joyner 	/* prepare the bits and mask */
471571d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
471671d10453SEric Joyner 
471771d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
471871d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
471971d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
472071d10453SEric Joyner 	 */
472171d10453SEric Joyner 	if (ce_info->width < 32)
472271d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
472371d10453SEric Joyner 	else
472471d10453SEric Joyner 		mask = (u32)~0;
472571d10453SEric Joyner 
472671d10453SEric Joyner 	/* shift to correct alignment */
472771d10453SEric Joyner 	mask <<= shift_width;
472871d10453SEric Joyner 
472971d10453SEric Joyner 	/* get the current bits from the src bit string */
473071d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
473171d10453SEric Joyner 
473271d10453SEric Joyner 	ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_DMA_TO_NONDMA);
473371d10453SEric Joyner 
473471d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
473571d10453SEric Joyner 	 * correctly
473671d10453SEric Joyner 	 */
473771d10453SEric Joyner 	src_dword &= ~(CPU_TO_LE32(mask));
473871d10453SEric Joyner 
473971d10453SEric Joyner 	/* get the data back into host order before shifting */
474071d10453SEric Joyner 	dest_dword = LE32_TO_CPU(src_dword);
474171d10453SEric Joyner 
474271d10453SEric Joyner 	dest_dword >>= shift_width;
474371d10453SEric Joyner 
474471d10453SEric Joyner 	/* get the address from the struct field */
474571d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
474671d10453SEric Joyner 
474771d10453SEric Joyner 	/* put it back in the struct */
474871d10453SEric Joyner 	ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA);
474971d10453SEric Joyner }
475071d10453SEric Joyner 
475171d10453SEric Joyner /**
475271d10453SEric Joyner  * ice_read_qword - read context qword into struct
475371d10453SEric Joyner  * @src_ctx:  the context structure to read from
475471d10453SEric Joyner  * @dest_ctx: the context to be written to
475571d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
475671d10453SEric Joyner  */
475771d10453SEric Joyner static void
475871d10453SEric Joyner ice_read_qword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
475971d10453SEric Joyner {
476071d10453SEric Joyner 	u64 dest_qword, mask;
476171d10453SEric Joyner 	__le64 src_qword;
476271d10453SEric Joyner 	u8 *src, *target;
476371d10453SEric Joyner 	u16 shift_width;
476471d10453SEric Joyner 
476571d10453SEric Joyner 	/* prepare the bits and mask */
476671d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
476771d10453SEric Joyner 
476871d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
476971d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
477071d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
477171d10453SEric Joyner 	 */
477271d10453SEric Joyner 	if (ce_info->width < 64)
477371d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
477471d10453SEric Joyner 	else
477571d10453SEric Joyner 		mask = (u64)~0;
477671d10453SEric Joyner 
477771d10453SEric Joyner 	/* shift to correct alignment */
477871d10453SEric Joyner 	mask <<= shift_width;
477971d10453SEric Joyner 
478071d10453SEric Joyner 	/* get the current bits from the src bit string */
478171d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
478271d10453SEric Joyner 
478371d10453SEric Joyner 	ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_DMA_TO_NONDMA);
478471d10453SEric Joyner 
478571d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
478671d10453SEric Joyner 	 * correctly
478771d10453SEric Joyner 	 */
478871d10453SEric Joyner 	src_qword &= ~(CPU_TO_LE64(mask));
478971d10453SEric Joyner 
479071d10453SEric Joyner 	/* get the data back into host order before shifting */
479171d10453SEric Joyner 	dest_qword = LE64_TO_CPU(src_qword);
479271d10453SEric Joyner 
479371d10453SEric Joyner 	dest_qword >>= shift_width;
479471d10453SEric Joyner 
479571d10453SEric Joyner 	/* get the address from the struct field */
479671d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
479771d10453SEric Joyner 
479871d10453SEric Joyner 	/* put it back in the struct */
479971d10453SEric Joyner 	ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA);
480071d10453SEric Joyner }
480171d10453SEric Joyner 
480271d10453SEric Joyner /**
480371d10453SEric Joyner  * ice_get_ctx - extract context bits from a packed structure
480471d10453SEric Joyner  * @src_ctx:  pointer to a generic packed context structure
480571d10453SEric Joyner  * @dest_ctx: pointer to a generic non-packed context structure
480671d10453SEric Joyner  * @ce_info:  a description of the structure to be read from
480771d10453SEric Joyner  */
480871d10453SEric Joyner enum ice_status
480971d10453SEric Joyner ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info)
481071d10453SEric Joyner {
481171d10453SEric Joyner 	int f;
481271d10453SEric Joyner 
481371d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
481471d10453SEric Joyner 		switch (ce_info[f].size_of) {
481571d10453SEric Joyner 		case 1:
481671d10453SEric Joyner 			ice_read_byte(src_ctx, dest_ctx, &ce_info[f]);
481771d10453SEric Joyner 			break;
481871d10453SEric Joyner 		case 2:
481971d10453SEric Joyner 			ice_read_word(src_ctx, dest_ctx, &ce_info[f]);
482071d10453SEric Joyner 			break;
482171d10453SEric Joyner 		case 4:
482271d10453SEric Joyner 			ice_read_dword(src_ctx, dest_ctx, &ce_info[f]);
482371d10453SEric Joyner 			break;
482471d10453SEric Joyner 		case 8:
482571d10453SEric Joyner 			ice_read_qword(src_ctx, dest_ctx, &ce_info[f]);
482671d10453SEric Joyner 			break;
482771d10453SEric Joyner 		default:
482871d10453SEric Joyner 			/* nothing to do, just keep going */
482971d10453SEric Joyner 			break;
483071d10453SEric Joyner 		}
483171d10453SEric Joyner 	}
483271d10453SEric Joyner 
483371d10453SEric Joyner 	return ICE_SUCCESS;
483471d10453SEric Joyner }
483571d10453SEric Joyner 
483671d10453SEric Joyner /**
483771d10453SEric Joyner  * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
483871d10453SEric Joyner  * @hw: pointer to the HW struct
483971d10453SEric Joyner  * @vsi_handle: software VSI handle
484071d10453SEric Joyner  * @tc: TC number
484171d10453SEric Joyner  * @q_handle: software queue handle
484271d10453SEric Joyner  */
484371d10453SEric Joyner struct ice_q_ctx *
484471d10453SEric Joyner ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
484571d10453SEric Joyner {
484671d10453SEric Joyner 	struct ice_vsi_ctx *vsi;
484771d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
484871d10453SEric Joyner 
484971d10453SEric Joyner 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
485071d10453SEric Joyner 	if (!vsi)
485171d10453SEric Joyner 		return NULL;
485271d10453SEric Joyner 	if (q_handle >= vsi->num_lan_q_entries[tc])
485371d10453SEric Joyner 		return NULL;
485471d10453SEric Joyner 	if (!vsi->lan_q_ctx[tc])
485571d10453SEric Joyner 		return NULL;
485671d10453SEric Joyner 	q_ctx = vsi->lan_q_ctx[tc];
485771d10453SEric Joyner 	return &q_ctx[q_handle];
485871d10453SEric Joyner }
485971d10453SEric Joyner 
486071d10453SEric Joyner /**
486171d10453SEric Joyner  * ice_ena_vsi_txq
486271d10453SEric Joyner  * @pi: port information structure
486371d10453SEric Joyner  * @vsi_handle: software VSI handle
486471d10453SEric Joyner  * @tc: TC number
486571d10453SEric Joyner  * @q_handle: software queue handle
486671d10453SEric Joyner  * @num_qgrps: Number of added queue groups
486771d10453SEric Joyner  * @buf: list of queue groups to be added
486871d10453SEric Joyner  * @buf_size: size of buffer for indirect command
486971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
487071d10453SEric Joyner  *
487171d10453SEric Joyner  * This function adds one LAN queue
487271d10453SEric Joyner  */
487371d10453SEric Joyner enum ice_status
487471d10453SEric Joyner ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
487571d10453SEric Joyner 		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
487671d10453SEric Joyner 		struct ice_sq_cd *cd)
487771d10453SEric Joyner {
487871d10453SEric Joyner 	struct ice_aqc_txsched_elem_data node = { 0 };
487971d10453SEric Joyner 	struct ice_sched_node *parent;
488071d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
488171d10453SEric Joyner 	enum ice_status status;
488271d10453SEric Joyner 	struct ice_hw *hw;
488371d10453SEric Joyner 
488471d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
488571d10453SEric Joyner 		return ICE_ERR_CFG;
488671d10453SEric Joyner 
488771d10453SEric Joyner 	if (num_qgrps > 1 || buf->num_txqs > 1)
488871d10453SEric Joyner 		return ICE_ERR_MAX_LIMIT;
488971d10453SEric Joyner 
489071d10453SEric Joyner 	hw = pi->hw;
489171d10453SEric Joyner 
489271d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
489371d10453SEric Joyner 		return ICE_ERR_PARAM;
489471d10453SEric Joyner 
489571d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
489671d10453SEric Joyner 
489771d10453SEric Joyner 	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
489871d10453SEric Joyner 	if (!q_ctx) {
489971d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
490071d10453SEric Joyner 			  q_handle);
490171d10453SEric Joyner 		status = ICE_ERR_PARAM;
490271d10453SEric Joyner 		goto ena_txq_exit;
490371d10453SEric Joyner 	}
490471d10453SEric Joyner 
490571d10453SEric Joyner 	/* find a parent node */
490671d10453SEric Joyner 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
490771d10453SEric Joyner 					    ICE_SCHED_NODE_OWNER_LAN);
490871d10453SEric Joyner 	if (!parent) {
490971d10453SEric Joyner 		status = ICE_ERR_PARAM;
491071d10453SEric Joyner 		goto ena_txq_exit;
491171d10453SEric Joyner 	}
491271d10453SEric Joyner 
491371d10453SEric Joyner 	buf->parent_teid = parent->info.node_teid;
491471d10453SEric Joyner 	node.parent_teid = parent->info.node_teid;
491571d10453SEric Joyner 	/* Mark that the values in the "generic" section as valid. The default
491671d10453SEric Joyner 	 * value in the "generic" section is zero. This means that :
491771d10453SEric Joyner 	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
491871d10453SEric Joyner 	 * - 0 priority among siblings, indicated by Bit 1-3.
491971d10453SEric Joyner 	 * - WFQ, indicated by Bit 4.
492071d10453SEric Joyner 	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
492171d10453SEric Joyner 	 * Bit 5-6.
492271d10453SEric Joyner 	 * - Bit 7 is reserved.
492371d10453SEric Joyner 	 * Without setting the generic section as valid in valid_sections, the
492471d10453SEric Joyner 	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
492571d10453SEric Joyner 	 */
49267d7af7f8SEric Joyner 	buf->txqs[0].info.valid_sections =
49277d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
49287d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_EIR;
49297d7af7f8SEric Joyner 	buf->txqs[0].info.generic = 0;
49307d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_profile_idx =
49317d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
49327d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_alloc =
49337d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
49347d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_profile_idx =
49357d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
49367d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_alloc =
49377d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
493871d10453SEric Joyner 
493971d10453SEric Joyner 	/* add the LAN queue */
494071d10453SEric Joyner 	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
494171d10453SEric Joyner 	if (status != ICE_SUCCESS) {
494271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
494371d10453SEric Joyner 			  LE16_TO_CPU(buf->txqs[0].txq_id),
494471d10453SEric Joyner 			  hw->adminq.sq_last_status);
494571d10453SEric Joyner 		goto ena_txq_exit;
494671d10453SEric Joyner 	}
494771d10453SEric Joyner 
494871d10453SEric Joyner 	node.node_teid = buf->txqs[0].q_teid;
494971d10453SEric Joyner 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
495071d10453SEric Joyner 	q_ctx->q_handle = q_handle;
495171d10453SEric Joyner 	q_ctx->q_teid = LE32_TO_CPU(node.node_teid);
495271d10453SEric Joyner 
495371d10453SEric Joyner 	/* add a leaf node into scheduler tree queue layer */
495471d10453SEric Joyner 	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node);
495571d10453SEric Joyner 	if (!status)
495671d10453SEric Joyner 		status = ice_sched_replay_q_bw(pi, q_ctx);
495771d10453SEric Joyner 
495871d10453SEric Joyner ena_txq_exit:
495971d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
496071d10453SEric Joyner 	return status;
496171d10453SEric Joyner }
496271d10453SEric Joyner 
496371d10453SEric Joyner /**
496471d10453SEric Joyner  * ice_dis_vsi_txq
496571d10453SEric Joyner  * @pi: port information structure
496671d10453SEric Joyner  * @vsi_handle: software VSI handle
496771d10453SEric Joyner  * @tc: TC number
496871d10453SEric Joyner  * @num_queues: number of queues
496971d10453SEric Joyner  * @q_handles: pointer to software queue handle array
497071d10453SEric Joyner  * @q_ids: pointer to the q_id array
497171d10453SEric Joyner  * @q_teids: pointer to queue node teids
497271d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
497371d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
497471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
497571d10453SEric Joyner  *
497671d10453SEric Joyner  * This function removes queues and their corresponding nodes in SW DB
497771d10453SEric Joyner  */
497871d10453SEric Joyner enum ice_status
497971d10453SEric Joyner ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
498071d10453SEric Joyner 		u16 *q_handles, u16 *q_ids, u32 *q_teids,
498171d10453SEric Joyner 		enum ice_disq_rst_src rst_src, u16 vmvf_num,
498271d10453SEric Joyner 		struct ice_sq_cd *cd)
498371d10453SEric Joyner {
498471d10453SEric Joyner 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
49857d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *qg_list;
498671d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
49877d7af7f8SEric Joyner 	struct ice_hw *hw;
49887d7af7f8SEric Joyner 	u16 i, buf_size;
498971d10453SEric Joyner 
499071d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
499171d10453SEric Joyner 		return ICE_ERR_CFG;
499271d10453SEric Joyner 
49937d7af7f8SEric Joyner 	hw = pi->hw;
49947d7af7f8SEric Joyner 
499571d10453SEric Joyner 	if (!num_queues) {
499671d10453SEric Joyner 		/* if queue is disabled already yet the disable queue command
499771d10453SEric Joyner 		 * has to be sent to complete the VF reset, then call
499871d10453SEric Joyner 		 * ice_aq_dis_lan_txq without any queue information
499971d10453SEric Joyner 		 */
500071d10453SEric Joyner 		if (rst_src)
50017d7af7f8SEric Joyner 			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
500271d10453SEric Joyner 						  vmvf_num, NULL);
500371d10453SEric Joyner 		return ICE_ERR_CFG;
500471d10453SEric Joyner 	}
500571d10453SEric Joyner 
50067d7af7f8SEric Joyner 	buf_size = ice_struct_size(qg_list, q_id, 1);
50077d7af7f8SEric Joyner 	qg_list = (struct ice_aqc_dis_txq_item *)ice_malloc(hw, buf_size);
50087d7af7f8SEric Joyner 	if (!qg_list)
50097d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
50107d7af7f8SEric Joyner 
501171d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
501271d10453SEric Joyner 
501371d10453SEric Joyner 	for (i = 0; i < num_queues; i++) {
501471d10453SEric Joyner 		struct ice_sched_node *node;
501571d10453SEric Joyner 
501671d10453SEric Joyner 		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
501771d10453SEric Joyner 		if (!node)
501871d10453SEric Joyner 			continue;
50197d7af7f8SEric Joyner 		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
502071d10453SEric Joyner 		if (!q_ctx) {
50217d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
502271d10453SEric Joyner 				  q_handles[i]);
502371d10453SEric Joyner 			continue;
502471d10453SEric Joyner 		}
502571d10453SEric Joyner 		if (q_ctx->q_handle != q_handles[i]) {
50267d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
502771d10453SEric Joyner 				  q_ctx->q_handle, q_handles[i]);
502871d10453SEric Joyner 			continue;
502971d10453SEric Joyner 		}
50307d7af7f8SEric Joyner 		qg_list->parent_teid = node->info.parent_teid;
50317d7af7f8SEric Joyner 		qg_list->num_qs = 1;
50327d7af7f8SEric Joyner 		qg_list->q_id[0] = CPU_TO_LE16(q_ids[i]);
50337d7af7f8SEric Joyner 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
50347d7af7f8SEric Joyner 					    vmvf_num, cd);
503571d10453SEric Joyner 
503671d10453SEric Joyner 		if (status != ICE_SUCCESS)
503771d10453SEric Joyner 			break;
503871d10453SEric Joyner 		ice_free_sched_node(pi, node);
503971d10453SEric Joyner 		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
504071d10453SEric Joyner 	}
504171d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
50427d7af7f8SEric Joyner 	ice_free(hw, qg_list);
504371d10453SEric Joyner 	return status;
504471d10453SEric Joyner }
504571d10453SEric Joyner 
504671d10453SEric Joyner /**
504771d10453SEric Joyner  * ice_cfg_vsi_qs - configure the new/existing VSI queues
504871d10453SEric Joyner  * @pi: port information structure
504971d10453SEric Joyner  * @vsi_handle: software VSI handle
505071d10453SEric Joyner  * @tc_bitmap: TC bitmap
505171d10453SEric Joyner  * @maxqs: max queues array per TC
505271d10453SEric Joyner  * @owner: LAN or RDMA
505371d10453SEric Joyner  *
505471d10453SEric Joyner  * This function adds/updates the VSI queues per TC.
505571d10453SEric Joyner  */
505671d10453SEric Joyner static enum ice_status
505771d10453SEric Joyner ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
505871d10453SEric Joyner 	       u16 *maxqs, u8 owner)
505971d10453SEric Joyner {
506071d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
506171d10453SEric Joyner 	u8 i;
506271d10453SEric Joyner 
506371d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
506471d10453SEric Joyner 		return ICE_ERR_CFG;
506571d10453SEric Joyner 
506671d10453SEric Joyner 	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
506771d10453SEric Joyner 		return ICE_ERR_PARAM;
506871d10453SEric Joyner 
506971d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
507071d10453SEric Joyner 
507171d10453SEric Joyner 	ice_for_each_traffic_class(i) {
507271d10453SEric Joyner 		/* configuration is possible only if TC node is present */
507371d10453SEric Joyner 		if (!ice_sched_get_tc_node(pi, i))
507471d10453SEric Joyner 			continue;
507571d10453SEric Joyner 
507671d10453SEric Joyner 		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
507771d10453SEric Joyner 					   ice_is_tc_ena(tc_bitmap, i));
507871d10453SEric Joyner 		if (status)
507971d10453SEric Joyner 			break;
508071d10453SEric Joyner 	}
508171d10453SEric Joyner 
508271d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
508371d10453SEric Joyner 	return status;
508471d10453SEric Joyner }
508571d10453SEric Joyner 
508671d10453SEric Joyner /**
508771d10453SEric Joyner  * ice_cfg_vsi_lan - configure VSI LAN queues
508871d10453SEric Joyner  * @pi: port information structure
508971d10453SEric Joyner  * @vsi_handle: software VSI handle
509071d10453SEric Joyner  * @tc_bitmap: TC bitmap
509171d10453SEric Joyner  * @max_lanqs: max LAN queues array per TC
509271d10453SEric Joyner  *
509371d10453SEric Joyner  * This function adds/updates the VSI LAN queues per TC.
509471d10453SEric Joyner  */
509571d10453SEric Joyner enum ice_status
509671d10453SEric Joyner ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
509771d10453SEric Joyner 		u16 *max_lanqs)
509871d10453SEric Joyner {
509971d10453SEric Joyner 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
510071d10453SEric Joyner 			      ICE_SCHED_NODE_OWNER_LAN);
510171d10453SEric Joyner }
510271d10453SEric Joyner 
510371d10453SEric Joyner /**
51047d7af7f8SEric Joyner  * ice_is_main_vsi - checks whether the VSI is main VSI
51057d7af7f8SEric Joyner  * @hw: pointer to the HW struct
51067d7af7f8SEric Joyner  * @vsi_handle: VSI handle
51077d7af7f8SEric Joyner  *
51087d7af7f8SEric Joyner  * Checks whether the VSI is the main VSI (the first PF VSI created on
51097d7af7f8SEric Joyner  * given PF).
51107d7af7f8SEric Joyner  */
51117d7af7f8SEric Joyner static bool ice_is_main_vsi(struct ice_hw *hw, u16 vsi_handle)
51127d7af7f8SEric Joyner {
51137d7af7f8SEric Joyner 	return vsi_handle == ICE_MAIN_VSI_HANDLE && hw->vsi_ctx[vsi_handle];
51147d7af7f8SEric Joyner }
51157d7af7f8SEric Joyner 
51167d7af7f8SEric Joyner /**
511771d10453SEric Joyner  * ice_replay_pre_init - replay pre initialization
511871d10453SEric Joyner  * @hw: pointer to the HW struct
51197d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function initializes filters
512071d10453SEric Joyner  *
512171d10453SEric Joyner  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
512271d10453SEric Joyner  */
5123*56429daeSEric Joyner enum ice_status
51247d7af7f8SEric Joyner ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
512571d10453SEric Joyner {
51267d7af7f8SEric Joyner 	enum ice_status status;
512771d10453SEric Joyner 	u8 i;
512871d10453SEric Joyner 
512971d10453SEric Joyner 	/* Delete old entries from replay filter list head if there is any */
51307d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
513171d10453SEric Joyner 	/* In start of replay, move entries into replay_rules list, it
513271d10453SEric Joyner 	 * will allow adding rules entries back to filt_rules list,
513371d10453SEric Joyner 	 * which is operational list.
513471d10453SEric Joyner 	 */
513571d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++)
513671d10453SEric Joyner 		LIST_REPLACE_INIT(&sw->recp_list[i].filt_rules,
513771d10453SEric Joyner 				  &sw->recp_list[i].filt_replay_rules);
513871d10453SEric Joyner 	ice_sched_replay_agg_vsi_preinit(hw);
513971d10453SEric Joyner 
51407d7af7f8SEric Joyner 	status = ice_sched_replay_root_node_bw(hw->port_info);
51417d7af7f8SEric Joyner 	if (status)
51427d7af7f8SEric Joyner 		return status;
51437d7af7f8SEric Joyner 
514471d10453SEric Joyner 	return ice_sched_replay_tc_node_bw(hw->port_info);
514571d10453SEric Joyner }
514671d10453SEric Joyner 
514771d10453SEric Joyner /**
514871d10453SEric Joyner  * ice_replay_vsi - replay VSI configuration
514971d10453SEric Joyner  * @hw: pointer to the HW struct
515071d10453SEric Joyner  * @vsi_handle: driver VSI handle
515171d10453SEric Joyner  *
515271d10453SEric Joyner  * Restore all VSI configuration after reset. It is required to call this
515371d10453SEric Joyner  * function with main VSI first.
515471d10453SEric Joyner  */
515571d10453SEric Joyner enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
515671d10453SEric Joyner {
51577d7af7f8SEric Joyner 	struct ice_switch_info *sw = hw->switch_info;
51587d7af7f8SEric Joyner 	struct ice_port_info *pi = hw->port_info;
515971d10453SEric Joyner 	enum ice_status status;
516071d10453SEric Joyner 
516171d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
516271d10453SEric Joyner 		return ICE_ERR_PARAM;
516371d10453SEric Joyner 
516471d10453SEric Joyner 	/* Replay pre-initialization if there is any */
51657d7af7f8SEric Joyner 	if (ice_is_main_vsi(hw, vsi_handle)) {
51667d7af7f8SEric Joyner 		status = ice_replay_pre_init(hw, sw);
516771d10453SEric Joyner 		if (status)
516871d10453SEric Joyner 			return status;
516971d10453SEric Joyner 	}
517071d10453SEric Joyner 	/* Replay per VSI all RSS configurations */
517171d10453SEric Joyner 	status = ice_replay_rss_cfg(hw, vsi_handle);
517271d10453SEric Joyner 	if (status)
517371d10453SEric Joyner 		return status;
517471d10453SEric Joyner 	/* Replay per VSI all filters */
51757d7af7f8SEric Joyner 	status = ice_replay_vsi_all_fltr(hw, pi, vsi_handle);
517671d10453SEric Joyner 	if (!status)
517771d10453SEric Joyner 		status = ice_replay_vsi_agg(hw, vsi_handle);
517871d10453SEric Joyner 	return status;
517971d10453SEric Joyner }
518071d10453SEric Joyner 
518171d10453SEric Joyner /**
518271d10453SEric Joyner  * ice_replay_post - post replay configuration cleanup
518371d10453SEric Joyner  * @hw: pointer to the HW struct
518471d10453SEric Joyner  *
518571d10453SEric Joyner  * Post replay cleanup.
518671d10453SEric Joyner  */
518771d10453SEric Joyner void ice_replay_post(struct ice_hw *hw)
518871d10453SEric Joyner {
518971d10453SEric Joyner 	/* Delete old entries from replay filter list head */
519071d10453SEric Joyner 	ice_rm_all_sw_replay_rule_info(hw);
519171d10453SEric Joyner 	ice_sched_replay_agg(hw);
519271d10453SEric Joyner }
519371d10453SEric Joyner 
519471d10453SEric Joyner /**
519571d10453SEric Joyner  * ice_stat_update40 - read 40 bit stat from the chip and update stat values
519671d10453SEric Joyner  * @hw: ptr to the hardware info
519771d10453SEric Joyner  * @reg: offset of 64 bit HW register to read from
519871d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
519971d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
520071d10453SEric Joyner  * @cur_stat: ptr to current stat value
520171d10453SEric Joyner  */
520271d10453SEric Joyner void
520371d10453SEric Joyner ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
520471d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
520571d10453SEric Joyner {
520671d10453SEric Joyner 	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
520771d10453SEric Joyner 
520871d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
520971d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
521071d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
521171d10453SEric Joyner 	 * count up from zero.
521271d10453SEric Joyner 	 */
521371d10453SEric Joyner 	if (!prev_stat_loaded) {
521471d10453SEric Joyner 		*prev_stat = new_data;
521571d10453SEric Joyner 		return;
521671d10453SEric Joyner 	}
521771d10453SEric Joyner 
521871d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
521971d10453SEric Joyner 	 * add it to the software stat value.
522071d10453SEric Joyner 	 */
522171d10453SEric Joyner 	if (new_data >= *prev_stat)
522271d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
522371d10453SEric Joyner 	else
522471d10453SEric Joyner 		/* to manage the potential roll-over */
522571d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
522671d10453SEric Joyner 
522771d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
522871d10453SEric Joyner 	*prev_stat = new_data;
522971d10453SEric Joyner }
523071d10453SEric Joyner 
523171d10453SEric Joyner /**
523271d10453SEric Joyner  * ice_stat_update32 - read 32 bit stat from the chip and update stat values
523371d10453SEric Joyner  * @hw: ptr to the hardware info
523471d10453SEric Joyner  * @reg: offset of HW register to read from
523571d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
523671d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
523771d10453SEric Joyner  * @cur_stat: ptr to current stat value
523871d10453SEric Joyner  */
523971d10453SEric Joyner void
524071d10453SEric Joyner ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
524171d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
524271d10453SEric Joyner {
524371d10453SEric Joyner 	u32 new_data;
524471d10453SEric Joyner 
524571d10453SEric Joyner 	new_data = rd32(hw, reg);
524671d10453SEric Joyner 
524771d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
524871d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
524971d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
525071d10453SEric Joyner 	 * count up from zero.
525171d10453SEric Joyner 	 */
525271d10453SEric Joyner 	if (!prev_stat_loaded) {
525371d10453SEric Joyner 		*prev_stat = new_data;
525471d10453SEric Joyner 		return;
525571d10453SEric Joyner 	}
525671d10453SEric Joyner 
525771d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
525871d10453SEric Joyner 	 * add it to the software stat value.
525971d10453SEric Joyner 	 */
526071d10453SEric Joyner 	if (new_data >= *prev_stat)
526171d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
526271d10453SEric Joyner 	else
526371d10453SEric Joyner 		/* to manage the potential roll-over */
526471d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
526571d10453SEric Joyner 
526671d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
526771d10453SEric Joyner 	*prev_stat = new_data;
526871d10453SEric Joyner }
526971d10453SEric Joyner 
527071d10453SEric Joyner /**
527171d10453SEric Joyner  * ice_stat_update_repc - read GLV_REPC stats from chip and update stat values
527271d10453SEric Joyner  * @hw: ptr to the hardware info
527371d10453SEric Joyner  * @vsi_handle: VSI handle
527471d10453SEric Joyner  * @prev_stat_loaded: bool to specify if the previous stat values are loaded
527571d10453SEric Joyner  * @cur_stats: ptr to current stats structure
527671d10453SEric Joyner  *
527771d10453SEric Joyner  * The GLV_REPC statistic register actually tracks two 16bit statistics, and
527871d10453SEric Joyner  * thus cannot be read using the normal ice_stat_update32 function.
527971d10453SEric Joyner  *
528071d10453SEric Joyner  * Read the GLV_REPC register associated with the given VSI, and update the
528171d10453SEric Joyner  * rx_no_desc and rx_error values in the ice_eth_stats structure.
528271d10453SEric Joyner  *
528371d10453SEric Joyner  * Because the statistics in GLV_REPC stick at 0xFFFF, the register must be
528471d10453SEric Joyner  * cleared each time it's read.
528571d10453SEric Joyner  *
528671d10453SEric Joyner  * Note that the GLV_RDPC register also counts the causes that would trigger
528771d10453SEric Joyner  * GLV_REPC. However, it does not give the finer grained detail about why the
528871d10453SEric Joyner  * packets are being dropped. The GLV_REPC values can be used to distinguish
528971d10453SEric Joyner  * whether Rx packets are dropped due to errors or due to no available
529071d10453SEric Joyner  * descriptors.
529171d10453SEric Joyner  */
529271d10453SEric Joyner void
529371d10453SEric Joyner ice_stat_update_repc(struct ice_hw *hw, u16 vsi_handle, bool prev_stat_loaded,
529471d10453SEric Joyner 		     struct ice_eth_stats *cur_stats)
529571d10453SEric Joyner {
529671d10453SEric Joyner 	u16 vsi_num, no_desc, error_cnt;
529771d10453SEric Joyner 	u32 repc;
529871d10453SEric Joyner 
529971d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
530071d10453SEric Joyner 		return;
530171d10453SEric Joyner 
530271d10453SEric Joyner 	vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
530371d10453SEric Joyner 
530471d10453SEric Joyner 	/* If we haven't loaded stats yet, just clear the current value */
530571d10453SEric Joyner 	if (!prev_stat_loaded) {
530671d10453SEric Joyner 		wr32(hw, GLV_REPC(vsi_num), 0);
530771d10453SEric Joyner 		return;
530871d10453SEric Joyner 	}
530971d10453SEric Joyner 
531071d10453SEric Joyner 	repc = rd32(hw, GLV_REPC(vsi_num));
531171d10453SEric Joyner 	no_desc = (repc & GLV_REPC_NO_DESC_CNT_M) >> GLV_REPC_NO_DESC_CNT_S;
531271d10453SEric Joyner 	error_cnt = (repc & GLV_REPC_ERROR_CNT_M) >> GLV_REPC_ERROR_CNT_S;
531371d10453SEric Joyner 
531471d10453SEric Joyner 	/* Clear the count by writing to the stats register */
531571d10453SEric Joyner 	wr32(hw, GLV_REPC(vsi_num), 0);
531671d10453SEric Joyner 
531771d10453SEric Joyner 	cur_stats->rx_no_desc += no_desc;
531871d10453SEric Joyner 	cur_stats->rx_errors += error_cnt;
531971d10453SEric Joyner }
532071d10453SEric Joyner 
532171d10453SEric Joyner /**
532271d10453SEric Joyner  * ice_aq_alternate_write
532371d10453SEric Joyner  * @hw: pointer to the hardware structure
532471d10453SEric Joyner  * @reg_addr0: address of first dword to be written
532571d10453SEric Joyner  * @reg_val0: value to be written under 'reg_addr0'
532671d10453SEric Joyner  * @reg_addr1: address of second dword to be written
532771d10453SEric Joyner  * @reg_val1: value to be written under 'reg_addr1'
532871d10453SEric Joyner  *
532971d10453SEric Joyner  * Write one or two dwords to alternate structure. Fields are indicated
533071d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers.
533171d10453SEric Joyner  */
533271d10453SEric Joyner enum ice_status
533371d10453SEric Joyner ice_aq_alternate_write(struct ice_hw *hw, u32 reg_addr0, u32 reg_val0,
533471d10453SEric Joyner 		       u32 reg_addr1, u32 reg_val1)
533571d10453SEric Joyner {
533671d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
533771d10453SEric Joyner 	struct ice_aq_desc desc;
533871d10453SEric Joyner 	enum ice_status status;
533971d10453SEric Joyner 
534071d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
534171d10453SEric Joyner 
534271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_alt_direct);
534371d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
534471d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
534571d10453SEric Joyner 	cmd->dword0_value = CPU_TO_LE32(reg_val0);
534671d10453SEric Joyner 	cmd->dword1_value = CPU_TO_LE32(reg_val1);
534771d10453SEric Joyner 
534871d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
534971d10453SEric Joyner 
535071d10453SEric Joyner 	return status;
535171d10453SEric Joyner }
535271d10453SEric Joyner 
535371d10453SEric Joyner /**
535471d10453SEric Joyner  * ice_aq_alternate_read
535571d10453SEric Joyner  * @hw: pointer to the hardware structure
535671d10453SEric Joyner  * @reg_addr0: address of first dword to be read
535771d10453SEric Joyner  * @reg_val0: pointer for data read from 'reg_addr0'
535871d10453SEric Joyner  * @reg_addr1: address of second dword to be read
535971d10453SEric Joyner  * @reg_val1: pointer for data read from 'reg_addr1'
536071d10453SEric Joyner  *
536171d10453SEric Joyner  * Read one or two dwords from alternate structure. Fields are indicated
536271d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer
536371d10453SEric Joyner  * is not passed then only register at 'reg_addr0' is read.
536471d10453SEric Joyner  */
536571d10453SEric Joyner enum ice_status
536671d10453SEric Joyner ice_aq_alternate_read(struct ice_hw *hw, u32 reg_addr0, u32 *reg_val0,
536771d10453SEric Joyner 		      u32 reg_addr1, u32 *reg_val1)
536871d10453SEric Joyner {
536971d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
537071d10453SEric Joyner 	struct ice_aq_desc desc;
537171d10453SEric Joyner 	enum ice_status status;
537271d10453SEric Joyner 
537371d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
537471d10453SEric Joyner 
537571d10453SEric Joyner 	if (!reg_val0)
537671d10453SEric Joyner 		return ICE_ERR_PARAM;
537771d10453SEric Joyner 
537871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_alt_direct);
537971d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
538071d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
538171d10453SEric Joyner 
538271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
538371d10453SEric Joyner 
538471d10453SEric Joyner 	if (status == ICE_SUCCESS) {
538571d10453SEric Joyner 		*reg_val0 = LE32_TO_CPU(cmd->dword0_value);
538671d10453SEric Joyner 
538771d10453SEric Joyner 		if (reg_val1)
538871d10453SEric Joyner 			*reg_val1 = LE32_TO_CPU(cmd->dword1_value);
538971d10453SEric Joyner 	}
539071d10453SEric Joyner 
539171d10453SEric Joyner 	return status;
539271d10453SEric Joyner }
539371d10453SEric Joyner 
539471d10453SEric Joyner /**
539571d10453SEric Joyner  *  ice_aq_alternate_write_done
539671d10453SEric Joyner  *  @hw: pointer to the HW structure.
539771d10453SEric Joyner  *  @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS
539871d10453SEric Joyner  *  @reset_needed: indicates the SW should trigger GLOBAL reset
539971d10453SEric Joyner  *
540071d10453SEric Joyner  *  Indicates to the FW that alternate structures have been changed.
540171d10453SEric Joyner  */
540271d10453SEric Joyner enum ice_status
540371d10453SEric Joyner ice_aq_alternate_write_done(struct ice_hw *hw, u8 bios_mode, bool *reset_needed)
540471d10453SEric Joyner {
540571d10453SEric Joyner 	struct ice_aqc_done_alt_write *cmd;
540671d10453SEric Joyner 	struct ice_aq_desc desc;
540771d10453SEric Joyner 	enum ice_status status;
540871d10453SEric Joyner 
540971d10453SEric Joyner 	cmd = &desc.params.done_alt_write;
541071d10453SEric Joyner 
541171d10453SEric Joyner 	if (!reset_needed)
541271d10453SEric Joyner 		return ICE_ERR_PARAM;
541371d10453SEric Joyner 
541471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_done_alt_write);
541571d10453SEric Joyner 	cmd->flags = bios_mode;
541671d10453SEric Joyner 
541771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
541871d10453SEric Joyner 	if (!status)
541971d10453SEric Joyner 		*reset_needed = (LE16_TO_CPU(cmd->flags) &
542071d10453SEric Joyner 				 ICE_AQC_RESP_RESET_NEEDED) != 0;
542171d10453SEric Joyner 
542271d10453SEric Joyner 	return status;
542371d10453SEric Joyner }
542471d10453SEric Joyner 
542571d10453SEric Joyner /**
542671d10453SEric Joyner  *  ice_aq_alternate_clear
542771d10453SEric Joyner  *  @hw: pointer to the HW structure.
542871d10453SEric Joyner  *
542971d10453SEric Joyner  *  Clear the alternate structures of the port from which the function
543071d10453SEric Joyner  *  is called.
543171d10453SEric Joyner  */
543271d10453SEric Joyner enum ice_status ice_aq_alternate_clear(struct ice_hw *hw)
543371d10453SEric Joyner {
543471d10453SEric Joyner 	struct ice_aq_desc desc;
543571d10453SEric Joyner 	enum ice_status status;
543671d10453SEric Joyner 
543771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_port_alt_write);
543871d10453SEric Joyner 
543971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
544071d10453SEric Joyner 
544171d10453SEric Joyner 	return status;
544271d10453SEric Joyner }
544371d10453SEric Joyner 
544471d10453SEric Joyner /**
544571d10453SEric Joyner  * ice_sched_query_elem - query element information from HW
544671d10453SEric Joyner  * @hw: pointer to the HW struct
544771d10453SEric Joyner  * @node_teid: node TEID to be queried
544871d10453SEric Joyner  * @buf: buffer to element information
544971d10453SEric Joyner  *
545071d10453SEric Joyner  * This function queries HW element information
545171d10453SEric Joyner  */
545271d10453SEric Joyner enum ice_status
545371d10453SEric Joyner ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
54547d7af7f8SEric Joyner 		     struct ice_aqc_txsched_elem_data *buf)
545571d10453SEric Joyner {
545671d10453SEric Joyner 	u16 buf_size, num_elem_ret = 0;
545771d10453SEric Joyner 	enum ice_status status;
545871d10453SEric Joyner 
545971d10453SEric Joyner 	buf_size = sizeof(*buf);
546071d10453SEric Joyner 	ice_memset(buf, 0, buf_size, ICE_NONDMA_MEM);
54617d7af7f8SEric Joyner 	buf->node_teid = CPU_TO_LE32(node_teid);
546271d10453SEric Joyner 	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
546371d10453SEric Joyner 					  NULL);
546471d10453SEric Joyner 	if (status != ICE_SUCCESS || num_elem_ret != 1)
546571d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
546671d10453SEric Joyner 	return status;
546771d10453SEric Joyner }
546871d10453SEric Joyner 
546971d10453SEric Joyner /**
547071d10453SEric Joyner  * ice_get_fw_mode - returns FW mode
547171d10453SEric Joyner  * @hw: pointer to the HW struct
547271d10453SEric Joyner  */
547371d10453SEric Joyner enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
547471d10453SEric Joyner {
547571d10453SEric Joyner #define ICE_FW_MODE_DBG_M BIT(0)
547671d10453SEric Joyner #define ICE_FW_MODE_REC_M BIT(1)
547771d10453SEric Joyner #define ICE_FW_MODE_ROLLBACK_M BIT(2)
547871d10453SEric Joyner 	u32 fw_mode;
547971d10453SEric Joyner 
548071d10453SEric Joyner 	/* check the current FW mode */
548171d10453SEric Joyner 	fw_mode = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_MODES_M;
548271d10453SEric Joyner 	if (fw_mode & ICE_FW_MODE_DBG_M)
548371d10453SEric Joyner 		return ICE_FW_MODE_DBG;
548471d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_REC_M)
548571d10453SEric Joyner 		return ICE_FW_MODE_REC;
548671d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_ROLLBACK_M)
548771d10453SEric Joyner 		return ICE_FW_MODE_ROLLBACK;
548871d10453SEric Joyner 	else
548971d10453SEric Joyner 		return ICE_FW_MODE_NORMAL;
549071d10453SEric Joyner }
549171d10453SEric Joyner 
549271d10453SEric Joyner /**
549371d10453SEric Joyner  * ice_cfg_get_cur_lldp_persist_status
549471d10453SEric Joyner  * @hw: pointer to the HW struct
549571d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
549671d10453SEric Joyner  *
549771d10453SEric Joyner  * Get the current status of LLDP persistent
549871d10453SEric Joyner  */
549971d10453SEric Joyner enum ice_status
550071d10453SEric Joyner ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
550171d10453SEric Joyner {
550271d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
550371d10453SEric Joyner 	enum ice_status ret;
550471d10453SEric Joyner 	__le32 raw_data;
550571d10453SEric Joyner 	u32 data, mask;
550671d10453SEric Joyner 
550771d10453SEric Joyner 	if (!lldp_status)
550871d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
550971d10453SEric Joyner 
551071d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
551171d10453SEric Joyner 	if (ret)
551271d10453SEric Joyner 		return ret;
551371d10453SEric Joyner 
551471d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LLDP_PRESERVED_MOD_ID,
551571d10453SEric Joyner 			      ICE_AQC_NVM_CUR_LLDP_PERSIST_RD_OFFSET,
551671d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data,
551771d10453SEric Joyner 			      false, true, NULL);
551871d10453SEric Joyner 	if (!ret) {
551971d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
552071d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
552171d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
552271d10453SEric Joyner 		data = data & mask;
552371d10453SEric Joyner 		*lldp_status = data >>
552471d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
552571d10453SEric Joyner 	}
552671d10453SEric Joyner 
552771d10453SEric Joyner 	ice_release_nvm(hw);
552871d10453SEric Joyner 
552971d10453SEric Joyner 	return ret;
553071d10453SEric Joyner }
553171d10453SEric Joyner 
553271d10453SEric Joyner /**
553371d10453SEric Joyner  * ice_get_dflt_lldp_persist_status
553471d10453SEric Joyner  * @hw: pointer to the HW struct
553571d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
553671d10453SEric Joyner  *
553771d10453SEric Joyner  * Get the default status of LLDP persistent
553871d10453SEric Joyner  */
553971d10453SEric Joyner enum ice_status
554071d10453SEric Joyner ice_get_dflt_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
554171d10453SEric Joyner {
554271d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
554371d10453SEric Joyner 	u32 data, mask, loc_data, loc_data_tmp;
554471d10453SEric Joyner 	enum ice_status ret;
554571d10453SEric Joyner 	__le16 loc_raw_data;
554671d10453SEric Joyner 	__le32 raw_data;
554771d10453SEric Joyner 
554871d10453SEric Joyner 	if (!lldp_status)
554971d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
555071d10453SEric Joyner 
555171d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
555271d10453SEric Joyner 	if (ret)
555371d10453SEric Joyner 		return ret;
555471d10453SEric Joyner 
555571d10453SEric Joyner 	/* Read the offset of EMP_SR_PTR */
555671d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT,
555771d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_OFFSET,
555871d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_RD_LEN,
555971d10453SEric Joyner 			      &loc_raw_data, false, true, NULL);
556071d10453SEric Joyner 	if (ret)
556171d10453SEric Joyner 		goto exit;
556271d10453SEric Joyner 
556371d10453SEric Joyner 	loc_data = LE16_TO_CPU(loc_raw_data);
556471d10453SEric Joyner 	if (loc_data & ICE_AQC_NVM_EMP_SR_PTR_TYPE_M) {
556571d10453SEric Joyner 		loc_data &= ICE_AQC_NVM_EMP_SR_PTR_M;
556671d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_SECTOR_UNIT;
556771d10453SEric Joyner 	} else {
556871d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_WORD_UNIT;
556971d10453SEric Joyner 	}
557071d10453SEric Joyner 
557171d10453SEric Joyner 	/* Read the offset of LLDP configuration pointer */
557271d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_PTR_OFFSET;
557371d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
557471d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_CFG_PTR_RD_LEN, &loc_raw_data,
557571d10453SEric Joyner 			      false, true, NULL);
557671d10453SEric Joyner 	if (ret)
557771d10453SEric Joyner 		goto exit;
557871d10453SEric Joyner 
557971d10453SEric Joyner 	loc_data_tmp = LE16_TO_CPU(loc_raw_data);
558071d10453SEric Joyner 	loc_data_tmp *= ICE_AQC_NVM_WORD_UNIT;
558171d10453SEric Joyner 	loc_data += loc_data_tmp;
558271d10453SEric Joyner 
558371d10453SEric Joyner 	/* We need to skip LLDP configuration section length (2 bytes) */
558471d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_HEADER_LEN;
558571d10453SEric Joyner 
558671d10453SEric Joyner 	/* Read the LLDP Default Configure */
558771d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
558871d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data, false,
558971d10453SEric Joyner 			      true, NULL);
559071d10453SEric Joyner 	if (!ret) {
559171d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
559271d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
559371d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
559471d10453SEric Joyner 		data = data & mask;
559571d10453SEric Joyner 		*lldp_status = data >>
559671d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
559771d10453SEric Joyner 	}
559871d10453SEric Joyner 
559971d10453SEric Joyner exit:
560071d10453SEric Joyner 	ice_release_nvm(hw);
560171d10453SEric Joyner 
560271d10453SEric Joyner 	return ret;
560371d10453SEric Joyner }
560471d10453SEric Joyner 
560571d10453SEric Joyner /**
5606*56429daeSEric Joyner  * ice_aq_read_i2c
5607*56429daeSEric Joyner  * @hw: pointer to the hw struct
5608*56429daeSEric Joyner  * @topo_addr: topology address for a device to communicate with
5609*56429daeSEric Joyner  * @bus_addr: 7-bit I2C bus address
5610*56429daeSEric Joyner  * @addr: I2C memory address (I2C offset) with up to 16 bits
5611*56429daeSEric Joyner  * @params: I2C parameters: bit [7] - Repeated start, bits [6:5] data offset size,
5612*56429daeSEric Joyner  *			    bit [4] - I2C address type, bits [3:0] - data size to read (0-16 bytes)
5613*56429daeSEric Joyner  * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
5614*56429daeSEric Joyner  * @cd: pointer to command details structure or NULL
5615*56429daeSEric Joyner  *
5616*56429daeSEric Joyner  * Read I2C (0x06E2)
5617*56429daeSEric Joyner  */
5618*56429daeSEric Joyner enum ice_status
5619*56429daeSEric Joyner ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
5620*56429daeSEric Joyner 		u16 bus_addr, __le16 addr, u8 params, u8 *data,
5621*56429daeSEric Joyner 		struct ice_sq_cd *cd)
5622*56429daeSEric Joyner {
5623*56429daeSEric Joyner 	struct ice_aq_desc desc = { 0 };
5624*56429daeSEric Joyner 	struct ice_aqc_i2c *cmd;
5625*56429daeSEric Joyner 	enum ice_status status;
5626*56429daeSEric Joyner 	u8 data_size;
5627*56429daeSEric Joyner 
5628*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
5629*56429daeSEric Joyner 	cmd = &desc.params.read_write_i2c;
5630*56429daeSEric Joyner 
5631*56429daeSEric Joyner 	if (!data)
5632*56429daeSEric Joyner 		return ICE_ERR_PARAM;
5633*56429daeSEric Joyner 
5634*56429daeSEric Joyner 	data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
5635*56429daeSEric Joyner 
5636*56429daeSEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
5637*56429daeSEric Joyner 	cmd->topo_addr = topo_addr;
5638*56429daeSEric Joyner 	cmd->i2c_params = params;
5639*56429daeSEric Joyner 	cmd->i2c_addr = addr;
5640*56429daeSEric Joyner 
5641*56429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
5642*56429daeSEric Joyner 	if (!status) {
5643*56429daeSEric Joyner 		struct ice_aqc_read_i2c_resp *resp;
5644*56429daeSEric Joyner 		u8 i;
5645*56429daeSEric Joyner 
5646*56429daeSEric Joyner 		resp = &desc.params.read_i2c_resp;
5647*56429daeSEric Joyner 		for (i = 0; i < data_size; i++) {
5648*56429daeSEric Joyner 			*data = resp->i2c_data[i];
5649*56429daeSEric Joyner 			data++;
5650*56429daeSEric Joyner 		}
5651*56429daeSEric Joyner 	}
5652*56429daeSEric Joyner 
5653*56429daeSEric Joyner 	return status;
5654*56429daeSEric Joyner }
5655*56429daeSEric Joyner 
5656*56429daeSEric Joyner /**
5657*56429daeSEric Joyner  * ice_aq_write_i2c
5658*56429daeSEric Joyner  * @hw: pointer to the hw struct
5659*56429daeSEric Joyner  * @topo_addr: topology address for a device to communicate with
5660*56429daeSEric Joyner  * @bus_addr: 7-bit I2C bus address
5661*56429daeSEric Joyner  * @addr: I2C memory address (I2C offset) with up to 16 bits
5662*56429daeSEric Joyner  * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
5663*56429daeSEric Joyner  * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
5664*56429daeSEric Joyner  * @cd: pointer to command details structure or NULL
5665*56429daeSEric Joyner  *
5666*56429daeSEric Joyner  * Write I2C (0x06E3)
5667*56429daeSEric Joyner  */
5668*56429daeSEric Joyner enum ice_status
5669*56429daeSEric Joyner ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
5670*56429daeSEric Joyner 		 u16 bus_addr, __le16 addr, u8 params, u8 *data,
5671*56429daeSEric Joyner 		 struct ice_sq_cd *cd)
5672*56429daeSEric Joyner {
5673*56429daeSEric Joyner 	struct ice_aq_desc desc = { 0 };
5674*56429daeSEric Joyner 	struct ice_aqc_i2c *cmd;
5675*56429daeSEric Joyner 	u8 i, data_size;
5676*56429daeSEric Joyner 
5677*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
5678*56429daeSEric Joyner 	cmd = &desc.params.read_write_i2c;
5679*56429daeSEric Joyner 
5680*56429daeSEric Joyner 	data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
5681*56429daeSEric Joyner 
5682*56429daeSEric Joyner 	/* data_size limited to 4 */
5683*56429daeSEric Joyner 	if (data_size > 4)
5684*56429daeSEric Joyner 		return ICE_ERR_PARAM;
5685*56429daeSEric Joyner 
5686*56429daeSEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
5687*56429daeSEric Joyner 	cmd->topo_addr = topo_addr;
5688*56429daeSEric Joyner 	cmd->i2c_params = params;
5689*56429daeSEric Joyner 	cmd->i2c_addr = addr;
5690*56429daeSEric Joyner 
5691*56429daeSEric Joyner 	for (i = 0; i < data_size; i++) {
5692*56429daeSEric Joyner 		cmd->i2c_data[i] = *data;
5693*56429daeSEric Joyner 		data++;
5694*56429daeSEric Joyner 	}
5695*56429daeSEric Joyner 
5696*56429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
5697*56429daeSEric Joyner }
5698*56429daeSEric Joyner 
5699*56429daeSEric Joyner /**
5700*56429daeSEric Joyner  * ice_aq_set_gpio
5701*56429daeSEric Joyner  * @hw: pointer to the hw struct
5702*56429daeSEric Joyner  * @gpio_ctrl_handle: GPIO controller node handle
5703*56429daeSEric Joyner  * @pin_idx: IO Number of the GPIO that needs to be set
5704*56429daeSEric Joyner  * @value: SW provide IO value to set in the LSB
5705*56429daeSEric Joyner  * @cd: pointer to command details structure or NULL
5706*56429daeSEric Joyner  *
5707*56429daeSEric Joyner  * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
5708*56429daeSEric Joyner  */
5709*56429daeSEric Joyner enum ice_status
5710*56429daeSEric Joyner ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
5711*56429daeSEric Joyner 		struct ice_sq_cd *cd)
5712*56429daeSEric Joyner {
5713*56429daeSEric Joyner 	struct ice_aqc_gpio *cmd;
5714*56429daeSEric Joyner 	struct ice_aq_desc desc;
5715*56429daeSEric Joyner 
5716*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
5717*56429daeSEric Joyner 	cmd = &desc.params.read_write_gpio;
5718*56429daeSEric Joyner 	cmd->gpio_ctrl_handle = gpio_ctrl_handle;
5719*56429daeSEric Joyner 	cmd->gpio_num = pin_idx;
5720*56429daeSEric Joyner 	cmd->gpio_val = value ? 1 : 0;
5721*56429daeSEric Joyner 
5722*56429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
5723*56429daeSEric Joyner }
5724*56429daeSEric Joyner 
5725*56429daeSEric Joyner /**
5726*56429daeSEric Joyner  * ice_aq_get_gpio
5727*56429daeSEric Joyner  * @hw: pointer to the hw struct
5728*56429daeSEric Joyner  * @gpio_ctrl_handle: GPIO controller node handle
5729*56429daeSEric Joyner  * @pin_idx: IO Number of the GPIO that needs to be set
5730*56429daeSEric Joyner  * @value: IO value read
5731*56429daeSEric Joyner  * @cd: pointer to command details structure or NULL
5732*56429daeSEric Joyner  *
5733*56429daeSEric Joyner  * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
5734*56429daeSEric Joyner  * the topology
5735*56429daeSEric Joyner  */
5736*56429daeSEric Joyner enum ice_status
5737*56429daeSEric Joyner ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
5738*56429daeSEric Joyner 		bool *value, struct ice_sq_cd *cd)
5739*56429daeSEric Joyner {
5740*56429daeSEric Joyner 	struct ice_aqc_gpio *cmd;
5741*56429daeSEric Joyner 	struct ice_aq_desc desc;
5742*56429daeSEric Joyner 	enum ice_status status;
5743*56429daeSEric Joyner 
5744*56429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
5745*56429daeSEric Joyner 	cmd = &desc.params.read_write_gpio;
5746*56429daeSEric Joyner 	cmd->gpio_ctrl_handle = gpio_ctrl_handle;
5747*56429daeSEric Joyner 	cmd->gpio_num = pin_idx;
5748*56429daeSEric Joyner 
5749*56429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
5750*56429daeSEric Joyner 	if (status)
5751*56429daeSEric Joyner 		return status;
5752*56429daeSEric Joyner 
5753*56429daeSEric Joyner 	*value = !!cmd->gpio_val;
5754*56429daeSEric Joyner 	return ICE_SUCCESS;
5755*56429daeSEric Joyner }
5756*56429daeSEric Joyner 
5757*56429daeSEric Joyner /**
575871d10453SEric Joyner  * ice_fw_supports_link_override
575971d10453SEric Joyner  * @hw: pointer to the hardware structure
576071d10453SEric Joyner  *
576171d10453SEric Joyner  * Checks if the firmware supports link override
576271d10453SEric Joyner  */
576371d10453SEric Joyner bool ice_fw_supports_link_override(struct ice_hw *hw)
576471d10453SEric Joyner {
576571d10453SEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_LINK_OVERRIDE_MAJ) {
576671d10453SEric Joyner 		if (hw->api_min_ver > ICE_FW_API_LINK_OVERRIDE_MIN)
576771d10453SEric Joyner 			return true;
576871d10453SEric Joyner 		if (hw->api_min_ver == ICE_FW_API_LINK_OVERRIDE_MIN &&
576971d10453SEric Joyner 		    hw->api_patch >= ICE_FW_API_LINK_OVERRIDE_PATCH)
577071d10453SEric Joyner 			return true;
577171d10453SEric Joyner 	} else if (hw->api_maj_ver > ICE_FW_API_LINK_OVERRIDE_MAJ) {
577271d10453SEric Joyner 		return true;
577371d10453SEric Joyner 	}
577471d10453SEric Joyner 
577571d10453SEric Joyner 	return false;
577671d10453SEric Joyner }
577771d10453SEric Joyner 
577871d10453SEric Joyner /**
577971d10453SEric Joyner  * ice_get_link_default_override
578071d10453SEric Joyner  * @ldo: pointer to the link default override struct
578171d10453SEric Joyner  * @pi: pointer to the port info struct
578271d10453SEric Joyner  *
578371d10453SEric Joyner  * Gets the link default override for a port
578471d10453SEric Joyner  */
578571d10453SEric Joyner enum ice_status
578671d10453SEric Joyner ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
578771d10453SEric Joyner 			      struct ice_port_info *pi)
578871d10453SEric Joyner {
578971d10453SEric Joyner 	u16 i, tlv, tlv_len, tlv_start, buf, offset;
579071d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
579171d10453SEric Joyner 	enum ice_status status;
579271d10453SEric Joyner 
579371d10453SEric Joyner 	status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
579471d10453SEric Joyner 					ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
579571d10453SEric Joyner 	if (status) {
57967d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n");
579771d10453SEric Joyner 		return status;
579871d10453SEric Joyner 	}
579971d10453SEric Joyner 
580071d10453SEric Joyner 	/* Each port has its own config; calculate for our port */
580171d10453SEric Joyner 	tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
580271d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
580371d10453SEric Joyner 
580471d10453SEric Joyner 	/* link options first */
580571d10453SEric Joyner 	status = ice_read_sr_word(hw, tlv_start, &buf);
580671d10453SEric Joyner 	if (status) {
58077d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
580871d10453SEric Joyner 		return status;
580971d10453SEric Joyner 	}
581071d10453SEric Joyner 	ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
581171d10453SEric Joyner 	ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
581271d10453SEric Joyner 		ICE_LINK_OVERRIDE_PHY_CFG_S;
581371d10453SEric Joyner 
581471d10453SEric Joyner 	/* link PHY config */
581571d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
581671d10453SEric Joyner 	status = ice_read_sr_word(hw, offset, &buf);
581771d10453SEric Joyner 	if (status) {
58187d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n");
581971d10453SEric Joyner 		return status;
582071d10453SEric Joyner 	}
582171d10453SEric Joyner 	ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
582271d10453SEric Joyner 
582371d10453SEric Joyner 	/* PHY types low */
582471d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
582571d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
582671d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
582771d10453SEric Joyner 		if (status) {
58287d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
582971d10453SEric Joyner 			return status;
583071d10453SEric Joyner 		}
583171d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
583271d10453SEric Joyner 		ldo->phy_type_low |= ((u64)buf << (i * 16));
583371d10453SEric Joyner 	}
583471d10453SEric Joyner 
583571d10453SEric Joyner 	/* PHY types high */
583671d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
583771d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
583871d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
583971d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
584071d10453SEric Joyner 		if (status) {
58417d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
584271d10453SEric Joyner 			return status;
584371d10453SEric Joyner 		}
584471d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
584571d10453SEric Joyner 		ldo->phy_type_high |= ((u64)buf << (i * 16));
584671d10453SEric Joyner 	}
584771d10453SEric Joyner 
584871d10453SEric Joyner 	return status;
584971d10453SEric Joyner }
58507d7af7f8SEric Joyner 
58517d7af7f8SEric Joyner /**
58527d7af7f8SEric Joyner  * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
58537d7af7f8SEric Joyner  * @caps: get PHY capability data
58547d7af7f8SEric Joyner  */
58557d7af7f8SEric Joyner bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
58567d7af7f8SEric Joyner {
58577d7af7f8SEric Joyner 	if (caps->caps & ICE_AQC_PHY_AN_MODE ||
58587d7af7f8SEric Joyner 	    caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
58597d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE73 |
58607d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE37))
58617d7af7f8SEric Joyner 		return true;
58627d7af7f8SEric Joyner 
58637d7af7f8SEric Joyner 	return false;
58647d7af7f8SEric Joyner }
58657d7af7f8SEric Joyner 
58667d7af7f8SEric Joyner /**
58679cf1841cSEric Joyner  * ice_is_fw_health_report_supported
58689cf1841cSEric Joyner  * @hw: pointer to the hardware structure
58699cf1841cSEric Joyner  *
58709cf1841cSEric Joyner  * Return true if firmware supports health status reports,
58719cf1841cSEric Joyner  * false otherwise
58729cf1841cSEric Joyner  */
58739cf1841cSEric Joyner bool ice_is_fw_health_report_supported(struct ice_hw *hw)
58749cf1841cSEric Joyner {
58759cf1841cSEric Joyner 	if (hw->api_maj_ver > ICE_FW_API_HEALTH_REPORT_MAJ)
58769cf1841cSEric Joyner 		return true;
58779cf1841cSEric Joyner 
58789cf1841cSEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_HEALTH_REPORT_MAJ) {
58799cf1841cSEric Joyner 		if (hw->api_min_ver > ICE_FW_API_HEALTH_REPORT_MIN)
58809cf1841cSEric Joyner 			return true;
58819cf1841cSEric Joyner 		if (hw->api_min_ver == ICE_FW_API_HEALTH_REPORT_MIN &&
58829cf1841cSEric Joyner 		    hw->api_patch >= ICE_FW_API_HEALTH_REPORT_PATCH)
58839cf1841cSEric Joyner 			return true;
58849cf1841cSEric Joyner 	}
58859cf1841cSEric Joyner 
58869cf1841cSEric Joyner 	return false;
58879cf1841cSEric Joyner }
58889cf1841cSEric Joyner 
58899cf1841cSEric Joyner /**
58909cf1841cSEric Joyner  * ice_aq_set_health_status_config - Configure FW health events
58919cf1841cSEric Joyner  * @hw: pointer to the HW struct
58929cf1841cSEric Joyner  * @event_source: type of diagnostic events to enable
58939cf1841cSEric Joyner  * @cd: pointer to command details structure or NULL
58949cf1841cSEric Joyner  *
58959cf1841cSEric Joyner  * Configure the health status event types that the firmware will send to this
58969cf1841cSEric Joyner  * PF. The supported event types are: PF-specific, all PFs, and global
58979cf1841cSEric Joyner  */
58989cf1841cSEric Joyner enum ice_status
58999cf1841cSEric Joyner ice_aq_set_health_status_config(struct ice_hw *hw, u8 event_source,
59009cf1841cSEric Joyner 				struct ice_sq_cd *cd)
59019cf1841cSEric Joyner {
59029cf1841cSEric Joyner 	struct ice_aqc_set_health_status_config *cmd;
59039cf1841cSEric Joyner 	struct ice_aq_desc desc;
59049cf1841cSEric Joyner 
59059cf1841cSEric Joyner 	cmd = &desc.params.set_health_status_config;
59069cf1841cSEric Joyner 
59079cf1841cSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc,
59089cf1841cSEric Joyner 				      ice_aqc_opc_set_health_status_config);
59099cf1841cSEric Joyner 
59109cf1841cSEric Joyner 	cmd->event_source = event_source;
59119cf1841cSEric Joyner 
59129cf1841cSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
59139cf1841cSEric Joyner }
59149cf1841cSEric Joyner 
59159cf1841cSEric Joyner /**
59169cf1841cSEric Joyner  * ice_aq_get_port_options
59179cf1841cSEric Joyner  * @hw: pointer to the hw struct
59189cf1841cSEric Joyner  * @options: buffer for the resultant port options
59199cf1841cSEric Joyner  * @option_count: input - size of the buffer in port options structures,
59209cf1841cSEric Joyner  *                output - number of returned port options
59219cf1841cSEric Joyner  * @lport: logical port to call the command with (optional)
59229cf1841cSEric Joyner  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
59239cf1841cSEric Joyner  *               when PF owns more than 1 port it must be true
59249cf1841cSEric Joyner  * @active_option_idx: index of active port option in returned buffer
59259cf1841cSEric Joyner  * @active_option_valid: active option in returned buffer is valid
59269cf1841cSEric Joyner  *
59279cf1841cSEric Joyner  * Calls Get Port Options AQC (0x06ea) and verifies result.
59289cf1841cSEric Joyner  */
59299cf1841cSEric Joyner enum ice_status
59309cf1841cSEric Joyner ice_aq_get_port_options(struct ice_hw *hw,
59319cf1841cSEric Joyner 			struct ice_aqc_get_port_options_elem *options,
59329cf1841cSEric Joyner 			u8 *option_count, u8 lport, bool lport_valid,
59339cf1841cSEric Joyner 			u8 *active_option_idx, bool *active_option_valid)
59349cf1841cSEric Joyner {
59359cf1841cSEric Joyner 	struct ice_aqc_get_port_options *cmd;
59369cf1841cSEric Joyner 	struct ice_aq_desc desc;
59379cf1841cSEric Joyner 	enum ice_status status;
59389cf1841cSEric Joyner 	u8 pmd_count;
59399cf1841cSEric Joyner 	u8 max_speed;
59409cf1841cSEric Joyner 	u8 i;
59419cf1841cSEric Joyner 
59429cf1841cSEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
59439cf1841cSEric Joyner 
59449cf1841cSEric Joyner 	/* options buffer shall be able to hold max returned options */
59459cf1841cSEric Joyner 	if (*option_count < ICE_AQC_PORT_OPT_COUNT_M)
59469cf1841cSEric Joyner 		return ICE_ERR_PARAM;
59479cf1841cSEric Joyner 
59489cf1841cSEric Joyner 	cmd = &desc.params.get_port_options;
59499cf1841cSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options);
59509cf1841cSEric Joyner 
59519cf1841cSEric Joyner 	if (lport_valid)
59529cf1841cSEric Joyner 		cmd->lport_num = lport;
59539cf1841cSEric Joyner 	cmd->lport_num_valid = lport_valid;
59549cf1841cSEric Joyner 
59559cf1841cSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, options,
59569cf1841cSEric Joyner 				 *option_count * sizeof(*options), NULL);
59579cf1841cSEric Joyner 	if (status != ICE_SUCCESS)
59589cf1841cSEric Joyner 		return status;
59599cf1841cSEric Joyner 
59609cf1841cSEric Joyner 	/* verify direct FW response & set output parameters */
59619cf1841cSEric Joyner 	*option_count = cmd->port_options_count & ICE_AQC_PORT_OPT_COUNT_M;
59629cf1841cSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count);
59639cf1841cSEric Joyner 	*active_option_valid = cmd->port_options & ICE_AQC_PORT_OPT_VALID;
59649cf1841cSEric Joyner 	if (*active_option_valid) {
59659cf1841cSEric Joyner 		*active_option_idx = cmd->port_options &
59669cf1841cSEric Joyner 				     ICE_AQC_PORT_OPT_ACTIVE_M;
59679cf1841cSEric Joyner 		if (*active_option_idx > (*option_count - 1))
59689cf1841cSEric Joyner 			return ICE_ERR_OUT_OF_RANGE;
59699cf1841cSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n",
59709cf1841cSEric Joyner 			  *active_option_idx);
59719cf1841cSEric Joyner 	}
59729cf1841cSEric Joyner 
59739cf1841cSEric Joyner 	/* verify indirect FW response & mask output options fields */
59749cf1841cSEric Joyner 	for (i = 0; i < *option_count; i++) {
59759cf1841cSEric Joyner 		options[i].pmd &= ICE_AQC_PORT_OPT_PMD_COUNT_M;
59769cf1841cSEric Joyner 		options[i].max_lane_speed &= ICE_AQC_PORT_OPT_MAX_LANE_M;
59779cf1841cSEric Joyner 		pmd_count = options[i].pmd;
59789cf1841cSEric Joyner 		max_speed = options[i].max_lane_speed;
59799cf1841cSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n",
59809cf1841cSEric Joyner 			  pmd_count, max_speed);
59819cf1841cSEric Joyner 
59829cf1841cSEric Joyner 		/* check only entries containing valid max pmd speed values,
59839cf1841cSEric Joyner 		 * other reserved values may be returned, when logical port
59849cf1841cSEric Joyner 		 * used is unrelated to specific option
59859cf1841cSEric Joyner 		 */
59869cf1841cSEric Joyner 		if (max_speed <= ICE_AQC_PORT_OPT_MAX_LANE_100G) {
59879cf1841cSEric Joyner 			if (pmd_count > ICE_MAX_PORT_PER_PCI_DEV)
59889cf1841cSEric Joyner 				return ICE_ERR_OUT_OF_RANGE;
59899cf1841cSEric Joyner 			if (pmd_count > 2 &&
59909cf1841cSEric Joyner 			    max_speed > ICE_AQC_PORT_OPT_MAX_LANE_25G)
59919cf1841cSEric Joyner 				return ICE_ERR_CFG;
59929cf1841cSEric Joyner 			if (pmd_count > 7 &&
59939cf1841cSEric Joyner 			    max_speed > ICE_AQC_PORT_OPT_MAX_LANE_10G)
59949cf1841cSEric Joyner 				return ICE_ERR_CFG;
59959cf1841cSEric Joyner 		}
59969cf1841cSEric Joyner 	}
59979cf1841cSEric Joyner 
59989cf1841cSEric Joyner 	return ICE_SUCCESS;
59999cf1841cSEric Joyner }
60009cf1841cSEric Joyner 
60019cf1841cSEric Joyner /**
60027d7af7f8SEric Joyner  * ice_aq_set_lldp_mib - Set the LLDP MIB
60037d7af7f8SEric Joyner  * @hw: pointer to the HW struct
60047d7af7f8SEric Joyner  * @mib_type: Local, Remote or both Local and Remote MIBs
60057d7af7f8SEric Joyner  * @buf: pointer to the caller-supplied buffer to store the MIB block
60067d7af7f8SEric Joyner  * @buf_size: size of the buffer (in bytes)
60077d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
60087d7af7f8SEric Joyner  *
60097d7af7f8SEric Joyner  * Set the LLDP MIB. (0x0A08)
60107d7af7f8SEric Joyner  */
60117d7af7f8SEric Joyner enum ice_status
60127d7af7f8SEric Joyner ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
60137d7af7f8SEric Joyner 		    struct ice_sq_cd *cd)
60147d7af7f8SEric Joyner {
60157d7af7f8SEric Joyner 	struct ice_aqc_lldp_set_local_mib *cmd;
60167d7af7f8SEric Joyner 	struct ice_aq_desc desc;
60177d7af7f8SEric Joyner 
60187d7af7f8SEric Joyner 	cmd = &desc.params.lldp_set_mib;
60197d7af7f8SEric Joyner 
60207d7af7f8SEric Joyner 	if (buf_size == 0 || !buf)
60217d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
60227d7af7f8SEric Joyner 
60237d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
60247d7af7f8SEric Joyner 
60257d7af7f8SEric Joyner 	desc.flags |= CPU_TO_LE16((u16)ICE_AQ_FLAG_RD);
60267d7af7f8SEric Joyner 	desc.datalen = CPU_TO_LE16(buf_size);
60277d7af7f8SEric Joyner 
60287d7af7f8SEric Joyner 	cmd->type = mib_type;
60297d7af7f8SEric Joyner 	cmd->length = CPU_TO_LE16(buf_size);
60307d7af7f8SEric Joyner 
60317d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
60327d7af7f8SEric Joyner }
60337d7af7f8SEric Joyner 
60347d7af7f8SEric Joyner /**
6035*56429daeSEric Joyner  * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
60367d7af7f8SEric Joyner  * @hw: pointer to HW struct
60377d7af7f8SEric Joyner  */
60387d7af7f8SEric Joyner bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
60397d7af7f8SEric Joyner {
60407d7af7f8SEric Joyner 	if (hw->mac_type != ICE_MAC_E810)
60417d7af7f8SEric Joyner 		return false;
60427d7af7f8SEric Joyner 
60437d7af7f8SEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_LLDP_FLTR_MAJ) {
60447d7af7f8SEric Joyner 		if (hw->api_min_ver > ICE_FW_API_LLDP_FLTR_MIN)
60457d7af7f8SEric Joyner 			return true;
60467d7af7f8SEric Joyner 		if (hw->api_min_ver == ICE_FW_API_LLDP_FLTR_MIN &&
60477d7af7f8SEric Joyner 		    hw->api_patch >= ICE_FW_API_LLDP_FLTR_PATCH)
60487d7af7f8SEric Joyner 			return true;
60497d7af7f8SEric Joyner 	} else if (hw->api_maj_ver > ICE_FW_API_LLDP_FLTR_MAJ) {
60507d7af7f8SEric Joyner 		return true;
60517d7af7f8SEric Joyner 	}
60527d7af7f8SEric Joyner 	return false;
60537d7af7f8SEric Joyner }
60547d7af7f8SEric Joyner 
60557d7af7f8SEric Joyner /**
60567d7af7f8SEric Joyner  * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
60577d7af7f8SEric Joyner  * @hw: pointer to HW struct
60587d7af7f8SEric Joyner  * @vsi_num: absolute HW index for VSI
60597d7af7f8SEric Joyner  * @add: boolean for if adding or removing a filter
60607d7af7f8SEric Joyner  */
60617d7af7f8SEric Joyner enum ice_status
60627d7af7f8SEric Joyner ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
60637d7af7f8SEric Joyner {
60647d7af7f8SEric Joyner 	struct ice_aqc_lldp_filter_ctrl *cmd;
60657d7af7f8SEric Joyner 	struct ice_aq_desc desc;
60667d7af7f8SEric Joyner 
60677d7af7f8SEric Joyner 	cmd = &desc.params.lldp_filter_ctrl;
60687d7af7f8SEric Joyner 
60697d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
60707d7af7f8SEric Joyner 
60717d7af7f8SEric Joyner 	if (add)
60727d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
60737d7af7f8SEric Joyner 	else
60747d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
60757d7af7f8SEric Joyner 
60767d7af7f8SEric Joyner 	cmd->vsi_num = CPU_TO_LE16(vsi_num);
60777d7af7f8SEric Joyner 
60787d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
60797d7af7f8SEric Joyner }
60809cf1841cSEric Joyner 
60819cf1841cSEric Joyner /**
60829cf1841cSEric Joyner  * ice_fw_supports_report_dflt_cfg
60839cf1841cSEric Joyner  * @hw: pointer to the hardware structure
60849cf1841cSEric Joyner  *
60859cf1841cSEric Joyner  * Checks if the firmware supports report default configuration
60869cf1841cSEric Joyner  */
60879cf1841cSEric Joyner bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
60889cf1841cSEric Joyner {
60899cf1841cSEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_REPORT_DFLT_CFG_MAJ) {
60909cf1841cSEric Joyner 		if (hw->api_min_ver > ICE_FW_API_REPORT_DFLT_CFG_MIN)
60919cf1841cSEric Joyner 			return true;
60929cf1841cSEric Joyner 		if (hw->api_min_ver == ICE_FW_API_REPORT_DFLT_CFG_MIN &&
60939cf1841cSEric Joyner 		    hw->api_patch >= ICE_FW_API_REPORT_DFLT_CFG_PATCH)
60949cf1841cSEric Joyner 			return true;
60959cf1841cSEric Joyner 	} else if (hw->api_maj_ver > ICE_FW_API_REPORT_DFLT_CFG_MAJ) {
60969cf1841cSEric Joyner 		return true;
60979cf1841cSEric Joyner 	}
60989cf1841cSEric Joyner 	return false;
60999cf1841cSEric Joyner }
6100*56429daeSEric Joyner 
6101*56429daeSEric Joyner /**
6102*56429daeSEric Joyner  * ice_is_fw_auto_drop_supported
6103*56429daeSEric Joyner  * @hw: pointer to the hardware structure
6104*56429daeSEric Joyner  *
6105*56429daeSEric Joyner  * Checks if the firmware supports auto drop feature
6106*56429daeSEric Joyner  */
6107*56429daeSEric Joyner bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)
6108*56429daeSEric Joyner {
6109*56429daeSEric Joyner 	if (hw->api_maj_ver >= ICE_FW_API_AUTO_DROP_MAJ &&
6110*56429daeSEric Joyner 	    hw->api_min_ver >= ICE_FW_API_AUTO_DROP_MIN)
6111*56429daeSEric Joyner 		return true;
6112*56429daeSEric Joyner 	return false;
6113*56429daeSEric Joyner }
6114