xref: /freebsd/sys/dev/ice/ice_common.c (revision f2635e844dd138ac9dfba676f27d41750049af26)
171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2015f8cc5SEric Joyner /*  Copyright (c) 2024, 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 
3271d10453SEric Joyner #include "ice_common.h"
3371d10453SEric Joyner #include "ice_sched.h"
3471d10453SEric Joyner #include "ice_adminq_cmd.h"
3571d10453SEric Joyner #include "ice_flow.h"
3671d10453SEric Joyner #include "ice_switch.h"
3771d10453SEric Joyner 
389dc2f6e2SEric Joyner #define ICE_PF_RESET_WAIT_COUNT	500
3971d10453SEric Joyner 
408923de59SPiotr Kubaj static const char * const ice_link_mode_str_low[] = {
419dc2f6e2SEric Joyner 	ice_arr_elem_idx(0, "100BASE_TX"),
429dc2f6e2SEric Joyner 	ice_arr_elem_idx(1, "100M_SGMII"),
439dc2f6e2SEric Joyner 	ice_arr_elem_idx(2, "1000BASE_T"),
449dc2f6e2SEric Joyner 	ice_arr_elem_idx(3, "1000BASE_SX"),
459dc2f6e2SEric Joyner 	ice_arr_elem_idx(4, "1000BASE_LX"),
469dc2f6e2SEric Joyner 	ice_arr_elem_idx(5, "1000BASE_KX"),
479dc2f6e2SEric Joyner 	ice_arr_elem_idx(6, "1G_SGMII"),
489dc2f6e2SEric Joyner 	ice_arr_elem_idx(7, "2500BASE_T"),
499dc2f6e2SEric Joyner 	ice_arr_elem_idx(8, "2500BASE_X"),
509dc2f6e2SEric Joyner 	ice_arr_elem_idx(9, "2500BASE_KX"),
519dc2f6e2SEric Joyner 	ice_arr_elem_idx(10, "5GBASE_T"),
529dc2f6e2SEric Joyner 	ice_arr_elem_idx(11, "5GBASE_KR"),
539dc2f6e2SEric Joyner 	ice_arr_elem_idx(12, "10GBASE_T"),
549dc2f6e2SEric Joyner 	ice_arr_elem_idx(13, "10G_SFI_DA"),
559dc2f6e2SEric Joyner 	ice_arr_elem_idx(14, "10GBASE_SR"),
569dc2f6e2SEric Joyner 	ice_arr_elem_idx(15, "10GBASE_LR"),
579dc2f6e2SEric Joyner 	ice_arr_elem_idx(16, "10GBASE_KR_CR1"),
589dc2f6e2SEric Joyner 	ice_arr_elem_idx(17, "10G_SFI_AOC_ACC"),
599dc2f6e2SEric Joyner 	ice_arr_elem_idx(18, "10G_SFI_C2C"),
609dc2f6e2SEric Joyner 	ice_arr_elem_idx(19, "25GBASE_T"),
619dc2f6e2SEric Joyner 	ice_arr_elem_idx(20, "25GBASE_CR"),
629dc2f6e2SEric Joyner 	ice_arr_elem_idx(21, "25GBASE_CR_S"),
639dc2f6e2SEric Joyner 	ice_arr_elem_idx(22, "25GBASE_CR1"),
649dc2f6e2SEric Joyner 	ice_arr_elem_idx(23, "25GBASE_SR"),
659dc2f6e2SEric Joyner 	ice_arr_elem_idx(24, "25GBASE_LR"),
669dc2f6e2SEric Joyner 	ice_arr_elem_idx(25, "25GBASE_KR"),
679dc2f6e2SEric Joyner 	ice_arr_elem_idx(26, "25GBASE_KR_S"),
689dc2f6e2SEric Joyner 	ice_arr_elem_idx(27, "25GBASE_KR1"),
699dc2f6e2SEric Joyner 	ice_arr_elem_idx(28, "25G_AUI_AOC_ACC"),
709dc2f6e2SEric Joyner 	ice_arr_elem_idx(29, "25G_AUI_C2C"),
719dc2f6e2SEric Joyner 	ice_arr_elem_idx(30, "40GBASE_CR4"),
729dc2f6e2SEric Joyner 	ice_arr_elem_idx(31, "40GBASE_SR4"),
739dc2f6e2SEric Joyner 	ice_arr_elem_idx(32, "40GBASE_LR4"),
749dc2f6e2SEric Joyner 	ice_arr_elem_idx(33, "40GBASE_KR4"),
759dc2f6e2SEric Joyner 	ice_arr_elem_idx(34, "40G_XLAUI_AOC_ACC"),
769dc2f6e2SEric Joyner 	ice_arr_elem_idx(35, "40G_XLAUI"),
779dc2f6e2SEric Joyner 	ice_arr_elem_idx(36, "50GBASE_CR2"),
789dc2f6e2SEric Joyner 	ice_arr_elem_idx(37, "50GBASE_SR2"),
799dc2f6e2SEric Joyner 	ice_arr_elem_idx(38, "50GBASE_LR2"),
809dc2f6e2SEric Joyner 	ice_arr_elem_idx(39, "50GBASE_KR2"),
819dc2f6e2SEric Joyner 	ice_arr_elem_idx(40, "50G_LAUI2_AOC_ACC"),
829dc2f6e2SEric Joyner 	ice_arr_elem_idx(41, "50G_LAUI2"),
839dc2f6e2SEric Joyner 	ice_arr_elem_idx(42, "50G_AUI2_AOC_ACC"),
849dc2f6e2SEric Joyner 	ice_arr_elem_idx(43, "50G_AUI2"),
859dc2f6e2SEric Joyner 	ice_arr_elem_idx(44, "50GBASE_CP"),
869dc2f6e2SEric Joyner 	ice_arr_elem_idx(45, "50GBASE_SR"),
879dc2f6e2SEric Joyner 	ice_arr_elem_idx(46, "50GBASE_FR"),
889dc2f6e2SEric Joyner 	ice_arr_elem_idx(47, "50GBASE_LR"),
899dc2f6e2SEric Joyner 	ice_arr_elem_idx(48, "50GBASE_KR_PAM4"),
909dc2f6e2SEric Joyner 	ice_arr_elem_idx(49, "50G_AUI1_AOC_ACC"),
919dc2f6e2SEric Joyner 	ice_arr_elem_idx(50, "50G_AUI1"),
929dc2f6e2SEric Joyner 	ice_arr_elem_idx(51, "100GBASE_CR4"),
939dc2f6e2SEric Joyner 	ice_arr_elem_idx(52, "100GBASE_SR4"),
949dc2f6e2SEric Joyner 	ice_arr_elem_idx(53, "100GBASE_LR4"),
959dc2f6e2SEric Joyner 	ice_arr_elem_idx(54, "100GBASE_KR4"),
969dc2f6e2SEric Joyner 	ice_arr_elem_idx(55, "100G_CAUI4_AOC_ACC"),
979dc2f6e2SEric Joyner 	ice_arr_elem_idx(56, "100G_CAUI4"),
989dc2f6e2SEric Joyner 	ice_arr_elem_idx(57, "100G_AUI4_AOC_ACC"),
999dc2f6e2SEric Joyner 	ice_arr_elem_idx(58, "100G_AUI4"),
1009dc2f6e2SEric Joyner 	ice_arr_elem_idx(59, "100GBASE_CR_PAM4"),
1019dc2f6e2SEric Joyner 	ice_arr_elem_idx(60, "100GBASE_KR_PAM4"),
1029dc2f6e2SEric Joyner 	ice_arr_elem_idx(61, "100GBASE_CP2"),
1039dc2f6e2SEric Joyner 	ice_arr_elem_idx(62, "100GBASE_SR2"),
1049dc2f6e2SEric Joyner 	ice_arr_elem_idx(63, "100GBASE_DR"),
1058923de59SPiotr Kubaj };
1068923de59SPiotr Kubaj 
1078923de59SPiotr Kubaj static const char * const ice_link_mode_str_high[] = {
1089dc2f6e2SEric Joyner 	ice_arr_elem_idx(0, "100GBASE_KR2_PAM4"),
1099dc2f6e2SEric Joyner 	ice_arr_elem_idx(1, "100G_CAUI2_AOC_ACC"),
1109dc2f6e2SEric Joyner 	ice_arr_elem_idx(2, "100G_CAUI2"),
1119dc2f6e2SEric Joyner 	ice_arr_elem_idx(3, "100G_AUI2_AOC_ACC"),
1129dc2f6e2SEric Joyner 	ice_arr_elem_idx(4, "100G_AUI2"),
113*f2635e84SEric Joyner 	ice_arr_elem_idx(5, "200G_CR4_PAM4"),
114*f2635e84SEric Joyner 	ice_arr_elem_idx(6, "200G_SR4"),
115*f2635e84SEric Joyner 	ice_arr_elem_idx(7, "200G_FR4"),
116*f2635e84SEric Joyner 	ice_arr_elem_idx(8, "200G_LR4"),
117*f2635e84SEric Joyner 	ice_arr_elem_idx(9, "200G_DR4"),
118*f2635e84SEric Joyner 	ice_arr_elem_idx(10, "200G_KR4_PAM4"),
119*f2635e84SEric Joyner 	ice_arr_elem_idx(11, "200G_AUI4_AOC_ACC"),
120*f2635e84SEric Joyner 	ice_arr_elem_idx(12, "200G_AUI4"),
121*f2635e84SEric Joyner 	ice_arr_elem_idx(13, "200G_AUI8_AOC_ACC"),
122*f2635e84SEric Joyner 	ice_arr_elem_idx(14, "200G_AUI8"),
123*f2635e84SEric Joyner 	ice_arr_elem_idx(15, "400GBASE_FR8"),
1248923de59SPiotr Kubaj };
12556429daeSEric Joyner 
12656429daeSEric Joyner /**
1278923de59SPiotr Kubaj  * ice_dump_phy_type - helper function to dump phy_type
12856429daeSEric Joyner  * @hw: pointer to the HW structure
12956429daeSEric Joyner  * @low: 64 bit value for phy_type_low
13056429daeSEric Joyner  * @high: 64 bit value for phy_type_high
13156429daeSEric Joyner  * @prefix: prefix string to differentiate multiple dumps
13256429daeSEric Joyner  */
13356429daeSEric Joyner static void
1348923de59SPiotr Kubaj ice_dump_phy_type(struct ice_hw *hw, u64 low, u64 high, const char *prefix)
13556429daeSEric Joyner {
1368923de59SPiotr Kubaj 	u32 i;
1378923de59SPiotr Kubaj 
1388923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix,
1398923de59SPiotr Kubaj 		  (unsigned long long)low);
1408923de59SPiotr Kubaj 
1418923de59SPiotr Kubaj 	for (i = 0; i < ARRAY_SIZE(ice_link_mode_str_low); i++) {
1428923de59SPiotr Kubaj 		if (low & BIT_ULL(i))
1438923de59SPiotr Kubaj 			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
1448923de59SPiotr Kubaj 				  prefix, i, ice_link_mode_str_low[i]);
1458923de59SPiotr Kubaj 	}
1468923de59SPiotr Kubaj 
14756429daeSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix,
14856429daeSEric Joyner 		  (unsigned long long)high);
14956429daeSEric Joyner 
1508923de59SPiotr Kubaj 	for (i = 0; i < ARRAY_SIZE(ice_link_mode_str_high); i++) {
1518923de59SPiotr Kubaj 		if (high & BIT_ULL(i))
1528923de59SPiotr Kubaj 			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
1538923de59SPiotr Kubaj 				  prefix, i, ice_link_mode_str_high[i]);
1548923de59SPiotr Kubaj 	}
15556429daeSEric Joyner }
15656429daeSEric Joyner 
15756429daeSEric Joyner /**
15871d10453SEric Joyner  * ice_set_mac_type - Sets MAC type
15971d10453SEric Joyner  * @hw: pointer to the HW structure
16071d10453SEric Joyner  *
16171d10453SEric Joyner  * This function sets the MAC type of the adapter based on the
16271d10453SEric Joyner  * vendor ID and device ID stored in the HW structure.
16371d10453SEric Joyner  */
164*f2635e84SEric Joyner int ice_set_mac_type(struct ice_hw *hw)
16571d10453SEric Joyner {
16671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
16771d10453SEric Joyner 
16871d10453SEric Joyner 	if (hw->vendor_id != ICE_INTEL_VENDOR_ID)
16971d10453SEric Joyner 		return ICE_ERR_DEVICE_NOT_SUPPORTED;
17071d10453SEric Joyner 
17171d10453SEric Joyner 	switch (hw->device_id) {
17271d10453SEric Joyner 	case ICE_DEV_ID_E810C_BACKPLANE:
17371d10453SEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
17471d10453SEric Joyner 	case ICE_DEV_ID_E810C_SFP:
17571d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_BACKPLANE:
17671d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_QSFP:
17771d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_SFP:
17871d10453SEric Joyner 		hw->mac_type = ICE_MAC_E810;
17971d10453SEric Joyner 		break;
18071d10453SEric Joyner 	case ICE_DEV_ID_E822C_10G_BASE_T:
18171d10453SEric Joyner 	case ICE_DEV_ID_E822C_BACKPLANE:
18271d10453SEric Joyner 	case ICE_DEV_ID_E822C_QSFP:
18371d10453SEric Joyner 	case ICE_DEV_ID_E822C_SFP:
18471d10453SEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
18571d10453SEric Joyner 	case ICE_DEV_ID_E822L_10G_BASE_T:
18671d10453SEric Joyner 	case ICE_DEV_ID_E822L_BACKPLANE:
18771d10453SEric Joyner 	case ICE_DEV_ID_E822L_SFP:
18871d10453SEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
18971d10453SEric Joyner 	case ICE_DEV_ID_E823L_10G_BASE_T:
19071d10453SEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
19171d10453SEric Joyner 	case ICE_DEV_ID_E823L_BACKPLANE:
19271d10453SEric Joyner 	case ICE_DEV_ID_E823L_QSFP:
19371d10453SEric Joyner 	case ICE_DEV_ID_E823L_SFP:
19456429daeSEric Joyner 	case ICE_DEV_ID_E823C_10G_BASE_T:
19556429daeSEric Joyner 	case ICE_DEV_ID_E823C_BACKPLANE:
19656429daeSEric Joyner 	case ICE_DEV_ID_E823C_QSFP:
19756429daeSEric Joyner 	case ICE_DEV_ID_E823C_SFP:
19856429daeSEric Joyner 	case ICE_DEV_ID_E823C_SGMII:
19971d10453SEric Joyner 		hw->mac_type = ICE_MAC_GENERIC;
20071d10453SEric Joyner 		break;
201*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_BACKPLANE:
202*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_QSFP:
203*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_SFP:
204*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_SGMII:
205*f2635e84SEric Joyner 		hw->mac_type = ICE_MAC_GENERIC_3K_E825;
206*f2635e84SEric Joyner 		break;
207*f2635e84SEric Joyner 	case ICE_DEV_ID_E830_BACKPLANE:
208*f2635e84SEric Joyner 	case ICE_DEV_ID_E830_QSFP56:
209*f2635e84SEric Joyner 	case ICE_DEV_ID_E830_SFP:
210*f2635e84SEric Joyner 	case ICE_DEV_ID_E830C_BACKPLANE:
211*f2635e84SEric Joyner 	case ICE_DEV_ID_E830_L_BACKPLANE:
212*f2635e84SEric Joyner 	case ICE_DEV_ID_E830C_QSFP:
213*f2635e84SEric Joyner 	case ICE_DEV_ID_E830_L_QSFP:
214*f2635e84SEric Joyner 	case ICE_DEV_ID_E830C_SFP:
215*f2635e84SEric Joyner 	case ICE_DEV_ID_E830_L_SFP:
216*f2635e84SEric Joyner 		hw->mac_type = ICE_MAC_E830;
217*f2635e84SEric Joyner 		break;
21871d10453SEric Joyner 	default:
21971d10453SEric Joyner 		hw->mac_type = ICE_MAC_UNKNOWN;
22071d10453SEric Joyner 		break;
22171d10453SEric Joyner 	}
22271d10453SEric Joyner 
22371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
224*f2635e84SEric Joyner 	return 0;
225*f2635e84SEric Joyner }
226*f2635e84SEric Joyner 
227*f2635e84SEric Joyner /**
228*f2635e84SEric Joyner  * ice_is_generic_mac
229*f2635e84SEric Joyner  * @hw: pointer to the hardware structure
230*f2635e84SEric Joyner  *
231*f2635e84SEric Joyner  * returns true if mac_type is ICE_MAC_GENERIC, false if not
232*f2635e84SEric Joyner  */
233*f2635e84SEric Joyner bool ice_is_generic_mac(struct ice_hw *hw)
234*f2635e84SEric Joyner {
235*f2635e84SEric Joyner 	return (hw->mac_type == ICE_MAC_GENERIC ||
236*f2635e84SEric Joyner 		hw->mac_type == ICE_MAC_GENERIC_3K ||
237*f2635e84SEric Joyner 		hw->mac_type == ICE_MAC_GENERIC_3K_E825);
23871d10453SEric Joyner }
23971d10453SEric Joyner 
24071d10453SEric Joyner /**
24156429daeSEric Joyner  * ice_is_e810
24256429daeSEric Joyner  * @hw: pointer to the hardware structure
24356429daeSEric Joyner  *
24456429daeSEric Joyner  * returns true if the device is E810 based, false if not.
24556429daeSEric Joyner  */
24656429daeSEric Joyner bool ice_is_e810(struct ice_hw *hw)
24756429daeSEric Joyner {
24856429daeSEric Joyner 	return hw->mac_type == ICE_MAC_E810;
24956429daeSEric Joyner }
25056429daeSEric Joyner 
25156429daeSEric Joyner /**
25256429daeSEric Joyner  * ice_is_e810t
25356429daeSEric Joyner  * @hw: pointer to the hardware structure
25456429daeSEric Joyner  *
25556429daeSEric Joyner  * returns true if the device is E810T based, false if not.
25656429daeSEric Joyner  */
25756429daeSEric Joyner bool ice_is_e810t(struct ice_hw *hw)
25856429daeSEric Joyner {
25956429daeSEric Joyner 	switch (hw->device_id) {
26056429daeSEric Joyner 	case ICE_DEV_ID_E810C_SFP:
2618923de59SPiotr Kubaj 		switch (hw->subsystem_device_id) {
2628923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T:
2638923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T2:
2648923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T3:
2658923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T4:
266*f2635e84SEric Joyner 		case ICE_SUBDEV_ID_E810T6:
2678923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T7:
26856429daeSEric Joyner 			return true;
2698923de59SPiotr Kubaj 		}
27056429daeSEric Joyner 		break;
27156429daeSEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
2728923de59SPiotr Kubaj 		switch (hw->subsystem_device_id) {
2738923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T2:
274*f2635e84SEric Joyner 		case ICE_SUBDEV_ID_E810T3:
2758923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T5:
27656429daeSEric Joyner 			return true;
2778923de59SPiotr Kubaj 		}
27856429daeSEric Joyner 		break;
27956429daeSEric Joyner 	default:
28056429daeSEric Joyner 		break;
28156429daeSEric Joyner 	}
28256429daeSEric Joyner 
28356429daeSEric Joyner 	return false;
28456429daeSEric Joyner }
28556429daeSEric Joyner 
28656429daeSEric Joyner /**
287*f2635e84SEric Joyner  * ice_is_e830
288*f2635e84SEric Joyner  * @hw: pointer to the hardware structure
289*f2635e84SEric Joyner  *
290*f2635e84SEric Joyner  * returns true if the device is E830 based, false if not.
291*f2635e84SEric Joyner  */
292*f2635e84SEric Joyner bool ice_is_e830(struct ice_hw *hw)
293*f2635e84SEric Joyner {
294*f2635e84SEric Joyner 	return hw->mac_type == ICE_MAC_E830;
295*f2635e84SEric Joyner }
296*f2635e84SEric Joyner 
297*f2635e84SEric Joyner /**
2988923de59SPiotr Kubaj  * ice_is_e823
2998923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
3008923de59SPiotr Kubaj  *
3018923de59SPiotr Kubaj  * returns true if the device is E823-L or E823-C based, false if not.
3028923de59SPiotr Kubaj  */
3038923de59SPiotr Kubaj bool ice_is_e823(struct ice_hw *hw)
3048923de59SPiotr Kubaj {
3058923de59SPiotr Kubaj 	switch (hw->device_id) {
3068923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_BACKPLANE:
3078923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_SFP:
3088923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_10G_BASE_T:
3098923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_1GBE:
3108923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_QSFP:
3118923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_BACKPLANE:
3128923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_QSFP:
3138923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_SFP:
3148923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_10G_BASE_T:
3158923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_SGMII:
3168923de59SPiotr Kubaj 		return true;
3178923de59SPiotr Kubaj 	default:
3188923de59SPiotr Kubaj 		return false;
3198923de59SPiotr Kubaj 	}
3208923de59SPiotr Kubaj }
3218923de59SPiotr Kubaj 
3228923de59SPiotr Kubaj /**
323*f2635e84SEric Joyner  * ice_is_e825c
324*f2635e84SEric Joyner  * @hw: pointer to the hardware structure
325*f2635e84SEric Joyner  *
326*f2635e84SEric Joyner  * returns true if the device is E825-C based, false if not.
327*f2635e84SEric Joyner  */
328*f2635e84SEric Joyner bool ice_is_e825c(struct ice_hw *hw)
329*f2635e84SEric Joyner {
330*f2635e84SEric Joyner 	switch (hw->device_id) {
331*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_BACKPLANE:
332*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_QSFP:
333*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_SFP:
334*f2635e84SEric Joyner 	case ICE_DEV_ID_E825C_SGMII:
335*f2635e84SEric Joyner 		return true;
336*f2635e84SEric Joyner 	default:
337*f2635e84SEric Joyner 		return false;
338*f2635e84SEric Joyner 	}
339*f2635e84SEric Joyner }
340*f2635e84SEric Joyner 
341*f2635e84SEric Joyner /**
34271d10453SEric Joyner  * ice_clear_pf_cfg - Clear PF configuration
34371d10453SEric Joyner  * @hw: pointer to the hardware structure
34471d10453SEric Joyner  *
34571d10453SEric Joyner  * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
34671d10453SEric Joyner  * configuration, flow director filters, etc.).
34771d10453SEric Joyner  */
348*f2635e84SEric Joyner int ice_clear_pf_cfg(struct ice_hw *hw)
34971d10453SEric Joyner {
35071d10453SEric Joyner 	struct ice_aq_desc desc;
35171d10453SEric Joyner 
35271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
35371d10453SEric Joyner 
35471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
35571d10453SEric Joyner }
35671d10453SEric Joyner 
35771d10453SEric Joyner /**
35871d10453SEric Joyner  * ice_aq_manage_mac_read - manage MAC address read command
35971d10453SEric Joyner  * @hw: pointer to the HW struct
36071d10453SEric Joyner  * @buf: a virtual buffer to hold the manage MAC read response
36171d10453SEric Joyner  * @buf_size: Size of the virtual buffer
36271d10453SEric Joyner  * @cd: pointer to command details structure or NULL
36371d10453SEric Joyner  *
36471d10453SEric Joyner  * This function is used to return per PF station MAC address (0x0107).
36571d10453SEric Joyner  * NOTE: Upon successful completion of this command, MAC address information
36671d10453SEric Joyner  * is returned in user specified buffer. Please interpret user specified
36771d10453SEric Joyner  * buffer as "manage_mac_read" response.
36871d10453SEric Joyner  * Response such as various MAC addresses are stored in HW struct (port.mac)
3697d7af7f8SEric Joyner  * ice_discover_dev_caps is expected to be called before this function is
3707d7af7f8SEric Joyner  * called.
37171d10453SEric Joyner  */
372*f2635e84SEric Joyner int
37371d10453SEric Joyner ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
37471d10453SEric Joyner 		       struct ice_sq_cd *cd)
37571d10453SEric Joyner {
37671d10453SEric Joyner 	struct ice_aqc_manage_mac_read_resp *resp;
37771d10453SEric Joyner 	struct ice_aqc_manage_mac_read *cmd;
37871d10453SEric Joyner 	struct ice_aq_desc desc;
379*f2635e84SEric Joyner 	int status;
38071d10453SEric Joyner 	u16 flags;
38171d10453SEric Joyner 	u8 i;
38271d10453SEric Joyner 
38371d10453SEric Joyner 	cmd = &desc.params.mac_read;
38471d10453SEric Joyner 
38571d10453SEric Joyner 	if (buf_size < sizeof(*resp))
38671d10453SEric Joyner 		return ICE_ERR_BUF_TOO_SHORT;
38771d10453SEric Joyner 
38871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
38971d10453SEric Joyner 
39071d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
39171d10453SEric Joyner 	if (status)
39271d10453SEric Joyner 		return status;
39371d10453SEric Joyner 
39471d10453SEric Joyner 	resp = (struct ice_aqc_manage_mac_read_resp *)buf;
39571d10453SEric Joyner 	flags = LE16_TO_CPU(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
39671d10453SEric Joyner 
39771d10453SEric Joyner 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
39871d10453SEric Joyner 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
39971d10453SEric Joyner 		return ICE_ERR_CFG;
40071d10453SEric Joyner 	}
40171d10453SEric Joyner 
40271d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
40371d10453SEric Joyner 	for (i = 0; i < cmd->num_addr; i++)
40471d10453SEric Joyner 		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
40571d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.lan_addr,
40671d10453SEric Joyner 				   resp[i].mac_addr, ETH_ALEN,
4078923de59SPiotr Kubaj 				   ICE_NONDMA_TO_NONDMA);
40871d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.perm_addr,
40971d10453SEric Joyner 				   resp[i].mac_addr,
4108923de59SPiotr Kubaj 				   ETH_ALEN, ICE_NONDMA_TO_NONDMA);
41171d10453SEric Joyner 			break;
41271d10453SEric Joyner 		}
413*f2635e84SEric Joyner 	return 0;
41471d10453SEric Joyner }
41571d10453SEric Joyner 
41671d10453SEric Joyner /**
4179c30461dSEric Joyner  * ice_phy_maps_to_media
4189c30461dSEric Joyner  * @phy_type_low: PHY type low bits
4199c30461dSEric Joyner  * @phy_type_high: PHY type high bits
4209c30461dSEric Joyner  * @media_mask_low: media type PHY type low bitmask
4219c30461dSEric Joyner  * @media_mask_high: media type PHY type high bitmask
4229c30461dSEric Joyner  *
4239c30461dSEric Joyner  * Return true if PHY type [low|high] bits are only of media type PHY types
4249c30461dSEric Joyner  * [low|high] bitmask.
4259c30461dSEric Joyner  */
4269c30461dSEric Joyner static bool
4279c30461dSEric Joyner ice_phy_maps_to_media(u64 phy_type_low, u64 phy_type_high,
4289c30461dSEric Joyner 		      u64 media_mask_low, u64 media_mask_high)
4299c30461dSEric Joyner {
4309c30461dSEric Joyner 	/* check if a PHY type exist for media type */
4319c30461dSEric Joyner 	if (!(phy_type_low & media_mask_low ||
4329c30461dSEric Joyner 	      phy_type_high & media_mask_high))
4339c30461dSEric Joyner 		return false;
4349c30461dSEric Joyner 
4359c30461dSEric Joyner 	/* check that PHY types are only of media type */
4369c30461dSEric Joyner 	if (!(phy_type_low & ~media_mask_low) &&
4379c30461dSEric Joyner 	    !(phy_type_high & ~media_mask_high))
4389c30461dSEric Joyner 		return true;
4399c30461dSEric Joyner 
4409c30461dSEric Joyner 	return false;
4419c30461dSEric Joyner }
4429c30461dSEric Joyner 
4439c30461dSEric Joyner /**
4449c30461dSEric Joyner  * ice_set_media_type - Sets media type
4459c30461dSEric Joyner  * @pi: port information structure
4469c30461dSEric Joyner  *
4479c30461dSEric Joyner  * Set ice_port_info PHY media type based on PHY type. This should be called
4489c30461dSEric Joyner  * from Get PHY caps with media.
4499c30461dSEric Joyner  */
4509c30461dSEric Joyner static void ice_set_media_type(struct ice_port_info *pi)
4519c30461dSEric Joyner {
4529c30461dSEric Joyner 	enum ice_media_type *media_type;
4539c30461dSEric Joyner 	u64 phy_type_high, phy_type_low;
4549c30461dSEric Joyner 
4559c30461dSEric Joyner 	phy_type_high = pi->phy.phy_type_high;
4569c30461dSEric Joyner 	phy_type_low = pi->phy.phy_type_low;
4579c30461dSEric Joyner 	media_type = &pi->phy.media_type;
4589c30461dSEric Joyner 
4599c30461dSEric Joyner 	/* if no media, then media type is NONE */
4609c30461dSEric Joyner 	if (!(pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE))
4619c30461dSEric Joyner 		*media_type = ICE_MEDIA_NONE;
4629c30461dSEric Joyner 	/* else if PHY types are only BASE-T, then media type is BASET */
4639c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
4649c30461dSEric Joyner 				       ICE_MEDIA_BASET_PHY_TYPE_LOW_M, 0))
4659c30461dSEric Joyner 		*media_type = ICE_MEDIA_BASET;
4669c30461dSEric Joyner 	/* else if any PHY type is BACKPLANE, then media type is BACKPLANE */
4679c30461dSEric Joyner 	else if (phy_type_low & ICE_MEDIA_BP_PHY_TYPE_LOW_M ||
4689c30461dSEric Joyner 		 phy_type_high & ICE_MEDIA_BP_PHY_TYPE_HIGH_M)
4699c30461dSEric Joyner 		*media_type = ICE_MEDIA_BACKPLANE;
4709c30461dSEric Joyner 	/* else if PHY types are only optical, or optical and C2M, then media
4719c30461dSEric Joyner 	 * type is FIBER
4729c30461dSEric Joyner 	 */
4739c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
474*f2635e84SEric Joyner 				       ICE_MEDIA_OPT_PHY_TYPE_LOW_M,
475*f2635e84SEric Joyner 				       ICE_MEDIA_OPT_PHY_TYPE_HIGH_M) ||
476*f2635e84SEric Joyner 		 ((phy_type_low & ICE_MEDIA_OPT_PHY_TYPE_LOW_M ||
477*f2635e84SEric Joyner 		   phy_type_high & ICE_MEDIA_OPT_PHY_TYPE_HIGH_M) &&
478*f2635e84SEric Joyner 		  (phy_type_low & ICE_MEDIA_C2M_PHY_TYPE_LOW_M ||
479*f2635e84SEric Joyner 		   phy_type_high & ICE_MEDIA_C2C_PHY_TYPE_HIGH_M)))
4809c30461dSEric Joyner 		*media_type = ICE_MEDIA_FIBER;
4819c30461dSEric Joyner 	/* else if PHY types are only DA, or DA and C2C, then media type DA */
4829c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
483*f2635e84SEric Joyner 				       ICE_MEDIA_DAC_PHY_TYPE_LOW_M,
484*f2635e84SEric Joyner 				       ICE_MEDIA_DAC_PHY_TYPE_HIGH_M) ||
485*f2635e84SEric Joyner 		 ((phy_type_low & ICE_MEDIA_DAC_PHY_TYPE_LOW_M ||
486*f2635e84SEric Joyner 		   phy_type_high & ICE_MEDIA_DAC_PHY_TYPE_HIGH_M) &&
4879c30461dSEric Joyner 		  (phy_type_low & ICE_MEDIA_C2C_PHY_TYPE_LOW_M ||
4889c30461dSEric Joyner 		   phy_type_high & ICE_MEDIA_C2C_PHY_TYPE_HIGH_M)))
4899c30461dSEric Joyner 		*media_type = ICE_MEDIA_DA;
4909c30461dSEric Joyner 	/* else if PHY types are only C2M or only C2C, then media is AUI */
4919c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
4929c30461dSEric Joyner 				       ICE_MEDIA_C2M_PHY_TYPE_LOW_M,
4939c30461dSEric Joyner 				       ICE_MEDIA_C2M_PHY_TYPE_HIGH_M) ||
4949c30461dSEric Joyner 		 ice_phy_maps_to_media(phy_type_low, phy_type_high,
4959c30461dSEric Joyner 				       ICE_MEDIA_C2C_PHY_TYPE_LOW_M,
4969c30461dSEric Joyner 				       ICE_MEDIA_C2C_PHY_TYPE_HIGH_M))
4979c30461dSEric Joyner 		*media_type = ICE_MEDIA_AUI;
4989c30461dSEric Joyner 
4999c30461dSEric Joyner 	else
5009c30461dSEric Joyner 		*media_type = ICE_MEDIA_UNKNOWN;
5019c30461dSEric Joyner }
5029c30461dSEric Joyner 
5039c30461dSEric Joyner /**
50471d10453SEric Joyner  * ice_aq_get_phy_caps - returns PHY capabilities
50571d10453SEric Joyner  * @pi: port information structure
50671d10453SEric Joyner  * @qual_mods: report qualified modules
50771d10453SEric Joyner  * @report_mode: report mode capabilities
50871d10453SEric Joyner  * @pcaps: structure for PHY capabilities to be filled
50971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
51071d10453SEric Joyner  *
51171d10453SEric Joyner  * Returns the various PHY capabilities supported on the Port (0x0600)
51271d10453SEric Joyner  */
513*f2635e84SEric Joyner int
51471d10453SEric Joyner ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
51571d10453SEric Joyner 		    struct ice_aqc_get_phy_caps_data *pcaps,
51671d10453SEric Joyner 		    struct ice_sq_cd *cd)
51771d10453SEric Joyner {
51871d10453SEric Joyner 	struct ice_aqc_get_phy_caps *cmd;
51971d10453SEric Joyner 	u16 pcaps_size = sizeof(*pcaps);
52071d10453SEric Joyner 	struct ice_aq_desc desc;
52156429daeSEric Joyner 	const char *prefix;
5227d7af7f8SEric Joyner 	struct ice_hw *hw;
523*f2635e84SEric Joyner 	int status;
52471d10453SEric Joyner 
52571d10453SEric Joyner 	cmd = &desc.params.get_phy;
52671d10453SEric Joyner 
52771d10453SEric Joyner 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
52871d10453SEric Joyner 		return ICE_ERR_PARAM;
5297d7af7f8SEric Joyner 	hw = pi->hw;
53071d10453SEric Joyner 
5319cf1841cSEric Joyner 	if (report_mode == ICE_AQC_REPORT_DFLT_CFG &&
5329cf1841cSEric Joyner 	    !ice_fw_supports_report_dflt_cfg(hw))
5339cf1841cSEric Joyner 		return ICE_ERR_PARAM;
5349cf1841cSEric Joyner 
53571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
53671d10453SEric Joyner 
53771d10453SEric Joyner 	if (qual_mods)
53871d10453SEric Joyner 		cmd->param0 |= CPU_TO_LE16(ICE_AQC_GET_PHY_RQM);
53971d10453SEric Joyner 
54071d10453SEric Joyner 	cmd->param0 |= CPU_TO_LE16(report_mode);
5418923de59SPiotr Kubaj 
5427d7af7f8SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
5437d7af7f8SEric Joyner 
54456429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
54556429daeSEric Joyner 
5468923de59SPiotr Kubaj 	switch (report_mode) {
5478923de59SPiotr Kubaj 	case ICE_AQC_REPORT_TOPO_CAP_MEDIA:
54856429daeSEric Joyner 		prefix = "phy_caps_media";
5498923de59SPiotr Kubaj 		break;
5508923de59SPiotr Kubaj 	case ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA:
55156429daeSEric Joyner 		prefix = "phy_caps_no_media";
5528923de59SPiotr Kubaj 		break;
5538923de59SPiotr Kubaj 	case ICE_AQC_REPORT_ACTIVE_CFG:
55456429daeSEric Joyner 		prefix = "phy_caps_active";
5558923de59SPiotr Kubaj 		break;
5568923de59SPiotr Kubaj 	case ICE_AQC_REPORT_DFLT_CFG:
55756429daeSEric Joyner 		prefix = "phy_caps_default";
5588923de59SPiotr Kubaj 		break;
5598923de59SPiotr Kubaj 	default:
56056429daeSEric Joyner 		prefix = "phy_caps_invalid";
5618923de59SPiotr Kubaj 	}
56256429daeSEric Joyner 
5638923de59SPiotr Kubaj 	ice_dump_phy_type(hw, LE64_TO_CPU(pcaps->phy_type_low),
5648923de59SPiotr Kubaj 			  LE64_TO_CPU(pcaps->phy_type_high), prefix);
56556429daeSEric Joyner 
56656429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
56756429daeSEric Joyner 		  prefix, report_mode);
56856429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
56956429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
5707d7af7f8SEric Joyner 		  pcaps->low_power_ctrl_an);
57156429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
57256429daeSEric Joyner 		  pcaps->eee_cap);
57356429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
5747d7af7f8SEric Joyner 		  pcaps->eeer_value);
57556429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
5767d7af7f8SEric Joyner 		  pcaps->link_fec_options);
57756429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
57856429daeSEric Joyner 		  prefix, pcaps->module_compliance_enforcement);
57956429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
58056429daeSEric Joyner 		  prefix, pcaps->extended_compliance_code);
58156429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
5827d7af7f8SEric Joyner 		  pcaps->module_type[0]);
58356429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
5847d7af7f8SEric Joyner 		  pcaps->module_type[1]);
58556429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
5867d7af7f8SEric Joyner 		  pcaps->module_type[2]);
58771d10453SEric Joyner 
588*f2635e84SEric Joyner 	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
58971d10453SEric Joyner 		pi->phy.phy_type_low = LE64_TO_CPU(pcaps->phy_type_low);
59071d10453SEric Joyner 		pi->phy.phy_type_high = LE64_TO_CPU(pcaps->phy_type_high);
5917d7af7f8SEric Joyner 		ice_memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
5927d7af7f8SEric Joyner 			   sizeof(pi->phy.link_info.module_type),
5937d7af7f8SEric Joyner 			   ICE_NONDMA_TO_NONDMA);
5949c30461dSEric Joyner 		ice_set_media_type(pi);
5959c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_LINK, "%s: media_type = 0x%x\n", prefix,
5969c30461dSEric Joyner 			  pi->phy.media_type);
59771d10453SEric Joyner 	}
59871d10453SEric Joyner 
59971d10453SEric Joyner 	return status;
60071d10453SEric Joyner }
60171d10453SEric Joyner 
60271d10453SEric Joyner /**
603*f2635e84SEric Joyner  * ice_aq_get_phy_equalization - function to read serdes equalizer value from
604*f2635e84SEric Joyner  *                               firmware using admin queue command.
605*f2635e84SEric Joyner  * @hw: pointer to the HW struct
606*f2635e84SEric Joyner  * @data_in: represents the serdes equalization parameter requested
607*f2635e84SEric Joyner  * @op_code: represents the serdes number and flag to represent tx or rx
608*f2635e84SEric Joyner  * @serdes_num: represents the serdes number
609*f2635e84SEric Joyner  * @output: pointer to the caller-supplied buffer to return serdes equalizer
61056429daeSEric Joyner  *
611*f2635e84SEric Joyner  * Returns 0 on success,
612*f2635e84SEric Joyner  *	   non-zero status on error
61356429daeSEric Joyner  */
614*f2635e84SEric Joyner int ice_aq_get_phy_equalization(struct ice_hw *hw, u16 data_in, u16 op_code,
615*f2635e84SEric Joyner 			    u8 serdes_num, int *output)
61656429daeSEric Joyner {
617*f2635e84SEric Joyner 	struct ice_aqc_dnl_call_command *cmd;
618*f2635e84SEric Joyner 	struct ice_aqc_dnl_call buf;
619*f2635e84SEric Joyner 	struct ice_aq_desc desc;
620*f2635e84SEric Joyner 	int err = 0;
62156429daeSEric Joyner 
622*f2635e84SEric Joyner 	if (!hw || !output)
623*f2635e84SEric Joyner 		return (ICE_ERR_PARAM);
6248923de59SPiotr Kubaj 
625*f2635e84SEric Joyner 	memset(&buf, 0, sizeof(buf));
626*f2635e84SEric Joyner 	buf.sto.txrx_equa_reqs.data_in = CPU_TO_LE16(data_in);
627*f2635e84SEric Joyner 	buf.sto.txrx_equa_reqs.op_code_serdes_sel =
628*f2635e84SEric Joyner 		CPU_TO_LE16(op_code | (serdes_num & 0xF));
62956429daeSEric Joyner 
630*f2635e84SEric Joyner 	cmd = &desc.params.dnl_call;
631*f2635e84SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dnl_call);
632*f2635e84SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_BUF | ICE_AQ_FLAG_RD |
633*f2635e84SEric Joyner 				  ICE_AQ_FLAG_SI);
634*f2635e84SEric Joyner 	desc.datalen = CPU_TO_LE16(sizeof(struct ice_aqc_dnl_call));
635*f2635e84SEric Joyner 	cmd->activity_id = CPU_TO_LE16(ICE_AQC_ACT_ID_DNL);
636*f2635e84SEric Joyner 	cmd->ctx = 0;
63756429daeSEric Joyner 
638*f2635e84SEric Joyner 	err = ice_aq_send_cmd(hw, &desc, &buf,
639*f2635e84SEric Joyner 			      sizeof(struct ice_aqc_dnl_call), NULL);
640*f2635e84SEric Joyner 	if (!err)
641*f2635e84SEric Joyner 		*output = buf.sto.txrx_equa_resp.val;
64256429daeSEric Joyner 
643*f2635e84SEric Joyner 	return err;
64456429daeSEric Joyner }
64556429daeSEric Joyner 
646*f2635e84SEric Joyner #define ice_get_link_status_data_ver(hw) ((hw)->mac_type == ICE_MAC_E830 ? \
647*f2635e84SEric Joyner 		ICE_GET_LINK_STATUS_DATA_V2 : ICE_GET_LINK_STATUS_DATA_V1)
64871d10453SEric Joyner 
649*f2635e84SEric Joyner /**
650*f2635e84SEric Joyner  * ice_get_link_status_datalen
651*f2635e84SEric Joyner  * @hw: pointer to the HW struct
652*f2635e84SEric Joyner  *
653*f2635e84SEric Joyner  * return Get Link Status datalen
654*f2635e84SEric Joyner  */
655*f2635e84SEric Joyner static u16 ice_get_link_status_datalen(struct ice_hw *hw)
656*f2635e84SEric Joyner {
657*f2635e84SEric Joyner 	return (ice_get_link_status_data_ver(hw) ==
658*f2635e84SEric Joyner 		ICE_GET_LINK_STATUS_DATA_V1) ? ICE_GET_LINK_STATUS_DATALEN_V1 :
659*f2635e84SEric Joyner 		ICE_GET_LINK_STATUS_DATALEN_V2;
660*f2635e84SEric Joyner }
6618923de59SPiotr Kubaj 
66271d10453SEric Joyner /**
66371d10453SEric Joyner  * ice_aq_get_link_info
66471d10453SEric Joyner  * @pi: port information structure
66571d10453SEric Joyner  * @ena_lse: enable/disable LinkStatusEvent reporting
66671d10453SEric Joyner  * @link: pointer to link status structure - optional
66771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
66871d10453SEric Joyner  *
66971d10453SEric Joyner  * Get Link Status (0x607). Returns the link status of the adapter.
67071d10453SEric Joyner  */
671*f2635e84SEric Joyner int
67271d10453SEric Joyner ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
67371d10453SEric Joyner 		     struct ice_link_status *link, struct ice_sq_cd *cd)
67471d10453SEric Joyner {
67571d10453SEric Joyner 	struct ice_aqc_get_link_status_data link_data = { 0 };
67671d10453SEric Joyner 	struct ice_aqc_get_link_status *resp;
67771d10453SEric Joyner 	struct ice_link_status *li_old, *li;
67871d10453SEric Joyner 	struct ice_fc_info *hw_fc_info;
67971d10453SEric Joyner 	bool tx_pause, rx_pause;
68071d10453SEric Joyner 	struct ice_aq_desc desc;
68171d10453SEric Joyner 	struct ice_hw *hw;
68271d10453SEric Joyner 	u16 cmd_flags;
683*f2635e84SEric Joyner 	int status;
68471d10453SEric Joyner 
68571d10453SEric Joyner 	if (!pi)
68671d10453SEric Joyner 		return ICE_ERR_PARAM;
68771d10453SEric Joyner 	hw = pi->hw;
68871d10453SEric Joyner 
68971d10453SEric Joyner 	li_old = &pi->phy.link_info_old;
69071d10453SEric Joyner 	li = &pi->phy.link_info;
69171d10453SEric Joyner 	hw_fc_info = &pi->fc;
69271d10453SEric Joyner 
69371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
69471d10453SEric Joyner 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
69571d10453SEric Joyner 	resp = &desc.params.get_link_status;
69671d10453SEric Joyner 	resp->cmd_flags = CPU_TO_LE16(cmd_flags);
69771d10453SEric Joyner 	resp->lport_num = pi->lport;
69871d10453SEric Joyner 
6998923de59SPiotr Kubaj 	status = ice_aq_send_cmd(hw, &desc, &link_data,
7008923de59SPiotr Kubaj 				 ice_get_link_status_datalen(hw), cd);
701*f2635e84SEric Joyner 	if (status)
70271d10453SEric Joyner 		return status;
70371d10453SEric Joyner 
70471d10453SEric Joyner 	/* save off old link status information */
70571d10453SEric Joyner 	*li_old = *li;
70671d10453SEric Joyner 
70771d10453SEric Joyner 	/* update current link status information */
70871d10453SEric Joyner 	li->link_speed = LE16_TO_CPU(link_data.link_speed);
70971d10453SEric Joyner 	li->phy_type_low = LE64_TO_CPU(link_data.phy_type_low);
71071d10453SEric Joyner 	li->phy_type_high = LE64_TO_CPU(link_data.phy_type_high);
71171d10453SEric Joyner 	li->link_info = link_data.link_info;
7129cf1841cSEric Joyner 	li->link_cfg_err = link_data.link_cfg_err;
71371d10453SEric Joyner 	li->an_info = link_data.an_info;
71471d10453SEric Joyner 	li->ext_info = link_data.ext_info;
71571d10453SEric Joyner 	li->max_frame_size = LE16_TO_CPU(link_data.max_frame_size);
71671d10453SEric Joyner 	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
71771d10453SEric Joyner 	li->topo_media_conflict = link_data.topo_media_conflict;
71871d10453SEric Joyner 	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
71971d10453SEric Joyner 				      ICE_AQ_CFG_PACING_TYPE_M);
72071d10453SEric Joyner 
72171d10453SEric Joyner 	/* update fc info */
72271d10453SEric Joyner 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
72371d10453SEric Joyner 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
72471d10453SEric Joyner 	if (tx_pause && rx_pause)
72571d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_FULL;
72671d10453SEric Joyner 	else if (tx_pause)
72771d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
72871d10453SEric Joyner 	else if (rx_pause)
72971d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
73071d10453SEric Joyner 	else
73171d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_NONE;
73271d10453SEric Joyner 
73371d10453SEric Joyner 	li->lse_ena = !!(resp->cmd_flags & CPU_TO_LE16(ICE_AQ_LSE_IS_ENABLED));
73471d10453SEric Joyner 
7357d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get link info\n");
73671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_speed = 0x%x\n", li->link_speed);
73771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
73871d10453SEric Joyner 		  (unsigned long long)li->phy_type_low);
73971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
74071d10453SEric Joyner 		  (unsigned long long)li->phy_type_high);
74171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_info = 0x%x\n", li->link_info);
74256429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_cfg_err = 0x%x\n", li->link_cfg_err);
74371d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	an_info = 0x%x\n", li->an_info);
74471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	ext_info = 0x%x\n", li->ext_info);
7457d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	fec_info = 0x%x\n", li->fec_info);
74671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	lse_ena = 0x%x\n", li->lse_ena);
7477d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	max_frame = 0x%x\n",
7487d7af7f8SEric Joyner 		  li->max_frame_size);
74971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	pacing = 0x%x\n", li->pacing);
75071d10453SEric Joyner 
75171d10453SEric Joyner 	/* save link status information */
75271d10453SEric Joyner 	if (link)
75371d10453SEric Joyner 		*link = *li;
75471d10453SEric Joyner 
75571d10453SEric Joyner 	/* flag cleared so calling functions don't call AQ again */
75671d10453SEric Joyner 	pi->phy.get_link_info = false;
75771d10453SEric Joyner 
758*f2635e84SEric Joyner 	return 0;
75971d10453SEric Joyner }
76071d10453SEric Joyner 
76171d10453SEric Joyner /**
7627d7af7f8SEric Joyner  * ice_fill_tx_timer_and_fc_thresh
76371d10453SEric Joyner  * @hw: pointer to the HW struct
7647d7af7f8SEric Joyner  * @cmd: pointer to MAC cfg structure
76571d10453SEric Joyner  *
7667d7af7f8SEric Joyner  * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
7677d7af7f8SEric Joyner  * descriptor
76871d10453SEric Joyner  */
7697d7af7f8SEric Joyner static void
7707d7af7f8SEric Joyner ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
7717d7af7f8SEric Joyner 				struct ice_aqc_set_mac_cfg *cmd)
77271d10453SEric Joyner {
7737d7af7f8SEric Joyner 	u16 fc_thres_val, tx_timer_val;
7747d7af7f8SEric Joyner 	u32 val;
77571d10453SEric Joyner 
77671d10453SEric Joyner 	/* We read back the transmit timer and fc threshold value of
77771d10453SEric Joyner 	 * LFC. Thus, we will use index =
77871d10453SEric Joyner 	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
77971d10453SEric Joyner 	 *
78056429daeSEric Joyner 	 * Also, because we are operating on transmit timer and fc
78171d10453SEric Joyner 	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
78271d10453SEric Joyner 	 */
783*f2635e84SEric Joyner #define E800_IDX_OF_LFC E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
78471d10453SEric Joyner 
785*f2635e84SEric Joyner 	if ((hw)->mac_type == ICE_MAC_E830) {
78671d10453SEric Joyner 		/* Retrieve the transmit timer */
787*f2635e84SEric Joyner 		val = rd32(hw, E830_PRTMAC_CL01_PAUSE_QUANTA);
788*f2635e84SEric Joyner 		tx_timer_val = val & E830_PRTMAC_CL01_PAUSE_QUANTA_CL0_PAUSE_QUANTA_M;
78971d10453SEric Joyner 		cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
79071d10453SEric Joyner 
79171d10453SEric Joyner 		/* Retrieve the fc threshold */
792*f2635e84SEric Joyner 		val = rd32(hw, E830_PRTMAC_CL01_QUANTA_THRESH);
793*f2635e84SEric Joyner 		fc_thres_val = val & E830_PRTMAC_CL01_QUANTA_THRESH_CL0_QUANTA_THRESH_M;
794*f2635e84SEric Joyner 	} else {
795*f2635e84SEric Joyner 		/* Retrieve the transmit timer */
796*f2635e84SEric Joyner 		val = rd32(hw, E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(E800_IDX_OF_LFC));
797*f2635e84SEric Joyner 		tx_timer_val = val &
798*f2635e84SEric Joyner 			E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
799*f2635e84SEric Joyner 		cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
800*f2635e84SEric Joyner 
801*f2635e84SEric Joyner 		/* Retrieve the fc threshold */
802*f2635e84SEric Joyner 		val = rd32(hw, E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(E800_IDX_OF_LFC));
803*f2635e84SEric Joyner 		fc_thres_val = val & E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
804*f2635e84SEric Joyner 	}
8057d7af7f8SEric Joyner 
8067d7af7f8SEric Joyner 	cmd->fc_refresh_threshold = CPU_TO_LE16(fc_thres_val);
8077d7af7f8SEric Joyner }
8087d7af7f8SEric Joyner 
8097d7af7f8SEric Joyner /**
8107d7af7f8SEric Joyner  * ice_aq_set_mac_cfg
8117d7af7f8SEric Joyner  * @hw: pointer to the HW struct
8127d7af7f8SEric Joyner  * @max_frame_size: Maximum Frame Size to be supported
81356429daeSEric Joyner  * @auto_drop: Tell HW to drop packets if TC queue is blocked
8147d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
8157d7af7f8SEric Joyner  *
8167d7af7f8SEric Joyner  * Set MAC configuration (0x0603)
8177d7af7f8SEric Joyner  */
818*f2635e84SEric Joyner int
81956429daeSEric Joyner ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,
82056429daeSEric Joyner 		   struct ice_sq_cd *cd)
8217d7af7f8SEric Joyner {
8227d7af7f8SEric Joyner 	struct ice_aqc_set_mac_cfg *cmd;
8237d7af7f8SEric Joyner 	struct ice_aq_desc desc;
8247d7af7f8SEric Joyner 
8257d7af7f8SEric Joyner 	cmd = &desc.params.set_mac_cfg;
8267d7af7f8SEric Joyner 
8277d7af7f8SEric Joyner 	if (max_frame_size == 0)
8287d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
8297d7af7f8SEric Joyner 
8307d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
8317d7af7f8SEric Joyner 
8327d7af7f8SEric Joyner 	cmd->max_frame_size = CPU_TO_LE16(max_frame_size);
8337d7af7f8SEric Joyner 
83456429daeSEric Joyner 	if (ice_is_fw_auto_drop_supported(hw) && auto_drop)
83556429daeSEric Joyner 		cmd->drop_opts |= ICE_AQ_SET_MAC_AUTO_DROP_BLOCKING_PKTS;
8367d7af7f8SEric Joyner 	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
83771d10453SEric Joyner 
83871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
83971d10453SEric Joyner }
84071d10453SEric Joyner 
84171d10453SEric Joyner /**
84271d10453SEric Joyner  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
84371d10453SEric Joyner  * @hw: pointer to the HW struct
84471d10453SEric Joyner  */
845*f2635e84SEric Joyner int ice_init_fltr_mgmt_struct(struct ice_hw *hw)
84671d10453SEric Joyner {
84771d10453SEric Joyner 	struct ice_switch_info *sw;
848*f2635e84SEric Joyner 	int status;
84971d10453SEric Joyner 
85071d10453SEric Joyner 	hw->switch_info = (struct ice_switch_info *)
85171d10453SEric Joyner 			  ice_malloc(hw, sizeof(*hw->switch_info));
85271d10453SEric Joyner 
85371d10453SEric Joyner 	sw = hw->switch_info;
85471d10453SEric Joyner 
85571d10453SEric Joyner 	if (!sw)
85671d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
85771d10453SEric Joyner 
85871d10453SEric Joyner 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
8597d7af7f8SEric Joyner 	sw->prof_res_bm_init = 0;
86071d10453SEric Joyner 
8617d7af7f8SEric Joyner 	status = ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
8627d7af7f8SEric Joyner 	if (status) {
8637d7af7f8SEric Joyner 		ice_free(hw, hw->switch_info);
8647d7af7f8SEric Joyner 		return status;
8657d7af7f8SEric Joyner 	}
866*f2635e84SEric Joyner 	return 0;
86771d10453SEric Joyner }
86871d10453SEric Joyner 
86971d10453SEric Joyner /**
8707d7af7f8SEric Joyner  * ice_cleanup_fltr_mgmt_single - clears single filter mngt struct
87171d10453SEric Joyner  * @hw: pointer to the HW struct
8727d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function clears filters
87371d10453SEric Joyner  */
8747d7af7f8SEric Joyner static void
8757d7af7f8SEric Joyner ice_cleanup_fltr_mgmt_single(struct ice_hw *hw, struct ice_switch_info *sw)
87671d10453SEric Joyner {
87771d10453SEric Joyner 	struct ice_vsi_list_map_info *v_pos_map;
87871d10453SEric Joyner 	struct ice_vsi_list_map_info *v_tmp_map;
87971d10453SEric Joyner 	struct ice_sw_recipe *recps;
88071d10453SEric Joyner 	u8 i;
88171d10453SEric Joyner 
8827d7af7f8SEric Joyner 	if (!sw)
8837d7af7f8SEric Joyner 		return;
8847d7af7f8SEric Joyner 
88571d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
88671d10453SEric Joyner 				 ice_vsi_list_map_info, list_entry) {
88771d10453SEric Joyner 		LIST_DEL(&v_pos_map->list_entry);
88871d10453SEric Joyner 		ice_free(hw, v_pos_map);
88971d10453SEric Joyner 	}
8907d7af7f8SEric Joyner 	recps = sw->recp_list;
89171d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
89271d10453SEric Joyner 		struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
89371d10453SEric Joyner 
89471d10453SEric Joyner 		recps[i].root_rid = i;
89571d10453SEric Joyner 		LIST_FOR_EACH_ENTRY_SAFE(rg_entry, tmprg_entry,
89671d10453SEric Joyner 					 &recps[i].rg_list, ice_recp_grp_entry,
89771d10453SEric Joyner 					 l_entry) {
89871d10453SEric Joyner 			LIST_DEL(&rg_entry->l_entry);
89971d10453SEric Joyner 			ice_free(hw, rg_entry);
90071d10453SEric Joyner 		}
90171d10453SEric Joyner 
90271d10453SEric Joyner 		if (recps[i].adv_rule) {
90371d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
90471d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *lst_itr;
90571d10453SEric Joyner 
90671d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
90771d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
90871d10453SEric Joyner 						 &recps[i].filt_rules,
90971d10453SEric Joyner 						 ice_adv_fltr_mgmt_list_entry,
91071d10453SEric Joyner 						 list_entry) {
91171d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
91271d10453SEric Joyner 				ice_free(hw, lst_itr->lkups);
91371d10453SEric Joyner 				ice_free(hw, lst_itr);
91471d10453SEric Joyner 			}
91571d10453SEric Joyner 		} else {
91671d10453SEric Joyner 			struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
91771d10453SEric Joyner 
91871d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
91971d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
92071d10453SEric Joyner 						 &recps[i].filt_rules,
92171d10453SEric Joyner 						 ice_fltr_mgmt_list_entry,
92271d10453SEric Joyner 						 list_entry) {
92371d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
92471d10453SEric Joyner 				ice_free(hw, lst_itr);
92571d10453SEric Joyner 			}
92671d10453SEric Joyner 		}
92771d10453SEric Joyner 		if (recps[i].root_buf)
92871d10453SEric Joyner 			ice_free(hw, recps[i].root_buf);
92971d10453SEric Joyner 	}
9307d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
93171d10453SEric Joyner 	ice_free(hw, sw->recp_list);
93271d10453SEric Joyner 	ice_free(hw, sw);
93371d10453SEric Joyner }
93471d10453SEric Joyner 
93571d10453SEric Joyner /**
93656429daeSEric Joyner  * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
9377d7af7f8SEric Joyner  * @hw: pointer to the HW struct
9387d7af7f8SEric Joyner  */
939*f2635e84SEric Joyner void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
9407d7af7f8SEric Joyner {
9417d7af7f8SEric Joyner 	ice_cleanup_fltr_mgmt_single(hw, hw->switch_info);
9427d7af7f8SEric Joyner }
9437d7af7f8SEric Joyner 
9447d7af7f8SEric Joyner /**
94571d10453SEric Joyner  * ice_get_itr_intrl_gran
94671d10453SEric Joyner  * @hw: pointer to the HW struct
94771d10453SEric Joyner  *
94871d10453SEric Joyner  * Determines the ITR/INTRL granularities based on the maximum aggregate
94971d10453SEric Joyner  * bandwidth according to the device's configuration during power-on.
95071d10453SEric Joyner  */
95171d10453SEric Joyner static void ice_get_itr_intrl_gran(struct ice_hw *hw)
95271d10453SEric Joyner {
95371d10453SEric Joyner 	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
95471d10453SEric Joyner 			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
95571d10453SEric Joyner 			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
95671d10453SEric Joyner 
95771d10453SEric Joyner 	switch (max_agg_bw) {
95871d10453SEric Joyner 	case ICE_MAX_AGG_BW_200G:
95971d10453SEric Joyner 	case ICE_MAX_AGG_BW_100G:
96071d10453SEric Joyner 	case ICE_MAX_AGG_BW_50G:
96171d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
96271d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
96371d10453SEric Joyner 		break;
96471d10453SEric Joyner 	case ICE_MAX_AGG_BW_25G:
96571d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
96671d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
96771d10453SEric Joyner 		break;
96871d10453SEric Joyner 	}
96971d10453SEric Joyner }
97071d10453SEric Joyner 
97171d10453SEric Joyner /**
97271d10453SEric Joyner  * ice_print_rollback_msg - print FW rollback message
97371d10453SEric Joyner  * @hw: pointer to the hardware structure
97471d10453SEric Joyner  */
97571d10453SEric Joyner void ice_print_rollback_msg(struct ice_hw *hw)
97671d10453SEric Joyner {
97771d10453SEric Joyner 	char nvm_str[ICE_NVM_VER_LEN] = { 0 };
97871d10453SEric Joyner 	struct ice_orom_info *orom;
979d08b8680SEric Joyner 	struct ice_nvm_info *nvm;
98071d10453SEric Joyner 
981d08b8680SEric Joyner 	orom = &hw->flash.orom;
982d08b8680SEric Joyner 	nvm = &hw->flash.nvm;
98371d10453SEric Joyner 
984*f2635e84SEric Joyner 	(void)SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d",
985d08b8680SEric Joyner 		 nvm->major, nvm->minor, nvm->eetrack, orom->major,
98671d10453SEric Joyner 		 orom->build, orom->patch);
98771d10453SEric Joyner 	ice_warn(hw,
98871d10453SEric 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",
98971d10453SEric Joyner 		 nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
99071d10453SEric Joyner }
99171d10453SEric Joyner 
99271d10453SEric Joyner /**
99356429daeSEric Joyner  * ice_set_umac_shared
99456429daeSEric Joyner  * @hw: pointer to the hw struct
99556429daeSEric Joyner  *
99656429daeSEric Joyner  * Set boolean flag to allow unicast MAC sharing
99756429daeSEric Joyner  */
99856429daeSEric Joyner void ice_set_umac_shared(struct ice_hw *hw)
99956429daeSEric Joyner {
100056429daeSEric Joyner 	hw->umac_shared = true;
100156429daeSEric Joyner }
100256429daeSEric Joyner 
100356429daeSEric Joyner /**
100471d10453SEric Joyner  * ice_init_hw - main hardware initialization routine
100571d10453SEric Joyner  * @hw: pointer to the hardware structure
100671d10453SEric Joyner  */
1007*f2635e84SEric Joyner int ice_init_hw(struct ice_hw *hw)
100871d10453SEric Joyner {
100971d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
101071d10453SEric Joyner 	u16 mac_buf_len;
101171d10453SEric Joyner 	void *mac_buf;
1012*f2635e84SEric Joyner 	int status;
101371d10453SEric Joyner 
101471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
101571d10453SEric Joyner 
101671d10453SEric Joyner 	/* Set MAC type based on DeviceID */
101771d10453SEric Joyner 	status = ice_set_mac_type(hw);
101871d10453SEric Joyner 	if (status)
101971d10453SEric Joyner 		return status;
102071d10453SEric Joyner 
102171d10453SEric Joyner 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
102271d10453SEric Joyner 			 PF_FUNC_RID_FUNCTION_NUMBER_M) >>
102371d10453SEric Joyner 		PF_FUNC_RID_FUNCTION_NUMBER_S;
102471d10453SEric Joyner 
102571d10453SEric Joyner 	status = ice_reset(hw, ICE_RESET_PFR);
102671d10453SEric Joyner 	if (status)
102771d10453SEric Joyner 		return status;
102871d10453SEric Joyner 	ice_get_itr_intrl_gran(hw);
102971d10453SEric Joyner 
1030*f2635e84SEric Joyner 	hw->fw_vsi_num = ICE_DFLT_VSI_INVAL;
1031*f2635e84SEric Joyner 
103271d10453SEric Joyner 	status = ice_create_all_ctrlq(hw);
103371d10453SEric Joyner 	if (status)
103471d10453SEric Joyner 		goto err_unroll_cqinit;
103571d10453SEric Joyner 
103656429daeSEric Joyner 	ice_fwlog_set_support_ena(hw);
103756429daeSEric Joyner 	status = ice_fwlog_set(hw, &hw->fwlog_cfg);
103856429daeSEric Joyner 	if (status) {
103956429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging, status %d.\n",
104056429daeSEric Joyner 			  status);
104156429daeSEric Joyner 	} else {
104256429daeSEric Joyner 		if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_REGISTER_ON_INIT) {
104356429daeSEric Joyner 			status = ice_fwlog_register(hw);
104456429daeSEric Joyner 			if (status)
104556429daeSEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "Failed to register for FW logging events, status %d.\n",
104656429daeSEric Joyner 					  status);
104756429daeSEric Joyner 		} else {
104856429daeSEric Joyner 			status = ice_fwlog_unregister(hw);
104956429daeSEric Joyner 			if (status)
105056429daeSEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "Failed to unregister for FW logging events, status %d.\n",
105156429daeSEric Joyner 					  status);
105256429daeSEric Joyner 		}
105356429daeSEric Joyner 	}
105456429daeSEric Joyner 
105571d10453SEric Joyner 	status = ice_init_nvm(hw);
105671d10453SEric Joyner 	if (status)
105771d10453SEric Joyner 		goto err_unroll_cqinit;
105871d10453SEric Joyner 
105971d10453SEric Joyner 	if (ice_get_fw_mode(hw) == ICE_FW_MODE_ROLLBACK)
106071d10453SEric Joyner 		ice_print_rollback_msg(hw);
106171d10453SEric Joyner 
1062*f2635e84SEric Joyner 	if (!hw->skip_clear_pf) {
106371d10453SEric Joyner 		status = ice_clear_pf_cfg(hw);
106471d10453SEric Joyner 		if (status)
106571d10453SEric Joyner 			goto err_unroll_cqinit;
1066*f2635e84SEric Joyner 	}
106771d10453SEric Joyner 
106871d10453SEric Joyner 	ice_clear_pxe_mode(hw);
106971d10453SEric Joyner 
107071d10453SEric Joyner 	status = ice_get_caps(hw);
107171d10453SEric Joyner 	if (status)
107271d10453SEric Joyner 		goto err_unroll_cqinit;
107371d10453SEric Joyner 
10749c30461dSEric Joyner 	if (!hw->port_info)
107571d10453SEric Joyner 		hw->port_info = (struct ice_port_info *)
107671d10453SEric Joyner 			ice_malloc(hw, sizeof(*hw->port_info));
107771d10453SEric Joyner 	if (!hw->port_info) {
107871d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
107971d10453SEric Joyner 		goto err_unroll_cqinit;
108071d10453SEric Joyner 	}
108171d10453SEric Joyner 
1082*f2635e84SEric Joyner 	hw->port_info->loopback_mode = ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NORMAL;
1083*f2635e84SEric Joyner 
108471d10453SEric Joyner 	/* set the back pointer to HW */
108571d10453SEric Joyner 	hw->port_info->hw = hw;
108671d10453SEric Joyner 
108771d10453SEric Joyner 	/* Initialize port_info struct with switch configuration data */
108871d10453SEric Joyner 	status = ice_get_initial_sw_cfg(hw);
108971d10453SEric Joyner 	if (status)
109071d10453SEric Joyner 		goto err_unroll_alloc;
109171d10453SEric Joyner 
109271d10453SEric Joyner 	hw->evb_veb = true;
109371d10453SEric Joyner 	/* Query the allocated resources for Tx scheduler */
109471d10453SEric Joyner 	status = ice_sched_query_res_alloc(hw);
109571d10453SEric Joyner 	if (status) {
10967d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
109771d10453SEric Joyner 		goto err_unroll_alloc;
109871d10453SEric Joyner 	}
109971d10453SEric Joyner 	ice_sched_get_psm_clk_freq(hw);
110071d10453SEric Joyner 
110171d10453SEric Joyner 	/* Initialize port_info struct with scheduler data */
110271d10453SEric Joyner 	status = ice_sched_init_port(hw->port_info);
110371d10453SEric Joyner 	if (status)
110471d10453SEric Joyner 		goto err_unroll_sched;
110571d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
110671d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
110771d10453SEric Joyner 	if (!pcaps) {
110871d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
110971d10453SEric Joyner 		goto err_unroll_sched;
111071d10453SEric Joyner 	}
111171d10453SEric Joyner 
111271d10453SEric Joyner 	/* Initialize port_info struct with PHY capabilities */
111371d10453SEric Joyner 	status = ice_aq_get_phy_caps(hw->port_info, false,
11149cf1841cSEric Joyner 				     ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, NULL);
111571d10453SEric Joyner 	ice_free(hw, pcaps);
111671d10453SEric Joyner 	if (status)
11179cf1841cSEric Joyner 		ice_warn(hw, "Get PHY capabilities failed status = %d, continuing anyway\n",
11189cf1841cSEric Joyner 			 status);
111971d10453SEric Joyner 
112071d10453SEric Joyner 	/* Initialize port_info struct with link information */
112171d10453SEric Joyner 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
112271d10453SEric Joyner 	if (status)
112371d10453SEric Joyner 		goto err_unroll_sched;
112471d10453SEric Joyner 	/* need a valid SW entry point to build a Tx tree */
112571d10453SEric Joyner 	if (!hw->sw_entry_point_layer) {
112671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
112771d10453SEric Joyner 		status = ICE_ERR_CFG;
112871d10453SEric Joyner 		goto err_unroll_sched;
112971d10453SEric Joyner 	}
113071d10453SEric Joyner 	INIT_LIST_HEAD(&hw->agg_list);
113171d10453SEric Joyner 	/* Initialize max burst size */
113271d10453SEric Joyner 	if (!hw->max_burst_size)
113371d10453SEric Joyner 		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
113471d10453SEric Joyner 	status = ice_init_fltr_mgmt_struct(hw);
113571d10453SEric Joyner 	if (status)
113671d10453SEric Joyner 		goto err_unroll_sched;
113771d10453SEric Joyner 
113871d10453SEric Joyner 	/* Get MAC information */
113956429daeSEric Joyner 
114071d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
114171d10453SEric Joyner 	mac_buf = ice_calloc(hw, 2,
114271d10453SEric Joyner 			     sizeof(struct ice_aqc_manage_mac_read_resp));
114371d10453SEric Joyner 	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
114471d10453SEric Joyner 
114571d10453SEric Joyner 	if (!mac_buf) {
114671d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
114771d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
114871d10453SEric Joyner 	}
114971d10453SEric Joyner 
115071d10453SEric Joyner 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
115171d10453SEric Joyner 	ice_free(hw, mac_buf);
115271d10453SEric Joyner 
115371d10453SEric Joyner 	if (status)
115471d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
115556429daeSEric Joyner 
11567d7af7f8SEric Joyner 	/* enable jumbo frame support at MAC level */
115756429daeSEric Joyner 	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, false,
115856429daeSEric Joyner 				    NULL);
11597d7af7f8SEric Joyner 	if (status)
11607d7af7f8SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
116156429daeSEric Joyner 
116271d10453SEric Joyner 	status = ice_init_hw_tbls(hw);
116371d10453SEric Joyner 	if (status)
116471d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
116571d10453SEric Joyner 	ice_init_lock(&hw->tnl_lock);
1166d08b8680SEric Joyner 
1167*f2635e84SEric Joyner 	return 0;
116871d10453SEric Joyner 
116971d10453SEric Joyner err_unroll_fltr_mgmt_struct:
117071d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
117171d10453SEric Joyner err_unroll_sched:
117271d10453SEric Joyner 	ice_sched_cleanup_all(hw);
117371d10453SEric Joyner err_unroll_alloc:
117471d10453SEric Joyner 	ice_free(hw, hw->port_info);
117571d10453SEric Joyner 	hw->port_info = NULL;
117671d10453SEric Joyner err_unroll_cqinit:
117771d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
117871d10453SEric Joyner 	return status;
117971d10453SEric Joyner }
118071d10453SEric Joyner 
118171d10453SEric Joyner /**
118271d10453SEric Joyner  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
118371d10453SEric Joyner  * @hw: pointer to the hardware structure
118471d10453SEric Joyner  *
118571d10453SEric Joyner  * This should be called only during nominal operation, not as a result of
118671d10453SEric Joyner  * ice_init_hw() failing since ice_init_hw() will take care of unrolling
118771d10453SEric Joyner  * applicable initializations if it fails for any reason.
118871d10453SEric Joyner  */
118971d10453SEric Joyner void ice_deinit_hw(struct ice_hw *hw)
119071d10453SEric Joyner {
119171d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
119271d10453SEric Joyner 
119371d10453SEric Joyner 	ice_sched_cleanup_all(hw);
119471d10453SEric Joyner 	ice_sched_clear_agg(hw);
119571d10453SEric Joyner 	ice_free_seg(hw);
119671d10453SEric Joyner 	ice_free_hw_tbls(hw);
119771d10453SEric Joyner 	ice_destroy_lock(&hw->tnl_lock);
119871d10453SEric Joyner 
119971d10453SEric Joyner 	if (hw->port_info) {
120071d10453SEric Joyner 		ice_free(hw, hw->port_info);
120171d10453SEric Joyner 		hw->port_info = NULL;
120271d10453SEric Joyner 	}
120371d10453SEric Joyner 
120471d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
120571d10453SEric Joyner 
120671d10453SEric Joyner 	/* Clear VSI contexts if not already cleared */
120771d10453SEric Joyner 	ice_clear_all_vsi_ctx(hw);
120871d10453SEric Joyner }
120971d10453SEric Joyner 
121071d10453SEric Joyner /**
121171d10453SEric Joyner  * ice_check_reset - Check to see if a global reset is complete
121271d10453SEric Joyner  * @hw: pointer to the hardware structure
121371d10453SEric Joyner  */
1214*f2635e84SEric Joyner int ice_check_reset(struct ice_hw *hw)
121571d10453SEric Joyner {
12169c30461dSEric Joyner 	u32 cnt, reg = 0, grst_timeout, uld_mask, reset_wait_cnt;
121771d10453SEric Joyner 
121871d10453SEric Joyner 	/* Poll for Device Active state in case a recent CORER, GLOBR,
121971d10453SEric Joyner 	 * or EMPR has occurred. The grst delay value is in 100ms units.
122071d10453SEric Joyner 	 * Add 1sec for outstanding AQ commands that can take a long time.
122171d10453SEric Joyner 	 */
12227d7af7f8SEric Joyner 	grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
122371d10453SEric Joyner 			GLGEN_RSTCTL_GRSTDEL_S) + 10;
122471d10453SEric Joyner 
12257d7af7f8SEric Joyner 	for (cnt = 0; cnt < grst_timeout; cnt++) {
122671d10453SEric Joyner 		ice_msec_delay(100, true);
122771d10453SEric Joyner 		reg = rd32(hw, GLGEN_RSTAT);
122871d10453SEric Joyner 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
122971d10453SEric Joyner 			break;
123071d10453SEric Joyner 	}
123171d10453SEric Joyner 
12327d7af7f8SEric Joyner 	if (cnt == grst_timeout) {
12337d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n");
123471d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
123571d10453SEric Joyner 	}
123671d10453SEric Joyner 
123771d10453SEric Joyner #define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
123871d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_1_M |\
123971d10453SEric Joyner 				 GLNVM_ULD_CORER_DONE_M |\
124071d10453SEric Joyner 				 GLNVM_ULD_GLOBR_DONE_M |\
124171d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_M |\
124271d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_1_M |\
124371d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_2_M)
124471d10453SEric Joyner 
12458a13362dSEric Joyner 	uld_mask = ICE_RESET_DONE_MASK | (hw->func_caps.common_cap.iwarp ?
12468a13362dSEric Joyner 					  GLNVM_ULD_PE_DONE_M : 0);
124771d10453SEric Joyner 
12489c30461dSEric Joyner 	reset_wait_cnt = ICE_PF_RESET_WAIT_COUNT;
12499c30461dSEric Joyner 
125071d10453SEric Joyner 	/* Device is Active; check Global Reset processes are done */
12519c30461dSEric Joyner 	for (cnt = 0; cnt < reset_wait_cnt; cnt++) {
125271d10453SEric Joyner 		reg = rd32(hw, GLNVM_ULD) & uld_mask;
125371d10453SEric Joyner 		if (reg == uld_mask) {
12547d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt);
125571d10453SEric Joyner 			break;
125671d10453SEric Joyner 		}
125771d10453SEric Joyner 		ice_msec_delay(10, true);
125871d10453SEric Joyner 	}
125971d10453SEric Joyner 
12609c30461dSEric Joyner 	if (cnt == reset_wait_cnt) {
12617d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
126271d10453SEric Joyner 			  reg);
126371d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
126471d10453SEric Joyner 	}
126571d10453SEric Joyner 
1266*f2635e84SEric Joyner 	return 0;
126771d10453SEric Joyner }
126871d10453SEric Joyner 
126971d10453SEric Joyner /**
127071d10453SEric Joyner  * ice_pf_reset - Reset the PF
127171d10453SEric Joyner  * @hw: pointer to the hardware structure
127271d10453SEric Joyner  *
127371d10453SEric Joyner  * If a global reset has been triggered, this function checks
127471d10453SEric Joyner  * for its completion and then issues the PF reset
127571d10453SEric Joyner  */
1276*f2635e84SEric Joyner static int ice_pf_reset(struct ice_hw *hw)
127771d10453SEric Joyner {
12789c30461dSEric Joyner 	u32 cnt, reg, reset_wait_cnt, cfg_lock_timeout;
127971d10453SEric Joyner 
128071d10453SEric Joyner 	/* If at function entry a global reset was already in progress, i.e.
128171d10453SEric Joyner 	 * state is not 'device active' or any of the reset done bits are not
128271d10453SEric Joyner 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
128371d10453SEric Joyner 	 * global reset is done.
128471d10453SEric Joyner 	 */
128571d10453SEric Joyner 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
128671d10453SEric Joyner 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
128771d10453SEric Joyner 		/* poll on global reset currently in progress until done */
128871d10453SEric Joyner 		if (ice_check_reset(hw))
128971d10453SEric Joyner 			return ICE_ERR_RESET_FAILED;
129071d10453SEric Joyner 
1291*f2635e84SEric Joyner 		return 0;
129271d10453SEric Joyner 	}
129371d10453SEric Joyner 
129471d10453SEric Joyner 	/* Reset the PF */
129571d10453SEric Joyner 	reg = rd32(hw, PFGEN_CTRL);
129671d10453SEric Joyner 
129771d10453SEric Joyner 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
129871d10453SEric Joyner 
12997d7af7f8SEric Joyner 	/* Wait for the PFR to complete. The wait time is the global config lock
13007d7af7f8SEric Joyner 	 * timeout plus the PFR timeout which will account for a possible reset
13017d7af7f8SEric Joyner 	 * that is occurring during a download package operation.
13027d7af7f8SEric Joyner 	 */
13039c30461dSEric Joyner 	reset_wait_cnt = ICE_PF_RESET_WAIT_COUNT;
13049c30461dSEric Joyner 	cfg_lock_timeout = ICE_GLOBAL_CFG_LOCK_TIMEOUT;
13059c30461dSEric Joyner 
13069c30461dSEric Joyner 	for (cnt = 0; cnt < cfg_lock_timeout + reset_wait_cnt; cnt++) {
130771d10453SEric Joyner 		reg = rd32(hw, PFGEN_CTRL);
130871d10453SEric Joyner 		if (!(reg & PFGEN_CTRL_PFSWR_M))
130971d10453SEric Joyner 			break;
131071d10453SEric Joyner 
131171d10453SEric Joyner 		ice_msec_delay(1, true);
131271d10453SEric Joyner 	}
131371d10453SEric Joyner 
13149c30461dSEric Joyner 	if (cnt == cfg_lock_timeout + reset_wait_cnt) {
13157d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n");
131671d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
131771d10453SEric Joyner 	}
131871d10453SEric Joyner 
1319*f2635e84SEric Joyner 	return 0;
132071d10453SEric Joyner }
132171d10453SEric Joyner 
132271d10453SEric Joyner /**
132371d10453SEric Joyner  * ice_reset - Perform different types of reset
132471d10453SEric Joyner  * @hw: pointer to the hardware structure
132571d10453SEric Joyner  * @req: reset request
132671d10453SEric Joyner  *
132771d10453SEric Joyner  * This function triggers a reset as specified by the req parameter.
132871d10453SEric Joyner  *
132971d10453SEric Joyner  * Note:
133071d10453SEric Joyner  * If anything other than a PF reset is triggered, PXE mode is restored.
133171d10453SEric Joyner  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
133271d10453SEric Joyner  * interface has been restored in the rebuild flow.
133371d10453SEric Joyner  */
1334*f2635e84SEric Joyner int ice_reset(struct ice_hw *hw, enum ice_reset_req req)
133571d10453SEric Joyner {
133671d10453SEric Joyner 	u32 val = 0;
133771d10453SEric Joyner 
133871d10453SEric Joyner 	switch (req) {
133971d10453SEric Joyner 	case ICE_RESET_PFR:
134071d10453SEric Joyner 		return ice_pf_reset(hw);
134171d10453SEric Joyner 	case ICE_RESET_CORER:
134271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
134371d10453SEric Joyner 		val = GLGEN_RTRIG_CORER_M;
134471d10453SEric Joyner 		break;
134571d10453SEric Joyner 	case ICE_RESET_GLOBR:
134671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
134771d10453SEric Joyner 		val = GLGEN_RTRIG_GLOBR_M;
134871d10453SEric Joyner 		break;
134971d10453SEric Joyner 	default:
135071d10453SEric Joyner 		return ICE_ERR_PARAM;
135171d10453SEric Joyner 	}
135271d10453SEric Joyner 
135371d10453SEric Joyner 	val |= rd32(hw, GLGEN_RTRIG);
135471d10453SEric Joyner 	wr32(hw, GLGEN_RTRIG, val);
135571d10453SEric Joyner 	ice_flush(hw);
135671d10453SEric Joyner 
135771d10453SEric Joyner 	/* wait for the FW to be ready */
135871d10453SEric Joyner 	return ice_check_reset(hw);
135971d10453SEric Joyner }
136071d10453SEric Joyner 
136171d10453SEric Joyner /**
136271d10453SEric Joyner  * ice_copy_rxq_ctx_to_hw
136371d10453SEric Joyner  * @hw: pointer to the hardware structure
136471d10453SEric Joyner  * @ice_rxq_ctx: pointer to the rxq context
136571d10453SEric Joyner  * @rxq_index: the index of the Rx queue
136671d10453SEric Joyner  *
136771d10453SEric Joyner  * Copies rxq context from dense structure to HW register space
136871d10453SEric Joyner  */
1369*f2635e84SEric Joyner static int
137071d10453SEric Joyner ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
137171d10453SEric Joyner {
137271d10453SEric Joyner 	u8 i;
137371d10453SEric Joyner 
137471d10453SEric Joyner 	if (!ice_rxq_ctx)
137571d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
137671d10453SEric Joyner 
137771d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
137871d10453SEric Joyner 		return ICE_ERR_PARAM;
137971d10453SEric Joyner 
138071d10453SEric Joyner 	/* Copy each dword separately to HW */
138171d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
138271d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index),
138371d10453SEric Joyner 		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
138471d10453SEric Joyner 
138571d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
138671d10453SEric Joyner 			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
138771d10453SEric Joyner 	}
138871d10453SEric Joyner 
1389*f2635e84SEric Joyner 	return 0;
139071d10453SEric Joyner }
139171d10453SEric Joyner 
13929dc2f6e2SEric Joyner /**
13939dc2f6e2SEric Joyner  * ice_copy_rxq_ctx_from_hw - Copy rxq context register from HW
13949dc2f6e2SEric Joyner  * @hw: pointer to the hardware structure
13959dc2f6e2SEric Joyner  * @ice_rxq_ctx: pointer to the rxq context
13969dc2f6e2SEric Joyner  * @rxq_index: the index of the Rx queue
13979dc2f6e2SEric Joyner  *
13989dc2f6e2SEric Joyner  * Copies rxq context from HW register space to dense structure
13999dc2f6e2SEric Joyner  */
1400*f2635e84SEric Joyner static int
14019dc2f6e2SEric Joyner ice_copy_rxq_ctx_from_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
14029dc2f6e2SEric Joyner {
14039dc2f6e2SEric Joyner 	u8 i;
14049dc2f6e2SEric Joyner 
14059dc2f6e2SEric Joyner 	if (!ice_rxq_ctx)
14069dc2f6e2SEric Joyner 		return ICE_ERR_BAD_PTR;
14079dc2f6e2SEric Joyner 
14089dc2f6e2SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
14099dc2f6e2SEric Joyner 		return ICE_ERR_PARAM;
14109dc2f6e2SEric Joyner 
14119dc2f6e2SEric Joyner 	/* Copy each dword separately from HW */
14129dc2f6e2SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
14139dc2f6e2SEric Joyner 		u32 *ctx = (u32 *)(ice_rxq_ctx + (i * sizeof(u32)));
14149dc2f6e2SEric Joyner 
14159dc2f6e2SEric Joyner 		*ctx = rd32(hw, QRX_CONTEXT(i, rxq_index));
14169dc2f6e2SEric Joyner 
14179dc2f6e2SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, *ctx);
14189dc2f6e2SEric Joyner 	}
14199dc2f6e2SEric Joyner 
1420*f2635e84SEric Joyner 	return 0;
14219dc2f6e2SEric Joyner }
14229dc2f6e2SEric Joyner 
142371d10453SEric Joyner /* LAN Rx Queue Context */
142471d10453SEric Joyner static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
142571d10453SEric Joyner 	/* Field		Width	LSB */
142671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
142771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
142871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
142971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
143071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
143171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
143271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
143371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
143471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
143571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
143671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
143771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
143871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
143971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
144071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
144171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
144271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
144371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
144471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
144571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
144671d10453SEric Joyner 	{ 0 }
144771d10453SEric Joyner };
144871d10453SEric Joyner 
144971d10453SEric Joyner /**
145071d10453SEric Joyner  * ice_write_rxq_ctx
145171d10453SEric Joyner  * @hw: pointer to the hardware structure
145271d10453SEric Joyner  * @rlan_ctx: pointer to the rxq context
145371d10453SEric Joyner  * @rxq_index: the index of the Rx queue
145471d10453SEric Joyner  *
145571d10453SEric Joyner  * Converts rxq context from sparse to dense structure and then writes
145671d10453SEric Joyner  * it to HW register space and enables the hardware to prefetch descriptors
145771d10453SEric Joyner  * instead of only fetching them on demand
145871d10453SEric Joyner  */
1459*f2635e84SEric Joyner int
146071d10453SEric Joyner ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
146171d10453SEric Joyner 		  u32 rxq_index)
146271d10453SEric Joyner {
146371d10453SEric Joyner 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
146471d10453SEric Joyner 
146571d10453SEric Joyner 	if (!rlan_ctx)
146671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
146771d10453SEric Joyner 
146871d10453SEric Joyner 	rlan_ctx->prefena = 1;
146971d10453SEric Joyner 
14707d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
147171d10453SEric Joyner 	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
147271d10453SEric Joyner }
147371d10453SEric Joyner 
147471d10453SEric Joyner /**
14759dc2f6e2SEric Joyner  * ice_read_rxq_ctx - Read rxq context from HW
14769dc2f6e2SEric Joyner  * @hw: pointer to the hardware structure
14779dc2f6e2SEric Joyner  * @rlan_ctx: pointer to the rxq context
14789dc2f6e2SEric Joyner  * @rxq_index: the index of the Rx queue
14799dc2f6e2SEric Joyner  *
14809dc2f6e2SEric Joyner  * Read rxq context from HW register space and then converts it from dense
14819dc2f6e2SEric Joyner  * structure to sparse
14829dc2f6e2SEric Joyner  */
1483*f2635e84SEric Joyner int
14849dc2f6e2SEric Joyner ice_read_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
14859dc2f6e2SEric Joyner 		 u32 rxq_index)
14869dc2f6e2SEric Joyner {
14879dc2f6e2SEric Joyner 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
1488*f2635e84SEric Joyner 	int status;
14899dc2f6e2SEric Joyner 
14909dc2f6e2SEric Joyner 	if (!rlan_ctx)
14919dc2f6e2SEric Joyner 		return ICE_ERR_BAD_PTR;
14929dc2f6e2SEric Joyner 
14939dc2f6e2SEric Joyner 	status = ice_copy_rxq_ctx_from_hw(hw, ctx_buf, rxq_index);
14949dc2f6e2SEric Joyner 	if (status)
14959dc2f6e2SEric Joyner 		return status;
14969dc2f6e2SEric Joyner 
14979dc2f6e2SEric Joyner 	return ice_get_ctx(ctx_buf, (u8 *)rlan_ctx, ice_rlan_ctx_info);
14989dc2f6e2SEric Joyner }
14999dc2f6e2SEric Joyner 
15009dc2f6e2SEric Joyner /**
150171d10453SEric Joyner  * ice_clear_rxq_ctx
150271d10453SEric Joyner  * @hw: pointer to the hardware structure
150371d10453SEric Joyner  * @rxq_index: the index of the Rx queue to clear
150471d10453SEric Joyner  *
150571d10453SEric Joyner  * Clears rxq context in HW register space
150671d10453SEric Joyner  */
1507*f2635e84SEric Joyner int ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index)
150871d10453SEric Joyner {
150971d10453SEric Joyner 	u8 i;
151071d10453SEric Joyner 
151171d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
151271d10453SEric Joyner 		return ICE_ERR_PARAM;
151371d10453SEric Joyner 
151471d10453SEric Joyner 	/* Clear each dword register separately */
151571d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++)
151671d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index), 0);
151771d10453SEric Joyner 
1518*f2635e84SEric Joyner 	return 0;
151971d10453SEric Joyner }
152071d10453SEric Joyner 
15219dc2f6e2SEric Joyner /* LAN Tx Queue Context used for set Tx config by ice_aqc_opc_add_txqs,
15229dc2f6e2SEric Joyner  * Bit[0-175] is valid
15239dc2f6e2SEric Joyner  */
152471d10453SEric Joyner const struct ice_ctx_ele ice_tlan_ctx_info[] = {
152571d10453SEric Joyner 				    /* Field			Width	LSB */
152671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
152771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
152871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
152971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
153071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
153171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
153271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
153371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
153471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
153571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
153671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
153771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
153871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
153971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
154071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
154171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
154271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
154371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
154471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
154571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
154671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
154771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
154871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
154971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
155071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
155171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
155271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
155371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
155471d10453SEric Joyner 	{ 0 }
155571d10453SEric Joyner };
155671d10453SEric Joyner 
155771d10453SEric Joyner /**
155871d10453SEric Joyner  * ice_copy_tx_cmpltnq_ctx_to_hw
155971d10453SEric Joyner  * @hw: pointer to the hardware structure
156071d10453SEric Joyner  * @ice_tx_cmpltnq_ctx: pointer to the Tx completion queue context
156171d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
156271d10453SEric Joyner  *
156371d10453SEric Joyner  * Copies Tx completion queue context from dense structure to HW register space
156471d10453SEric Joyner  */
1565*f2635e84SEric Joyner static int
156671d10453SEric Joyner ice_copy_tx_cmpltnq_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_cmpltnq_ctx,
156771d10453SEric Joyner 			      u32 tx_cmpltnq_index)
156871d10453SEric Joyner {
156971d10453SEric Joyner 	u8 i;
157071d10453SEric Joyner 
157171d10453SEric Joyner 	if (!ice_tx_cmpltnq_ctx)
157271d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
157371d10453SEric Joyner 
157471d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
157571d10453SEric Joyner 		return ICE_ERR_PARAM;
157671d10453SEric Joyner 
157771d10453SEric Joyner 	/* Copy each dword separately to HW */
157871d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++) {
157971d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index),
158071d10453SEric Joyner 		     *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
158171d10453SEric Joyner 
158271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "cmpltnqdata[%d]: %08X\n", i,
158371d10453SEric Joyner 			  *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
158471d10453SEric Joyner 	}
158571d10453SEric Joyner 
1586*f2635e84SEric Joyner 	return 0;
158771d10453SEric Joyner }
158871d10453SEric Joyner 
158971d10453SEric Joyner /* LAN Tx Completion Queue Context */
159071d10453SEric Joyner static const struct ice_ctx_ele ice_tx_cmpltnq_ctx_info[] = {
159171d10453SEric Joyner 				       /* Field			Width   LSB */
159271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, base,			57,	0),
159371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, q_len,		18,	64),
159471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, generation,		1,	96),
159571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, wrt_ptr,		22,	97),
159671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, pf_num,		3,	128),
159771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_num,		10,	131),
159871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_type,		2,	141),
159971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, tph_desc_wr,		1,	160),
160071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cpuid,		8,	161),
160171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cmpltn_cache,		512,	192),
160271d10453SEric Joyner 	{ 0 }
160371d10453SEric Joyner };
160471d10453SEric Joyner 
160571d10453SEric Joyner /**
160671d10453SEric Joyner  * ice_write_tx_cmpltnq_ctx
160771d10453SEric Joyner  * @hw: pointer to the hardware structure
160871d10453SEric Joyner  * @tx_cmpltnq_ctx: pointer to the completion queue context
160971d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
161071d10453SEric Joyner  *
161171d10453SEric Joyner  * Converts completion queue context from sparse to dense structure and then
161271d10453SEric Joyner  * writes it to HW register space
161371d10453SEric Joyner  */
1614*f2635e84SEric Joyner int
161571d10453SEric Joyner ice_write_tx_cmpltnq_ctx(struct ice_hw *hw,
161671d10453SEric Joyner 			 struct ice_tx_cmpltnq_ctx *tx_cmpltnq_ctx,
161771d10453SEric Joyner 			 u32 tx_cmpltnq_index)
161871d10453SEric Joyner {
161971d10453SEric Joyner 	u8 ctx_buf[ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
162071d10453SEric Joyner 
16217d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info);
162271d10453SEric Joyner 	return ice_copy_tx_cmpltnq_ctx_to_hw(hw, ctx_buf, tx_cmpltnq_index);
162371d10453SEric Joyner }
162471d10453SEric Joyner 
162571d10453SEric Joyner /**
162671d10453SEric Joyner  * ice_clear_tx_cmpltnq_ctx
162771d10453SEric Joyner  * @hw: pointer to the hardware structure
162871d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue to clear
162971d10453SEric Joyner  *
163071d10453SEric Joyner  * Clears Tx completion queue context in HW register space
163171d10453SEric Joyner  */
1632*f2635e84SEric Joyner int
163371d10453SEric Joyner ice_clear_tx_cmpltnq_ctx(struct ice_hw *hw, u32 tx_cmpltnq_index)
163471d10453SEric Joyner {
163571d10453SEric Joyner 	u8 i;
163671d10453SEric Joyner 
163771d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
163871d10453SEric Joyner 		return ICE_ERR_PARAM;
163971d10453SEric Joyner 
164071d10453SEric Joyner 	/* Clear each dword register separately */
164171d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++)
164271d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index), 0);
164371d10453SEric Joyner 
1644*f2635e84SEric Joyner 	return 0;
164571d10453SEric Joyner }
164671d10453SEric Joyner 
164771d10453SEric Joyner /**
164871d10453SEric Joyner  * ice_copy_tx_drbell_q_ctx_to_hw
164971d10453SEric Joyner  * @hw: pointer to the hardware structure
165071d10453SEric Joyner  * @ice_tx_drbell_q_ctx: pointer to the doorbell queue context
165171d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
165271d10453SEric Joyner  *
165371d10453SEric Joyner  * Copies doorbell queue context from dense structure to HW register space
165471d10453SEric Joyner  */
1655*f2635e84SEric Joyner static int
165671d10453SEric Joyner ice_copy_tx_drbell_q_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_drbell_q_ctx,
165771d10453SEric Joyner 			       u32 tx_drbell_q_index)
165871d10453SEric Joyner {
165971d10453SEric Joyner 	u8 i;
166071d10453SEric Joyner 
166171d10453SEric Joyner 	if (!ice_tx_drbell_q_ctx)
166271d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
166371d10453SEric Joyner 
166471d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
166571d10453SEric Joyner 		return ICE_ERR_PARAM;
166671d10453SEric Joyner 
166771d10453SEric Joyner 	/* Copy each dword separately to HW */
166871d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++) {
166971d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index),
167071d10453SEric Joyner 		     *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
167171d10453SEric Joyner 
167271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "tx_drbell_qdata[%d]: %08X\n", i,
167371d10453SEric Joyner 			  *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
167471d10453SEric Joyner 	}
167571d10453SEric Joyner 
1676*f2635e84SEric Joyner 	return 0;
167771d10453SEric Joyner }
167871d10453SEric Joyner 
167971d10453SEric Joyner /* LAN Tx Doorbell Queue Context info */
168071d10453SEric Joyner static const struct ice_ctx_ele ice_tx_drbell_q_ctx_info[] = {
168171d10453SEric Joyner 					/* Field		Width   LSB */
168271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, base,		57,	0),
168371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, ring_len,		13,	64),
168471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, pf_num,		3,	80),
168571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vf_num,		8,	84),
168671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vmvf_type,		2,	94),
168771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, cpuid,		8,	96),
168871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_rd,		1,	104),
168971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_wr,		1,	108),
169071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, db_q_en,		1,	112),
169171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_head,		13,	128),
169271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_tail,		13,	144),
169371d10453SEric Joyner 	{ 0 }
169471d10453SEric Joyner };
169571d10453SEric Joyner 
169671d10453SEric Joyner /**
169771d10453SEric Joyner  * ice_write_tx_drbell_q_ctx
169871d10453SEric Joyner  * @hw: pointer to the hardware structure
169971d10453SEric Joyner  * @tx_drbell_q_ctx: pointer to the doorbell queue context
170071d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
170171d10453SEric Joyner  *
170271d10453SEric Joyner  * Converts doorbell queue context from sparse to dense structure and then
170371d10453SEric Joyner  * writes it to HW register space
170471d10453SEric Joyner  */
1705*f2635e84SEric Joyner int
170671d10453SEric Joyner ice_write_tx_drbell_q_ctx(struct ice_hw *hw,
170771d10453SEric Joyner 			  struct ice_tx_drbell_q_ctx *tx_drbell_q_ctx,
170871d10453SEric Joyner 			  u32 tx_drbell_q_index)
170971d10453SEric Joyner {
171071d10453SEric Joyner 	u8 ctx_buf[ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
171171d10453SEric Joyner 
17127d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_drbell_q_ctx, ctx_buf,
17137d7af7f8SEric Joyner 		    ice_tx_drbell_q_ctx_info);
171471d10453SEric Joyner 	return ice_copy_tx_drbell_q_ctx_to_hw(hw, ctx_buf, tx_drbell_q_index);
171571d10453SEric Joyner }
171671d10453SEric Joyner 
171771d10453SEric Joyner /**
171871d10453SEric Joyner  * ice_clear_tx_drbell_q_ctx
171971d10453SEric Joyner  * @hw: pointer to the hardware structure
172071d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue to clear
172171d10453SEric Joyner  *
172271d10453SEric Joyner  * Clears doorbell queue context in HW register space
172371d10453SEric Joyner  */
1724*f2635e84SEric Joyner int
172571d10453SEric Joyner ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index)
172671d10453SEric Joyner {
172771d10453SEric Joyner 	u8 i;
172871d10453SEric Joyner 
172971d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
173071d10453SEric Joyner 		return ICE_ERR_PARAM;
173171d10453SEric Joyner 
173271d10453SEric Joyner 	/* Clear each dword register separately */
173371d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++)
173471d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index), 0);
173571d10453SEric Joyner 
1736*f2635e84SEric Joyner 	return 0;
1737*f2635e84SEric Joyner }
1738*f2635e84SEric Joyner 
1739*f2635e84SEric Joyner /* Sideband Queue command wrappers */
1740*f2635e84SEric Joyner 
1741*f2635e84SEric Joyner /**
1742*f2635e84SEric Joyner  * ice_get_sbq - returns the right control queue to use for sideband
1743*f2635e84SEric Joyner  * @hw: pointer to the hardware structure
1744*f2635e84SEric Joyner  */
1745*f2635e84SEric Joyner static struct ice_ctl_q_info *ice_get_sbq(struct ice_hw *hw)
1746*f2635e84SEric Joyner {
1747*f2635e84SEric Joyner 	if (!ice_is_generic_mac(hw))
1748*f2635e84SEric Joyner 		return &hw->adminq;
1749*f2635e84SEric Joyner 	return &hw->sbq;
1750*f2635e84SEric Joyner }
1751*f2635e84SEric Joyner 
1752*f2635e84SEric Joyner /**
1753*f2635e84SEric Joyner  * ice_sbq_send_cmd - send Sideband Queue command to Sideband Queue
1754*f2635e84SEric Joyner  * @hw: pointer to the HW struct
1755*f2635e84SEric Joyner  * @desc: descriptor describing the command
1756*f2635e84SEric Joyner  * @buf: buffer to use for indirect commands (NULL for direct commands)
1757*f2635e84SEric Joyner  * @buf_size: size of buffer for indirect commands (0 for direct commands)
1758*f2635e84SEric Joyner  * @cd: pointer to command details structure
1759*f2635e84SEric Joyner  */
1760*f2635e84SEric Joyner static int
1761*f2635e84SEric Joyner ice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
1762*f2635e84SEric Joyner 		 void *buf, u16 buf_size, struct ice_sq_cd *cd)
1763*f2635e84SEric Joyner {
1764*f2635e84SEric Joyner 	return ice_sq_send_cmd(hw, ice_get_sbq(hw), (struct ice_aq_desc *)desc,
1765*f2635e84SEric Joyner 			       buf, buf_size, cd);
1766*f2635e84SEric Joyner }
1767*f2635e84SEric Joyner 
1768*f2635e84SEric Joyner /**
1769*f2635e84SEric Joyner  * ice_sbq_send_cmd_nolock - send Sideband Queue command to Sideband Queue
1770*f2635e84SEric Joyner  *                           but do not lock sq_lock
1771*f2635e84SEric Joyner  * @hw: pointer to the HW struct
1772*f2635e84SEric Joyner  * @desc: descriptor describing the command
1773*f2635e84SEric Joyner  * @buf: buffer to use for indirect commands (NULL for direct commands)
1774*f2635e84SEric Joyner  * @buf_size: size of buffer for indirect commands (0 for direct commands)
1775*f2635e84SEric Joyner  * @cd: pointer to command details structure
1776*f2635e84SEric Joyner  */
1777*f2635e84SEric Joyner static int
1778*f2635e84SEric Joyner ice_sbq_send_cmd_nolock(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
1779*f2635e84SEric Joyner 			void *buf, u16 buf_size, struct ice_sq_cd *cd)
1780*f2635e84SEric Joyner {
1781*f2635e84SEric Joyner 	return ice_sq_send_cmd_nolock(hw, ice_get_sbq(hw),
1782*f2635e84SEric Joyner 				      (struct ice_aq_desc *)desc, buf,
1783*f2635e84SEric Joyner 				      buf_size, cd);
1784*f2635e84SEric Joyner }
1785*f2635e84SEric Joyner 
1786*f2635e84SEric Joyner /**
1787*f2635e84SEric Joyner  * ice_sbq_rw_reg_lp - Fill Sideband Queue command, with lock parameter
1788*f2635e84SEric Joyner  * @hw: pointer to the HW struct
1789*f2635e84SEric Joyner  * @in: message info to be filled in descriptor
1790*f2635e84SEric Joyner  * @flag: flag to fill desc structure
1791*f2635e84SEric Joyner  * @lock: true to lock the sq_lock (the usual case); false if the sq_lock has
1792*f2635e84SEric Joyner  *        already been locked at a higher level
1793*f2635e84SEric Joyner  */
1794*f2635e84SEric Joyner int ice_sbq_rw_reg_lp(struct ice_hw *hw, struct ice_sbq_msg_input *in,
1795*f2635e84SEric Joyner 		      u16 flag, bool lock)
1796*f2635e84SEric Joyner {
1797*f2635e84SEric Joyner 	struct ice_sbq_cmd_desc desc = {0};
1798*f2635e84SEric Joyner 	struct ice_sbq_msg_req msg = {0};
1799*f2635e84SEric Joyner 	u16 msg_len;
1800*f2635e84SEric Joyner 	int status;
1801*f2635e84SEric Joyner 
1802*f2635e84SEric Joyner 	msg_len = sizeof(msg);
1803*f2635e84SEric Joyner 
1804*f2635e84SEric Joyner 	msg.dest_dev = in->dest_dev;
1805*f2635e84SEric Joyner 	msg.opcode = in->opcode;
1806*f2635e84SEric Joyner 	msg.flags = ICE_SBQ_MSG_FLAGS;
1807*f2635e84SEric Joyner 	msg.sbe_fbe = ICE_SBQ_MSG_SBE_FBE;
1808*f2635e84SEric Joyner 	msg.msg_addr_low = CPU_TO_LE16(in->msg_addr_low);
1809*f2635e84SEric Joyner 	msg.msg_addr_high = CPU_TO_LE32(in->msg_addr_high);
1810*f2635e84SEric Joyner 
1811*f2635e84SEric Joyner 	if (in->opcode)
1812*f2635e84SEric Joyner 		msg.data = CPU_TO_LE32(in->data);
1813*f2635e84SEric Joyner 	else
1814*f2635e84SEric Joyner 		/* data read comes back in completion, so shorten the struct by
1815*f2635e84SEric Joyner 		 * sizeof(msg.data)
1816*f2635e84SEric Joyner 		 */
1817*f2635e84SEric Joyner 		msg_len -= sizeof(msg.data);
1818*f2635e84SEric Joyner 
1819*f2635e84SEric Joyner 	desc.flags = CPU_TO_LE16(flag);
1820*f2635e84SEric Joyner 	desc.opcode = CPU_TO_LE16(ice_sbq_opc_neigh_dev_req);
1821*f2635e84SEric Joyner 	desc.param0.cmd_len = CPU_TO_LE16(msg_len);
1822*f2635e84SEric Joyner 	if (lock)
1823*f2635e84SEric Joyner 		status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL);
1824*f2635e84SEric Joyner 	else
1825*f2635e84SEric Joyner 		status = ice_sbq_send_cmd_nolock(hw, &desc, &msg, msg_len,
1826*f2635e84SEric Joyner 						 NULL);
1827*f2635e84SEric Joyner 	if (!status && !in->opcode)
1828*f2635e84SEric Joyner 		in->data = LE32_TO_CPU
1829*f2635e84SEric Joyner 			(((struct ice_sbq_msg_cmpl *)&msg)->data);
1830*f2635e84SEric Joyner 	return status;
1831*f2635e84SEric Joyner }
1832*f2635e84SEric Joyner 
1833*f2635e84SEric Joyner /**
1834*f2635e84SEric Joyner  * ice_sbq_rw_reg - Fill Sideband Queue command
1835*f2635e84SEric Joyner  * @hw: pointer to the HW struct
1836*f2635e84SEric Joyner  * @in: message info to be filled in descriptor
1837*f2635e84SEric Joyner  * @flag: flag to fill desc structure
1838*f2635e84SEric Joyner  */
1839*f2635e84SEric Joyner int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in, u16 flag)
1840*f2635e84SEric Joyner {
1841*f2635e84SEric Joyner 	return ice_sbq_rw_reg_lp(hw, in, flag, true);
1842*f2635e84SEric Joyner }
1843*f2635e84SEric Joyner 
1844*f2635e84SEric Joyner /**
1845*f2635e84SEric Joyner  * ice_sbq_lock - Lock the sideband queue's sq_lock
1846*f2635e84SEric Joyner  * @hw: pointer to the HW struct
1847*f2635e84SEric Joyner  */
1848*f2635e84SEric Joyner void ice_sbq_lock(struct ice_hw *hw)
1849*f2635e84SEric Joyner {
1850*f2635e84SEric Joyner 	ice_acquire_lock(&ice_get_sbq(hw)->sq_lock);
1851*f2635e84SEric Joyner }
1852*f2635e84SEric Joyner 
1853*f2635e84SEric Joyner /**
1854*f2635e84SEric Joyner  * ice_sbq_unlock - Unlock the sideband queue's sq_lock
1855*f2635e84SEric Joyner  * @hw: pointer to the HW struct
1856*f2635e84SEric Joyner  */
1857*f2635e84SEric Joyner void ice_sbq_unlock(struct ice_hw *hw)
1858*f2635e84SEric Joyner {
1859*f2635e84SEric Joyner 	ice_release_lock(&ice_get_sbq(hw)->sq_lock);
186071d10453SEric Joyner }
186171d10453SEric Joyner 
186271d10453SEric Joyner /* FW Admin Queue command wrappers */
186371d10453SEric Joyner 
186471d10453SEric Joyner /**
18659cf1841cSEric Joyner  * ice_should_retry_sq_send_cmd
18669cf1841cSEric Joyner  * @opcode: AQ opcode
18679cf1841cSEric Joyner  *
18689cf1841cSEric Joyner  * Decide if we should retry the send command routine for the ATQ, depending
18699cf1841cSEric Joyner  * on the opcode.
18709cf1841cSEric Joyner  */
18719cf1841cSEric Joyner static bool ice_should_retry_sq_send_cmd(u16 opcode)
18729cf1841cSEric Joyner {
18739cf1841cSEric Joyner 	switch (opcode) {
18749cf1841cSEric Joyner 	case ice_aqc_opc_dnl_get_status:
18759cf1841cSEric Joyner 	case ice_aqc_opc_dnl_run:
18769cf1841cSEric Joyner 	case ice_aqc_opc_dnl_call:
18779cf1841cSEric Joyner 	case ice_aqc_opc_dnl_read_sto:
18789cf1841cSEric Joyner 	case ice_aqc_opc_dnl_write_sto:
18799cf1841cSEric Joyner 	case ice_aqc_opc_dnl_set_breakpoints:
18809cf1841cSEric Joyner 	case ice_aqc_opc_dnl_read_log:
18819cf1841cSEric Joyner 	case ice_aqc_opc_get_link_topo:
18829cf1841cSEric Joyner 	case ice_aqc_opc_done_alt_write:
18839cf1841cSEric Joyner 	case ice_aqc_opc_lldp_stop:
18849cf1841cSEric Joyner 	case ice_aqc_opc_lldp_start:
18859cf1841cSEric Joyner 	case ice_aqc_opc_lldp_filter_ctrl:
18869cf1841cSEric Joyner 		return true;
18879cf1841cSEric Joyner 	}
18889cf1841cSEric Joyner 
18899cf1841cSEric Joyner 	return false;
18909cf1841cSEric Joyner }
18919cf1841cSEric Joyner 
18929cf1841cSEric Joyner /**
18939cf1841cSEric Joyner  * ice_sq_send_cmd_retry - send command to Control Queue (ATQ)
18949cf1841cSEric Joyner  * @hw: pointer to the HW struct
18959cf1841cSEric Joyner  * @cq: pointer to the specific Control queue
18969cf1841cSEric Joyner  * @desc: prefilled descriptor describing the command
18979cf1841cSEric Joyner  * @buf: buffer to use for indirect commands (or NULL for direct commands)
18989cf1841cSEric Joyner  * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
18999cf1841cSEric Joyner  * @cd: pointer to command details structure
19009cf1841cSEric Joyner  *
19019cf1841cSEric Joyner  * Retry sending the FW Admin Queue command, multiple times, to the FW Admin
19029cf1841cSEric Joyner  * Queue if the EBUSY AQ error is returned.
19039cf1841cSEric Joyner  */
1904*f2635e84SEric Joyner static int
19059cf1841cSEric Joyner ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
19069cf1841cSEric Joyner 		      struct ice_aq_desc *desc, void *buf, u16 buf_size,
19079cf1841cSEric Joyner 		      struct ice_sq_cd *cd)
19089cf1841cSEric Joyner {
19099cf1841cSEric Joyner 	struct ice_aq_desc desc_cpy;
19109cf1841cSEric Joyner 	bool is_cmd_for_retry;
19119cf1841cSEric Joyner 	u8 *buf_cpy = NULL;
19129cf1841cSEric Joyner 	u8 idx = 0;
19139cf1841cSEric Joyner 	u16 opcode;
1914*f2635e84SEric Joyner 	int status;
19159cf1841cSEric Joyner 
19169cf1841cSEric Joyner 	opcode = LE16_TO_CPU(desc->opcode);
19179cf1841cSEric Joyner 	is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode);
19189cf1841cSEric Joyner 	ice_memset(&desc_cpy, 0, sizeof(desc_cpy), ICE_NONDMA_MEM);
19199cf1841cSEric Joyner 
19209cf1841cSEric Joyner 	if (is_cmd_for_retry) {
19219cf1841cSEric Joyner 		if (buf) {
19229cf1841cSEric Joyner 			buf_cpy = (u8 *)ice_malloc(hw, buf_size);
19239cf1841cSEric Joyner 			if (!buf_cpy)
19249cf1841cSEric Joyner 				return ICE_ERR_NO_MEMORY;
19259cf1841cSEric Joyner 		}
19269cf1841cSEric Joyner 
19279cf1841cSEric Joyner 		ice_memcpy(&desc_cpy, desc, sizeof(desc_cpy),
19289cf1841cSEric Joyner 			   ICE_NONDMA_TO_NONDMA);
19299cf1841cSEric Joyner 	}
19309cf1841cSEric Joyner 
19319cf1841cSEric Joyner 	do {
19329cf1841cSEric Joyner 		status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd);
19339cf1841cSEric Joyner 
1934*f2635e84SEric Joyner 		if (!is_cmd_for_retry || !status ||
19359cf1841cSEric Joyner 		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
19369cf1841cSEric Joyner 			break;
19379cf1841cSEric Joyner 
19389cf1841cSEric Joyner 		if (buf_cpy)
19399cf1841cSEric Joyner 			ice_memcpy(buf, buf_cpy, buf_size,
19409cf1841cSEric Joyner 				   ICE_NONDMA_TO_NONDMA);
19419cf1841cSEric Joyner 
19429cf1841cSEric Joyner 		ice_memcpy(desc, &desc_cpy, sizeof(desc_cpy),
19439cf1841cSEric Joyner 			   ICE_NONDMA_TO_NONDMA);
19449cf1841cSEric Joyner 
19459cf1841cSEric Joyner 		ice_msec_delay(ICE_SQ_SEND_DELAY_TIME_MS, false);
19469cf1841cSEric Joyner 
19479cf1841cSEric Joyner 	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
19489cf1841cSEric Joyner 
19499cf1841cSEric Joyner 	if (buf_cpy)
19509cf1841cSEric Joyner 		ice_free(hw, buf_cpy);
19519cf1841cSEric Joyner 
19529cf1841cSEric Joyner 	return status;
19539cf1841cSEric Joyner }
19549cf1841cSEric Joyner 
19559cf1841cSEric Joyner /**
195671d10453SEric Joyner  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
195771d10453SEric Joyner  * @hw: pointer to the HW struct
195871d10453SEric Joyner  * @desc: descriptor describing the command
195971d10453SEric Joyner  * @buf: buffer to use for indirect commands (NULL for direct commands)
196071d10453SEric Joyner  * @buf_size: size of buffer for indirect commands (0 for direct commands)
196171d10453SEric Joyner  * @cd: pointer to command details structure
196271d10453SEric Joyner  *
196371d10453SEric Joyner  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
196471d10453SEric Joyner  */
1965*f2635e84SEric Joyner int
196671d10453SEric Joyner ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
196771d10453SEric Joyner 		u16 buf_size, struct ice_sq_cd *cd)
196871d10453SEric Joyner {
19699cf1841cSEric Joyner 	return ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);
197071d10453SEric Joyner }
197171d10453SEric Joyner 
197271d10453SEric Joyner /**
197371d10453SEric Joyner  * ice_aq_get_fw_ver
197471d10453SEric Joyner  * @hw: pointer to the HW struct
197571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
197671d10453SEric Joyner  *
197771d10453SEric Joyner  * Get the firmware version (0x0001) from the admin queue commands
197871d10453SEric Joyner  */
1979*f2635e84SEric Joyner int ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
198071d10453SEric Joyner {
198171d10453SEric Joyner 	struct ice_aqc_get_ver *resp;
198271d10453SEric Joyner 	struct ice_aq_desc desc;
1983*f2635e84SEric Joyner 	int status;
198471d10453SEric Joyner 
198571d10453SEric Joyner 	resp = &desc.params.get_ver;
198671d10453SEric Joyner 
198771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
198871d10453SEric Joyner 
198971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
199071d10453SEric Joyner 
199171d10453SEric Joyner 	if (!status) {
199271d10453SEric Joyner 		hw->fw_branch = resp->fw_branch;
199371d10453SEric Joyner 		hw->fw_maj_ver = resp->fw_major;
199471d10453SEric Joyner 		hw->fw_min_ver = resp->fw_minor;
199571d10453SEric Joyner 		hw->fw_patch = resp->fw_patch;
199671d10453SEric Joyner 		hw->fw_build = LE32_TO_CPU(resp->fw_build);
199771d10453SEric Joyner 		hw->api_branch = resp->api_branch;
199871d10453SEric Joyner 		hw->api_maj_ver = resp->api_major;
199971d10453SEric Joyner 		hw->api_min_ver = resp->api_minor;
200071d10453SEric Joyner 		hw->api_patch = resp->api_patch;
200171d10453SEric Joyner 	}
200271d10453SEric Joyner 
200371d10453SEric Joyner 	return status;
200471d10453SEric Joyner }
200571d10453SEric Joyner 
200671d10453SEric Joyner /**
200771d10453SEric Joyner  * ice_aq_send_driver_ver
200871d10453SEric Joyner  * @hw: pointer to the HW struct
200971d10453SEric Joyner  * @dv: driver's major, minor version
201071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
201171d10453SEric Joyner  *
201271d10453SEric Joyner  * Send the driver version (0x0002) to the firmware
201371d10453SEric Joyner  */
2014*f2635e84SEric Joyner int
201571d10453SEric Joyner ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
201671d10453SEric Joyner 		       struct ice_sq_cd *cd)
201771d10453SEric Joyner {
201871d10453SEric Joyner 	struct ice_aqc_driver_ver *cmd;
201971d10453SEric Joyner 	struct ice_aq_desc desc;
202071d10453SEric Joyner 	u16 len;
202171d10453SEric Joyner 
202271d10453SEric Joyner 	cmd = &desc.params.driver_ver;
202371d10453SEric Joyner 
202471d10453SEric Joyner 	if (!dv)
202571d10453SEric Joyner 		return ICE_ERR_PARAM;
202671d10453SEric Joyner 
202771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
202871d10453SEric Joyner 
202971d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
203071d10453SEric Joyner 	cmd->major_ver = dv->major_ver;
203171d10453SEric Joyner 	cmd->minor_ver = dv->minor_ver;
203271d10453SEric Joyner 	cmd->build_ver = dv->build_ver;
203371d10453SEric Joyner 	cmd->subbuild_ver = dv->subbuild_ver;
203471d10453SEric Joyner 
203571d10453SEric Joyner 	len = 0;
203671d10453SEric Joyner 	while (len < sizeof(dv->driver_string) &&
203771d10453SEric Joyner 	       IS_ASCII(dv->driver_string[len]) && dv->driver_string[len])
203871d10453SEric Joyner 		len++;
203971d10453SEric Joyner 
204071d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
204171d10453SEric Joyner }
204271d10453SEric Joyner 
204371d10453SEric Joyner /**
204471d10453SEric Joyner  * ice_aq_q_shutdown
204571d10453SEric Joyner  * @hw: pointer to the HW struct
204671d10453SEric Joyner  * @unloading: is the driver unloading itself
204771d10453SEric Joyner  *
204871d10453SEric Joyner  * Tell the Firmware that we're shutting down the AdminQ and whether
204971d10453SEric Joyner  * or not the driver is unloading as well (0x0003).
205071d10453SEric Joyner  */
2051*f2635e84SEric Joyner int ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
205271d10453SEric Joyner {
205371d10453SEric Joyner 	struct ice_aqc_q_shutdown *cmd;
205471d10453SEric Joyner 	struct ice_aq_desc desc;
205571d10453SEric Joyner 
205671d10453SEric Joyner 	cmd = &desc.params.q_shutdown;
205771d10453SEric Joyner 
205871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
205971d10453SEric Joyner 
206071d10453SEric Joyner 	if (unloading)
206171d10453SEric Joyner 		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
206271d10453SEric Joyner 
206371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
206471d10453SEric Joyner }
206571d10453SEric Joyner 
206671d10453SEric Joyner /**
206771d10453SEric Joyner  * ice_aq_req_res
206871d10453SEric Joyner  * @hw: pointer to the HW struct
206971d10453SEric Joyner  * @res: resource ID
207071d10453SEric Joyner  * @access: access type
207171d10453SEric Joyner  * @sdp_number: resource number
207271d10453SEric Joyner  * @timeout: the maximum time in ms that the driver may hold the resource
207371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
207471d10453SEric Joyner  *
207571d10453SEric Joyner  * Requests common resource using the admin queue commands (0x0008).
207671d10453SEric Joyner  * When attempting to acquire the Global Config Lock, the driver can
207771d10453SEric Joyner  * learn of three states:
2078*f2635e84SEric Joyner  *  1) 0 - acquired lock, and can perform download package
207971d10453SEric Joyner  *  2) ICE_ERR_AQ_ERROR - did not get lock, driver should fail to load
208071d10453SEric Joyner  *  3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
208171d10453SEric Joyner  *                          successfully downloaded the package; the driver does
208271d10453SEric Joyner  *                          not have to download the package and can continue
208371d10453SEric Joyner  *                          loading
208471d10453SEric Joyner  *
208571d10453SEric Joyner  * Note that if the caller is in an acquire lock, perform action, release lock
208671d10453SEric Joyner  * phase of operation, it is possible that the FW may detect a timeout and issue
208771d10453SEric Joyner  * a CORER. In this case, the driver will receive a CORER interrupt and will
208871d10453SEric Joyner  * have to determine its cause. The calling thread that is handling this flow
208971d10453SEric Joyner  * will likely get an error propagated back to it indicating the Download
209071d10453SEric Joyner  * Package, Update Package or the Release Resource AQ commands timed out.
209171d10453SEric Joyner  */
2092*f2635e84SEric Joyner static int
209371d10453SEric Joyner ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
209471d10453SEric Joyner 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
209571d10453SEric Joyner 	       struct ice_sq_cd *cd)
209671d10453SEric Joyner {
209771d10453SEric Joyner 	struct ice_aqc_req_res *cmd_resp;
209871d10453SEric Joyner 	struct ice_aq_desc desc;
2099*f2635e84SEric Joyner 	int status;
210071d10453SEric Joyner 
210171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
210271d10453SEric Joyner 
210371d10453SEric Joyner 	cmd_resp = &desc.params.res_owner;
210471d10453SEric Joyner 
210571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
210671d10453SEric Joyner 
210771d10453SEric Joyner 	cmd_resp->res_id = CPU_TO_LE16(res);
210871d10453SEric Joyner 	cmd_resp->access_type = CPU_TO_LE16(access);
210971d10453SEric Joyner 	cmd_resp->res_number = CPU_TO_LE32(sdp_number);
211071d10453SEric Joyner 	cmd_resp->timeout = CPU_TO_LE32(*timeout);
211171d10453SEric Joyner 	*timeout = 0;
211271d10453SEric Joyner 
211371d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
211471d10453SEric Joyner 
211571d10453SEric Joyner 	/* The completion specifies the maximum time in ms that the driver
211671d10453SEric Joyner 	 * may hold the resource in the Timeout field.
211771d10453SEric Joyner 	 */
211871d10453SEric Joyner 
211971d10453SEric Joyner 	/* Global config lock response utilizes an additional status field.
212071d10453SEric Joyner 	 *
212171d10453SEric Joyner 	 * If the Global config lock resource is held by some other driver, the
212271d10453SEric Joyner 	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
212371d10453SEric Joyner 	 * and the timeout field indicates the maximum time the current owner
212471d10453SEric Joyner 	 * of the resource has to free it.
212571d10453SEric Joyner 	 */
212671d10453SEric Joyner 	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
212771d10453SEric Joyner 		if (LE16_TO_CPU(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
212871d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
2129*f2635e84SEric Joyner 			return 0;
213071d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
213171d10453SEric Joyner 			   ICE_AQ_RES_GLBL_IN_PROG) {
213271d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
213371d10453SEric Joyner 			return ICE_ERR_AQ_ERROR;
213471d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
213571d10453SEric Joyner 			   ICE_AQ_RES_GLBL_DONE) {
213671d10453SEric Joyner 			return ICE_ERR_AQ_NO_WORK;
213771d10453SEric Joyner 		}
213871d10453SEric Joyner 
213971d10453SEric Joyner 		/* invalid FW response, force a timeout immediately */
214071d10453SEric Joyner 		*timeout = 0;
214171d10453SEric Joyner 		return ICE_ERR_AQ_ERROR;
214271d10453SEric Joyner 	}
214371d10453SEric Joyner 
214471d10453SEric Joyner 	/* If the resource is held by some other driver, the command completes
214571d10453SEric Joyner 	 * with a busy return value and the timeout field indicates the maximum
214671d10453SEric Joyner 	 * time the current owner of the resource has to free it.
214771d10453SEric Joyner 	 */
214871d10453SEric Joyner 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
214971d10453SEric Joyner 		*timeout = LE32_TO_CPU(cmd_resp->timeout);
215071d10453SEric Joyner 
215171d10453SEric Joyner 	return status;
215271d10453SEric Joyner }
215371d10453SEric Joyner 
215471d10453SEric Joyner /**
215571d10453SEric Joyner  * ice_aq_release_res
215671d10453SEric Joyner  * @hw: pointer to the HW struct
215771d10453SEric Joyner  * @res: resource ID
215871d10453SEric Joyner  * @sdp_number: resource number
215971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
216071d10453SEric Joyner  *
216171d10453SEric Joyner  * release common resource using the admin queue commands (0x0009)
216271d10453SEric Joyner  */
2163*f2635e84SEric Joyner static int
216471d10453SEric Joyner ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
216571d10453SEric Joyner 		   struct ice_sq_cd *cd)
216671d10453SEric Joyner {
216771d10453SEric Joyner 	struct ice_aqc_req_res *cmd;
216871d10453SEric Joyner 	struct ice_aq_desc desc;
216971d10453SEric Joyner 
217071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
217171d10453SEric Joyner 
217271d10453SEric Joyner 	cmd = &desc.params.res_owner;
217371d10453SEric Joyner 
217471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
217571d10453SEric Joyner 
217671d10453SEric Joyner 	cmd->res_id = CPU_TO_LE16(res);
217771d10453SEric Joyner 	cmd->res_number = CPU_TO_LE32(sdp_number);
217871d10453SEric Joyner 
217971d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
218071d10453SEric Joyner }
218171d10453SEric Joyner 
218271d10453SEric Joyner /**
218371d10453SEric Joyner  * ice_acquire_res
218471d10453SEric Joyner  * @hw: pointer to the HW structure
218571d10453SEric Joyner  * @res: resource ID
218671d10453SEric Joyner  * @access: access type (read or write)
218771d10453SEric Joyner  * @timeout: timeout in milliseconds
218871d10453SEric Joyner  *
218971d10453SEric Joyner  * This function will attempt to acquire the ownership of a resource.
219071d10453SEric Joyner  */
2191*f2635e84SEric Joyner int
219271d10453SEric Joyner ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
219371d10453SEric Joyner 		enum ice_aq_res_access_type access, u32 timeout)
219471d10453SEric Joyner {
219571d10453SEric Joyner #define ICE_RES_POLLING_DELAY_MS	10
219671d10453SEric Joyner 	u32 delay = ICE_RES_POLLING_DELAY_MS;
219771d10453SEric Joyner 	u32 time_left = timeout;
2198*f2635e84SEric Joyner 	int status;
219971d10453SEric Joyner 
220071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
220171d10453SEric Joyner 
220271d10453SEric Joyner 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
220371d10453SEric Joyner 
220471d10453SEric Joyner 	/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
220571d10453SEric Joyner 	 * previously acquired the resource and performed any necessary updates;
220671d10453SEric Joyner 	 * in this case the caller does not obtain the resource and has no
220771d10453SEric Joyner 	 * further work to do.
220871d10453SEric Joyner 	 */
220971d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK)
221071d10453SEric Joyner 		goto ice_acquire_res_exit;
221171d10453SEric Joyner 
221271d10453SEric Joyner 	if (status)
22137d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access);
221471d10453SEric Joyner 
221571d10453SEric Joyner 	/* If necessary, poll until the current lock owner timeouts */
221671d10453SEric Joyner 	timeout = time_left;
221771d10453SEric Joyner 	while (status && timeout && time_left) {
221871d10453SEric Joyner 		ice_msec_delay(delay, true);
221971d10453SEric Joyner 		timeout = (timeout > delay) ? timeout - delay : 0;
222071d10453SEric Joyner 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
222171d10453SEric Joyner 
222271d10453SEric Joyner 		if (status == ICE_ERR_AQ_NO_WORK)
222371d10453SEric Joyner 			/* lock free, but no work to do */
222471d10453SEric Joyner 			break;
222571d10453SEric Joyner 
222671d10453SEric Joyner 		if (!status)
222771d10453SEric Joyner 			/* lock acquired */
222871d10453SEric Joyner 			break;
222971d10453SEric Joyner 	}
223071d10453SEric Joyner 	if (status && status != ICE_ERR_AQ_NO_WORK)
223171d10453SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
223271d10453SEric Joyner 
223371d10453SEric Joyner ice_acquire_res_exit:
223471d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK) {
223571d10453SEric Joyner 		if (access == ICE_RES_WRITE)
22367d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n");
223771d10453SEric Joyner 		else
22387d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "Warning: ICE_ERR_AQ_NO_WORK not expected\n");
223971d10453SEric Joyner 	}
224071d10453SEric Joyner 	return status;
224171d10453SEric Joyner }
224271d10453SEric Joyner 
224371d10453SEric Joyner /**
224471d10453SEric Joyner  * ice_release_res
224571d10453SEric Joyner  * @hw: pointer to the HW structure
224671d10453SEric Joyner  * @res: resource ID
224771d10453SEric Joyner  *
224871d10453SEric Joyner  * This function will release a resource using the proper Admin Command.
224971d10453SEric Joyner  */
225071d10453SEric Joyner void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
225171d10453SEric Joyner {
225271d10453SEric Joyner 	u32 total_delay = 0;
2253*f2635e84SEric Joyner 	int status;
225471d10453SEric Joyner 
225571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
225671d10453SEric Joyner 
225771d10453SEric Joyner 	status = ice_aq_release_res(hw, res, 0, NULL);
225871d10453SEric Joyner 
225971d10453SEric Joyner 	/* there are some rare cases when trying to release the resource
226071d10453SEric Joyner 	 * results in an admin queue timeout, so handle them correctly
226171d10453SEric Joyner 	 */
226271d10453SEric Joyner 	while ((status == ICE_ERR_AQ_TIMEOUT) &&
226371d10453SEric Joyner 	       (total_delay < hw->adminq.sq_cmd_timeout)) {
226471d10453SEric Joyner 		ice_msec_delay(1, true);
226571d10453SEric Joyner 		status = ice_aq_release_res(hw, res, 0, NULL);
226671d10453SEric Joyner 		total_delay++;
226771d10453SEric Joyner 	}
226871d10453SEric Joyner }
226971d10453SEric Joyner 
227071d10453SEric Joyner /**
227171d10453SEric Joyner  * ice_aq_alloc_free_res - command to allocate/free resources
227271d10453SEric Joyner  * @hw: pointer to the HW struct
227371d10453SEric Joyner  * @num_entries: number of resource entries in buffer
227471d10453SEric Joyner  * @buf: Indirect buffer to hold data parameters and response
227571d10453SEric Joyner  * @buf_size: size of buffer for indirect commands
227671d10453SEric Joyner  * @opc: pass in the command opcode
227771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
227871d10453SEric Joyner  *
227971d10453SEric Joyner  * Helper function to allocate/free resources using the admin queue commands
228071d10453SEric Joyner  */
2281*f2635e84SEric Joyner int
228271d10453SEric Joyner ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
228371d10453SEric Joyner 		      struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
228471d10453SEric Joyner 		      enum ice_adminq_opc opc, struct ice_sq_cd *cd)
228571d10453SEric Joyner {
228671d10453SEric Joyner 	struct ice_aqc_alloc_free_res_cmd *cmd;
228771d10453SEric Joyner 	struct ice_aq_desc desc;
228871d10453SEric Joyner 
228971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
229071d10453SEric Joyner 
229171d10453SEric Joyner 	cmd = &desc.params.sw_res_ctrl;
229271d10453SEric Joyner 
229371d10453SEric Joyner 	if (!buf)
229471d10453SEric Joyner 		return ICE_ERR_PARAM;
229571d10453SEric Joyner 
2296d08b8680SEric Joyner 	if (buf_size < FLEX_ARRAY_SIZE(buf, elem, num_entries))
229771d10453SEric Joyner 		return ICE_ERR_PARAM;
229871d10453SEric Joyner 
229971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
230071d10453SEric Joyner 
230171d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
230271d10453SEric Joyner 
230371d10453SEric Joyner 	cmd->num_entries = CPU_TO_LE16(num_entries);
230471d10453SEric Joyner 
230571d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
230671d10453SEric Joyner }
230771d10453SEric Joyner 
230871d10453SEric Joyner /**
230971d10453SEric Joyner  * ice_alloc_hw_res - allocate resource
231071d10453SEric Joyner  * @hw: pointer to the HW struct
231171d10453SEric Joyner  * @type: type of resource
231271d10453SEric Joyner  * @num: number of resources to allocate
231371d10453SEric Joyner  * @btm: allocate from bottom
231471d10453SEric Joyner  * @res: pointer to array that will receive the resources
231571d10453SEric Joyner  */
2316*f2635e84SEric Joyner int
231771d10453SEric Joyner ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
231871d10453SEric Joyner {
231971d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
232071d10453SEric Joyner 	u16 buf_len;
2321*f2635e84SEric Joyner 	int status;
232271d10453SEric Joyner 
23237d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
23247d7af7f8SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
232571d10453SEric Joyner 	if (!buf)
232671d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
232771d10453SEric Joyner 
232871d10453SEric Joyner 	/* Prepare buffer to allocate resource. */
232971d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
233071d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
233171d10453SEric Joyner 				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
233271d10453SEric Joyner 	if (btm)
233371d10453SEric Joyner 		buf->res_type |= CPU_TO_LE16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
233471d10453SEric Joyner 
233571d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
233671d10453SEric Joyner 				       ice_aqc_opc_alloc_res, NULL);
233771d10453SEric Joyner 	if (status)
233871d10453SEric Joyner 		goto ice_alloc_res_exit;
233971d10453SEric Joyner 
23407d7af7f8SEric Joyner 	ice_memcpy(res, buf->elem, sizeof(*buf->elem) * num,
234171d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
234271d10453SEric Joyner 
234371d10453SEric Joyner ice_alloc_res_exit:
234471d10453SEric Joyner 	ice_free(hw, buf);
234571d10453SEric Joyner 	return status;
234671d10453SEric Joyner }
234771d10453SEric Joyner 
234871d10453SEric Joyner /**
234971d10453SEric Joyner  * ice_free_hw_res - free allocated HW resource
235071d10453SEric Joyner  * @hw: pointer to the HW struct
235171d10453SEric Joyner  * @type: type of resource to free
235271d10453SEric Joyner  * @num: number of resources
235371d10453SEric Joyner  * @res: pointer to array that contains the resources to free
235471d10453SEric Joyner  */
2355*f2635e84SEric Joyner int ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
235671d10453SEric Joyner {
235771d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
235871d10453SEric Joyner 	u16 buf_len;
2359*f2635e84SEric Joyner 	int status;
236071d10453SEric Joyner 
23617d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
236271d10453SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
236371d10453SEric Joyner 	if (!buf)
236471d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
236571d10453SEric Joyner 
236671d10453SEric Joyner 	/* Prepare buffer to free resource. */
236771d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
236871d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type);
23697d7af7f8SEric Joyner 	ice_memcpy(buf->elem, res, sizeof(*buf->elem) * num,
237071d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
237171d10453SEric Joyner 
237271d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, num, buf, buf_len,
237371d10453SEric Joyner 				       ice_aqc_opc_free_res, NULL);
237471d10453SEric Joyner 	if (status)
237571d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
237671d10453SEric Joyner 
237771d10453SEric Joyner 	ice_free(hw, buf);
237871d10453SEric Joyner 	return status;
237971d10453SEric Joyner }
238071d10453SEric Joyner 
238171d10453SEric Joyner /**
238271d10453SEric Joyner  * ice_get_num_per_func - determine number of resources per PF
238371d10453SEric Joyner  * @hw: pointer to the HW structure
238471d10453SEric Joyner  * @max: value to be evenly split between each PF
238571d10453SEric Joyner  *
238671d10453SEric Joyner  * Determine the number of valid functions by going through the bitmap returned
238771d10453SEric Joyner  * from parsing capabilities and use this to calculate the number of resources
238871d10453SEric Joyner  * per PF based on the max value passed in.
238971d10453SEric Joyner  */
239071d10453SEric Joyner static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
239171d10453SEric Joyner {
239271d10453SEric Joyner 	u8 funcs;
239371d10453SEric Joyner 
239471d10453SEric Joyner #define ICE_CAPS_VALID_FUNCS_M	0xFF
239571d10453SEric Joyner 	funcs = ice_hweight8(hw->dev_caps.common_cap.valid_functions &
239671d10453SEric Joyner 			     ICE_CAPS_VALID_FUNCS_M);
239771d10453SEric Joyner 
239871d10453SEric Joyner 	if (!funcs)
239971d10453SEric Joyner 		return 0;
240071d10453SEric Joyner 
240171d10453SEric Joyner 	return max / funcs;
240271d10453SEric Joyner }
240371d10453SEric Joyner 
240471d10453SEric Joyner /**
240571d10453SEric Joyner  * ice_print_led_caps - print LED capabilities
240671d10453SEric Joyner  * @hw: pointer to the ice_hw instance
240771d10453SEric Joyner  * @caps: pointer to common caps instance
240871d10453SEric Joyner  * @prefix: string to prefix when printing
24099cf1841cSEric Joyner  * @dbg: set to indicate debug print
241071d10453SEric Joyner  */
241171d10453SEric Joyner static void
241271d10453SEric Joyner ice_print_led_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
24139cf1841cSEric Joyner 		   char const *prefix, bool dbg)
241471d10453SEric Joyner {
241571d10453SEric Joyner 	u8 i;
241671d10453SEric Joyner 
24179cf1841cSEric Joyner 	if (dbg)
2418*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: led_pin_num = %u\n", prefix,
241971d10453SEric Joyner 			  caps->led_pin_num);
242071d10453SEric Joyner 	else
2421*f2635e84SEric Joyner 		ice_info(hw, "%s: led_pin_num = %u\n", prefix,
242271d10453SEric Joyner 			 caps->led_pin_num);
242371d10453SEric Joyner 
242471d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_LED; i++) {
242571d10453SEric Joyner 		if (!caps->led[i])
242671d10453SEric Joyner 			continue;
242771d10453SEric Joyner 
24289cf1841cSEric Joyner 		if (dbg)
2429*f2635e84SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%u] = %u\n",
243071d10453SEric Joyner 				  prefix, i, caps->led[i]);
243171d10453SEric Joyner 		else
2432*f2635e84SEric Joyner 			ice_info(hw, "%s: led[%u] = %u\n", prefix, i,
243371d10453SEric Joyner 				 caps->led[i]);
243471d10453SEric Joyner 	}
243571d10453SEric Joyner }
243671d10453SEric Joyner 
243771d10453SEric Joyner /**
243871d10453SEric Joyner  * ice_print_sdp_caps - print SDP capabilities
243971d10453SEric Joyner  * @hw: pointer to the ice_hw instance
244071d10453SEric Joyner  * @caps: pointer to common caps instance
244171d10453SEric Joyner  * @prefix: string to prefix when printing
24429cf1841cSEric Joyner  * @dbg: set to indicate debug print
244371d10453SEric Joyner  */
244471d10453SEric Joyner static void
244571d10453SEric Joyner ice_print_sdp_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
24469cf1841cSEric Joyner 		   char const *prefix, bool dbg)
244771d10453SEric Joyner {
244871d10453SEric Joyner 	u8 i;
244971d10453SEric Joyner 
24509cf1841cSEric Joyner 	if (dbg)
2451*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sdp_pin_num = %u\n", prefix,
245271d10453SEric Joyner 			  caps->sdp_pin_num);
245371d10453SEric Joyner 	else
2454*f2635e84SEric Joyner 		ice_info(hw, "%s: sdp_pin_num = %u\n", prefix,
245571d10453SEric Joyner 			 caps->sdp_pin_num);
245671d10453SEric Joyner 
245771d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_SDP; i++) {
245871d10453SEric Joyner 		if (!caps->sdp[i])
245971d10453SEric Joyner 			continue;
246071d10453SEric Joyner 
24619cf1841cSEric Joyner 		if (dbg)
2462*f2635e84SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%u] = %u\n",
246371d10453SEric Joyner 				  prefix, i, caps->sdp[i]);
246471d10453SEric Joyner 		else
2465*f2635e84SEric Joyner 			ice_info(hw, "%s: sdp[%u] = %u\n", prefix,
246671d10453SEric Joyner 				 i, caps->sdp[i]);
246771d10453SEric Joyner 	}
246871d10453SEric Joyner }
246971d10453SEric Joyner 
247071d10453SEric Joyner /**
24717d7af7f8SEric Joyner  * ice_parse_common_caps - parse common device/function capabilities
247271d10453SEric Joyner  * @hw: pointer to the HW struct
24737d7af7f8SEric Joyner  * @caps: pointer to common capabilities structure
24747d7af7f8SEric Joyner  * @elem: the capability element to parse
24757d7af7f8SEric Joyner  * @prefix: message prefix for tracing capabilities
247671d10453SEric Joyner  *
24777d7af7f8SEric Joyner  * Given a capability element, extract relevant details into the common
24787d7af7f8SEric Joyner  * capability structure.
24797d7af7f8SEric Joyner  *
24807d7af7f8SEric Joyner  * Returns: true if the capability matches one of the common capability ids,
24817d7af7f8SEric Joyner  * false otherwise.
248271d10453SEric Joyner  */
24837d7af7f8SEric Joyner static bool
24847d7af7f8SEric Joyner ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
24857d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
248671d10453SEric Joyner {
24877d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(elem->logical_id);
24887d7af7f8SEric Joyner 	u32 phys_id = LE32_TO_CPU(elem->phys_id);
24897d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(elem->number);
24907d7af7f8SEric Joyner 	u16 cap = LE16_TO_CPU(elem->cap);
24917d7af7f8SEric Joyner 	bool found = true;
249271d10453SEric Joyner 
249371d10453SEric Joyner 	switch (cap) {
249471d10453SEric Joyner 	case ICE_AQC_CAPS_SWITCHING_MODE:
249571d10453SEric Joyner 		caps->switching_mode = number;
2496*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: switching_mode = %u\n", prefix,
249771d10453SEric Joyner 			  caps->switching_mode);
249871d10453SEric Joyner 		break;
249971d10453SEric Joyner 	case ICE_AQC_CAPS_MANAGEABILITY_MODE:
250071d10453SEric Joyner 		caps->mgmt_mode = number;
250171d10453SEric Joyner 		caps->mgmt_protocols_mctp = logical_id;
2502*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_mode = %u\n", prefix,
250371d10453SEric Joyner 			  caps->mgmt_mode);
2504*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_protocols_mctp = %u\n", prefix,
250571d10453SEric Joyner 			  caps->mgmt_protocols_mctp);
250671d10453SEric Joyner 		break;
250771d10453SEric Joyner 	case ICE_AQC_CAPS_OS2BMC:
250871d10453SEric Joyner 		caps->os2bmc = number;
2509*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: os2bmc = %u\n", prefix, caps->os2bmc);
251071d10453SEric Joyner 		break;
251171d10453SEric Joyner 	case ICE_AQC_CAPS_VALID_FUNCTIONS:
251271d10453SEric Joyner 		caps->valid_functions = number;
2513*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = 0x%x\n", prefix,
251471d10453SEric Joyner 			  caps->valid_functions);
251571d10453SEric Joyner 		break;
251671d10453SEric Joyner 	case ICE_AQC_CAPS_SRIOV:
251771d10453SEric Joyner 		caps->sr_iov_1_1 = (number == 1);
2518*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %u\n", prefix,
251971d10453SEric Joyner 			  caps->sr_iov_1_1);
252071d10453SEric Joyner 		break;
25219e54973fSEric Joyner 	case ICE_AQC_CAPS_VMDQ:
25229e54973fSEric Joyner 		caps->vmdq = (number == 1);
2523*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: vmdq = %u\n", prefix, caps->vmdq);
25249e54973fSEric Joyner 		break;
252571d10453SEric Joyner 	case ICE_AQC_CAPS_802_1QBG:
252671d10453SEric Joyner 		caps->evb_802_1_qbg = (number == 1);
2527*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbg = %u\n", prefix, number);
252871d10453SEric Joyner 		break;
252971d10453SEric Joyner 	case ICE_AQC_CAPS_802_1BR:
253071d10453SEric Joyner 		caps->evb_802_1_qbh = (number == 1);
2531*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbh = %u\n", prefix, number);
253271d10453SEric Joyner 		break;
253371d10453SEric Joyner 	case ICE_AQC_CAPS_DCB:
253471d10453SEric Joyner 		caps->dcb = (number == 1);
253571d10453SEric Joyner 		caps->active_tc_bitmap = logical_id;
253671d10453SEric Joyner 		caps->maxtc = phys_id;
2537*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %u\n", prefix, caps->dcb);
2538*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = 0x%x\n", prefix,
253971d10453SEric Joyner 			  caps->active_tc_bitmap);
2540*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %u\n", prefix, caps->maxtc);
254171d10453SEric Joyner 		break;
254271d10453SEric Joyner 	case ICE_AQC_CAPS_ISCSI:
254371d10453SEric Joyner 		caps->iscsi = (number == 1);
2544*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: iscsi = %u\n", prefix, caps->iscsi);
254571d10453SEric Joyner 		break;
254671d10453SEric Joyner 	case ICE_AQC_CAPS_RSS:
254771d10453SEric Joyner 		caps->rss_table_size = number;
254871d10453SEric Joyner 		caps->rss_table_entry_width = logical_id;
2549*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %u\n", prefix,
255071d10453SEric Joyner 			  caps->rss_table_size);
2551*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %u\n", prefix,
255271d10453SEric Joyner 			  caps->rss_table_entry_width);
255371d10453SEric Joyner 		break;
255471d10453SEric Joyner 	case ICE_AQC_CAPS_RXQS:
255571d10453SEric Joyner 		caps->num_rxq = number;
255671d10453SEric Joyner 		caps->rxq_first_id = phys_id;
2557*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %u\n", prefix,
255871d10453SEric Joyner 			  caps->num_rxq);
2559*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %u\n", prefix,
256071d10453SEric Joyner 			  caps->rxq_first_id);
256171d10453SEric Joyner 		break;
256271d10453SEric Joyner 	case ICE_AQC_CAPS_TXQS:
256371d10453SEric Joyner 		caps->num_txq = number;
256471d10453SEric Joyner 		caps->txq_first_id = phys_id;
2565*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %u\n", prefix,
256671d10453SEric Joyner 			  caps->num_txq);
2567*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %u\n", prefix,
256871d10453SEric Joyner 			  caps->txq_first_id);
256971d10453SEric Joyner 		break;
257071d10453SEric Joyner 	case ICE_AQC_CAPS_MSIX:
257171d10453SEric Joyner 		caps->num_msix_vectors = number;
257271d10453SEric Joyner 		caps->msix_vector_first_id = phys_id;
2573*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %u\n", prefix,
257471d10453SEric Joyner 			  caps->num_msix_vectors);
2575*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %u\n", prefix,
257671d10453SEric Joyner 			  caps->msix_vector_first_id);
257771d10453SEric Joyner 		break;
257871d10453SEric Joyner 	case ICE_AQC_CAPS_NVM_MGMT:
2579d08b8680SEric Joyner 		caps->sec_rev_disabled =
2580d08b8680SEric Joyner 			(number & ICE_NVM_MGMT_SEC_REV_DISABLED) ?
2581d08b8680SEric Joyner 			true : false;
2582d08b8680SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sec_rev_disabled = %d\n", prefix,
2583d08b8680SEric Joyner 			  caps->sec_rev_disabled);
2584d08b8680SEric Joyner 		caps->update_disabled =
2585d08b8680SEric Joyner 			(number & ICE_NVM_MGMT_UPDATE_DISABLED) ?
2586d08b8680SEric Joyner 			true : false;
2587d08b8680SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: update_disabled = %d\n", prefix,
2588d08b8680SEric Joyner 			  caps->update_disabled);
258971d10453SEric Joyner 		caps->nvm_unified_update =
259071d10453SEric Joyner 			(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
259171d10453SEric Joyner 			true : false;
25927d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
259371d10453SEric Joyner 			  caps->nvm_unified_update);
25949c30461dSEric Joyner 		caps->netlist_auth =
25959c30461dSEric Joyner 			(number & ICE_NVM_MGMT_NETLIST_AUTH_SUPPORT) ?
25969c30461dSEric Joyner 			true : false;
25979c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: netlist_auth = %d\n", prefix,
25989c30461dSEric Joyner 			  caps->netlist_auth);
259971d10453SEric Joyner 		break;
260071d10453SEric Joyner 	case ICE_AQC_CAPS_CEM:
260171d10453SEric Joyner 		caps->mgmt_cem = (number == 1);
2602*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_cem = %u\n", prefix,
260371d10453SEric Joyner 			  caps->mgmt_cem);
260471d10453SEric Joyner 		break;
26058a13362dSEric Joyner 	case ICE_AQC_CAPS_IWARP:
26068a13362dSEric Joyner 		caps->iwarp = (number == 1);
2607*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: iwarp = %u\n", prefix, caps->iwarp);
26088a13362dSEric Joyner 		break;
26098923de59SPiotr Kubaj 	case ICE_AQC_CAPS_ROCEV2_LAG:
26109e54973fSEric Joyner 		caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG);
2611*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n",
26128923de59SPiotr Kubaj 			  prefix, caps->roce_lag);
26138923de59SPiotr Kubaj 		break;
261471d10453SEric Joyner 	case ICE_AQC_CAPS_LED:
261571d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_LED) {
261671d10453SEric Joyner 			caps->led[phys_id] = true;
261771d10453SEric Joyner 			caps->led_pin_num++;
2618*f2635e84SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%u] = 1\n", prefix, phys_id);
261971d10453SEric Joyner 		}
262071d10453SEric Joyner 		break;
262171d10453SEric Joyner 	case ICE_AQC_CAPS_SDP:
262271d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_SDP) {
262371d10453SEric Joyner 			caps->sdp[phys_id] = true;
262471d10453SEric Joyner 			caps->sdp_pin_num++;
2625*f2635e84SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%u] = 1\n", prefix, phys_id);
262671d10453SEric Joyner 		}
262771d10453SEric Joyner 		break;
262871d10453SEric Joyner 	case ICE_AQC_CAPS_WR_CSR_PROT:
262971d10453SEric Joyner 		caps->wr_csr_prot = number;
263071d10453SEric Joyner 		caps->wr_csr_prot |= (u64)logical_id << 32;
26317d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wr_csr_prot = 0x%llX\n", prefix,
263271d10453SEric Joyner 			  (unsigned long long)caps->wr_csr_prot);
263371d10453SEric Joyner 		break;
263471d10453SEric Joyner 	case ICE_AQC_CAPS_WOL_PROXY:
263571d10453SEric Joyner 		caps->num_wol_proxy_fltr = number;
263671d10453SEric Joyner 		caps->wol_proxy_vsi_seid = logical_id;
263771d10453SEric Joyner 		caps->apm_wol_support = !!(phys_id & ICE_WOL_SUPPORT_M);
263871d10453SEric Joyner 		caps->acpi_prog_mthd = !!(phys_id &
263971d10453SEric Joyner 					  ICE_ACPI_PROG_MTHD_M);
264071d10453SEric Joyner 		caps->proxy_support = !!(phys_id & ICE_PROXY_SUPPORT_M);
2641*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_wol_proxy_fltr = %u\n", prefix,
264271d10453SEric Joyner 			  caps->num_wol_proxy_fltr);
2643*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wol_proxy_vsi_seid = %u\n", prefix,
264471d10453SEric Joyner 			  caps->wol_proxy_vsi_seid);
2645*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: apm_wol_support = %u\n",
264656429daeSEric Joyner 			  prefix, caps->apm_wol_support);
264771d10453SEric Joyner 		break;
264871d10453SEric Joyner 	case ICE_AQC_CAPS_MAX_MTU:
264971d10453SEric Joyner 		caps->max_mtu = number;
2650*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %u\n",
265171d10453SEric Joyner 			  prefix, caps->max_mtu);
265271d10453SEric Joyner 		break;
265356429daeSEric Joyner 	case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
265456429daeSEric Joyner 		caps->pcie_reset_avoidance = (number > 0);
265556429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
265656429daeSEric Joyner 			  "%s: pcie_reset_avoidance = %d\n", prefix,
265756429daeSEric Joyner 			  caps->pcie_reset_avoidance);
265856429daeSEric Joyner 		break;
265956429daeSEric Joyner 	case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
266056429daeSEric Joyner 		caps->reset_restrict_support = (number == 1);
266156429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
266256429daeSEric Joyner 			  "%s: reset_restrict_support = %d\n", prefix,
266356429daeSEric Joyner 			  caps->reset_restrict_support);
266456429daeSEric Joyner 		break;
266556429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0:
266656429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1:
266756429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2:
266856429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3:
266956429daeSEric Joyner 	{
26708923de59SPiotr Kubaj 		u8 index = (u8)(cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0);
267156429daeSEric Joyner 
267256429daeSEric Joyner 		caps->ext_topo_dev_img_ver_high[index] = number;
267356429daeSEric Joyner 		caps->ext_topo_dev_img_ver_low[index] = logical_id;
267456429daeSEric Joyner 		caps->ext_topo_dev_img_part_num[index] =
267556429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
267656429daeSEric Joyner 			ICE_EXT_TOPO_DEV_IMG_PART_NUM_S;
267756429daeSEric Joyner 		caps->ext_topo_dev_img_load_en[index] =
267856429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
267956429daeSEric Joyner 		caps->ext_topo_dev_img_prog_en[index] =
268056429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
26819c30461dSEric Joyner 		caps->ext_topo_dev_img_ver_schema[index] =
26829c30461dSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_VER_SCHEMA) != 0;
268356429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2684*f2635e84SEric Joyner 			  "%s: ext_topo_dev_img_ver_high[%d] = %u\n",
268556429daeSEric Joyner 			  prefix, index,
268656429daeSEric Joyner 			  caps->ext_topo_dev_img_ver_high[index]);
268756429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2688*f2635e84SEric Joyner 			  "%s: ext_topo_dev_img_ver_low[%d] = %u\n",
268956429daeSEric Joyner 			  prefix, index,
269056429daeSEric Joyner 			  caps->ext_topo_dev_img_ver_low[index]);
269156429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
2692*f2635e84SEric Joyner 			  "%s: ext_topo_dev_img_part_num[%d] = %u\n",
269356429daeSEric Joyner 			  prefix, index,
269456429daeSEric Joyner 			  caps->ext_topo_dev_img_part_num[index]);
269556429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
269656429daeSEric Joyner 			  "%s: ext_topo_dev_img_load_en[%d] = %d\n",
269756429daeSEric Joyner 			  prefix, index,
269856429daeSEric Joyner 			  caps->ext_topo_dev_img_load_en[index]);
269956429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
270056429daeSEric Joyner 			  "%s: ext_topo_dev_img_prog_en[%d] = %d\n",
270156429daeSEric Joyner 			  prefix, index,
270256429daeSEric Joyner 			  caps->ext_topo_dev_img_prog_en[index]);
27039c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
27049c30461dSEric Joyner 			  "%s: ext_topo_dev_img_ver_schema[%d] = %d\n",
27059c30461dSEric Joyner 			  prefix, index,
27069c30461dSEric Joyner 			  caps->ext_topo_dev_img_ver_schema[index]);
270756429daeSEric Joyner 		break;
270856429daeSEric Joyner 	}
27098923de59SPiotr Kubaj 	case ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE:
27108923de59SPiotr Kubaj 		caps->tx_sched_topo_comp_mode_en = (number == 1);
27118923de59SPiotr Kubaj 		break;
27128923de59SPiotr Kubaj 	case ICE_AQC_CAPS_DYN_FLATTENING:
27138923de59SPiotr Kubaj 		caps->dyn_flattening_en = (number == 1);
27148923de59SPiotr Kubaj 		ice_debug(hw, ICE_DBG_INIT, "%s: dyn_flattening_en = %d\n",
27158923de59SPiotr Kubaj 			  prefix, caps->dyn_flattening_en);
27168923de59SPiotr Kubaj 		break;
27179c30461dSEric Joyner 	case ICE_AQC_CAPS_OROM_RECOVERY_UPDATE:
27189c30461dSEric Joyner 		caps->orom_recovery_update = (number == 1);
27199c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: orom_recovery_update = %d\n",
27209c30461dSEric Joyner 			  prefix, caps->orom_recovery_update);
27219c30461dSEric Joyner 		break;
2722*f2635e84SEric Joyner 	case ICE_AQC_CAPS_NEXT_CLUSTER_ID:
2723*f2635e84SEric Joyner 		caps->next_cluster_id_support = (number == 1);
2724*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: next_cluster_id_support = %d\n",
2725*f2635e84SEric Joyner 			  prefix, caps->next_cluster_id_support);
2726*f2635e84SEric Joyner 		break;
272771d10453SEric Joyner 	default:
27287d7af7f8SEric Joyner 		/* Not one of the recognized common capabilities */
27297d7af7f8SEric Joyner 		found = false;
273071d10453SEric Joyner 	}
273171d10453SEric Joyner 
27327d7af7f8SEric Joyner 	return found;
27337d7af7f8SEric Joyner }
273471d10453SEric Joyner 
27357d7af7f8SEric Joyner /**
27367d7af7f8SEric Joyner  * ice_recalc_port_limited_caps - Recalculate port limited capabilities
27377d7af7f8SEric Joyner  * @hw: pointer to the HW structure
27387d7af7f8SEric Joyner  * @caps: pointer to capabilities structure to fix
27397d7af7f8SEric Joyner  *
27407d7af7f8SEric Joyner  * Re-calculate the capabilities that are dependent on the number of physical
27417d7af7f8SEric Joyner  * ports; i.e. some features are not supported or function differently on
27427d7af7f8SEric Joyner  * devices with more than 4 ports.
27437d7af7f8SEric Joyner  */
27447d7af7f8SEric Joyner static void
27457d7af7f8SEric Joyner ice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
27467d7af7f8SEric Joyner {
27477d7af7f8SEric Joyner 	/* This assumes device capabilities are always scanned before function
27487d7af7f8SEric Joyner 	 * capabilities during the initialization flow.
274971d10453SEric Joyner 	 */
275071d10453SEric Joyner 	if (hw->dev_caps.num_funcs > 4) {
275171d10453SEric Joyner 		/* Max 4 TCs per port */
275271d10453SEric Joyner 		caps->maxtc = 4;
2753*f2635e84SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %u (based on #ports)\n",
275471d10453SEric Joyner 			  caps->maxtc);
27558a13362dSEric Joyner 		if (caps->iwarp) {
27568a13362dSEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "forcing RDMA off\n");
27578a13362dSEric Joyner 			caps->iwarp = 0;
27588a13362dSEric Joyner 		}
27598a13362dSEric Joyner 
27608a13362dSEric Joyner 		/* print message only when processing device capabilities
27618a13362dSEric Joyner 		 * during initialization.
27628a13362dSEric Joyner 		 */
27638a13362dSEric Joyner 		if (caps == &hw->dev_caps.common_cap)
27648a13362dSEric Joyner 			ice_info(hw, "RDMA functionality is not available with the current device configuration.\n");
276571d10453SEric Joyner 	}
276671d10453SEric Joyner }
276771d10453SEric Joyner 
276871d10453SEric Joyner /**
27697d7af7f8SEric Joyner  * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
277071d10453SEric Joyner  * @hw: pointer to the HW struct
27717d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
27727d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
27737d7af7f8SEric Joyner  *
27747d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VF.
27757d7af7f8SEric Joyner  */
27767d7af7f8SEric Joyner static void
27777d7af7f8SEric Joyner ice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
27787d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
27797d7af7f8SEric Joyner {
27807d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
27817d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(cap->logical_id);
27827d7af7f8SEric Joyner 
27837d7af7f8SEric Joyner 	func_p->num_allocd_vfs = number;
27847d7af7f8SEric Joyner 	func_p->vf_base_id = logical_id;
2785*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %u\n",
27867d7af7f8SEric Joyner 		  func_p->num_allocd_vfs);
2787*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %u\n",
27887d7af7f8SEric Joyner 		  func_p->vf_base_id);
27897d7af7f8SEric Joyner }
27907d7af7f8SEric Joyner 
27917d7af7f8SEric Joyner /**
27927d7af7f8SEric Joyner  * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
27937d7af7f8SEric Joyner  * @hw: pointer to the HW struct
27947d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
27957d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
27967d7af7f8SEric Joyner  *
27977d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VSI.
27987d7af7f8SEric Joyner  */
27997d7af7f8SEric Joyner static void
28007d7af7f8SEric Joyner ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
28017d7af7f8SEric Joyner 			struct ice_aqc_list_caps_elem *cap)
28027d7af7f8SEric Joyner {
28037d7af7f8SEric Joyner 	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
2804*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %u\n",
28057d7af7f8SEric Joyner 		  LE32_TO_CPU(cap->number));
2806*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %u\n",
28077d7af7f8SEric Joyner 		  func_p->guar_num_vsi);
28087d7af7f8SEric Joyner }
28097d7af7f8SEric Joyner 
28107d7af7f8SEric Joyner /**
28117d7af7f8SEric Joyner  * ice_parse_func_caps - Parse function capabilities
28127d7af7f8SEric Joyner  * @hw: pointer to the HW struct
28137d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
28147d7af7f8SEric Joyner  * @buf: buffer containing the function capability records
28157d7af7f8SEric Joyner  * @cap_count: the number of capabilities
28167d7af7f8SEric Joyner  *
28177d7af7f8SEric Joyner  * Helper function to parse function (0x000A) capabilities list. For
28187d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
28197d7af7f8SEric Joyner  * ice_parse_common_caps.
28207d7af7f8SEric Joyner  *
28217d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
28227d7af7f8SEric Joyner  * data into the function capabilities structured.
28237d7af7f8SEric Joyner  */
28247d7af7f8SEric Joyner static void
28257d7af7f8SEric Joyner ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
28267d7af7f8SEric Joyner 		    void *buf, u32 cap_count)
28277d7af7f8SEric Joyner {
28287d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
28297d7af7f8SEric Joyner 	u32 i;
28307d7af7f8SEric Joyner 
28317d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
28327d7af7f8SEric Joyner 
28337d7af7f8SEric Joyner 	ice_memset(func_p, 0, sizeof(*func_p), ICE_NONDMA_MEM);
28347d7af7f8SEric Joyner 
28357d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
28367d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
28377d7af7f8SEric Joyner 		bool found;
28387d7af7f8SEric Joyner 
28397d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &func_p->common_cap,
28407d7af7f8SEric Joyner 					      &cap_resp[i], "func caps");
28417d7af7f8SEric Joyner 
28427d7af7f8SEric Joyner 		switch (cap) {
28437d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
28447d7af7f8SEric Joyner 			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
28457d7af7f8SEric Joyner 			break;
28467d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
28477d7af7f8SEric Joyner 			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
28487d7af7f8SEric Joyner 			break;
28497d7af7f8SEric Joyner 		default:
28507d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
28517d7af7f8SEric Joyner 			if (!found)
28527d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n",
28537d7af7f8SEric Joyner 					  i, cap);
28547d7af7f8SEric Joyner 			break;
28557d7af7f8SEric Joyner 		}
28567d7af7f8SEric Joyner 	}
28577d7af7f8SEric Joyner 
28587d7af7f8SEric Joyner 	ice_print_led_caps(hw, &func_p->common_cap, "func caps", true);
28597d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &func_p->common_cap, "func caps", true);
28607d7af7f8SEric Joyner 
28617d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
28627d7af7f8SEric Joyner }
28637d7af7f8SEric Joyner 
28647d7af7f8SEric Joyner /**
28657d7af7f8SEric Joyner  * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
28667d7af7f8SEric Joyner  * @hw: pointer to the HW struct
28677d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
28687d7af7f8SEric Joyner  * @cap: capability element to parse
28697d7af7f8SEric Joyner  *
28707d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
28717d7af7f8SEric Joyner  */
28727d7af7f8SEric Joyner static void
28737d7af7f8SEric Joyner ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
28747d7af7f8SEric Joyner 			      struct ice_aqc_list_caps_elem *cap)
28757d7af7f8SEric Joyner {
28767d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
28777d7af7f8SEric Joyner 
28787d7af7f8SEric Joyner 	dev_p->num_funcs = ice_hweight32(number);
2879*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %u\n",
28807d7af7f8SEric Joyner 		  dev_p->num_funcs);
288156429daeSEric Joyner 
28827d7af7f8SEric Joyner }
28837d7af7f8SEric Joyner 
28847d7af7f8SEric Joyner /**
28857d7af7f8SEric Joyner  * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
28867d7af7f8SEric Joyner  * @hw: pointer to the HW struct
28877d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
28887d7af7f8SEric Joyner  * @cap: capability element to parse
28897d7af7f8SEric Joyner  *
28907d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VF for device capabilities.
28917d7af7f8SEric Joyner  */
28927d7af7f8SEric Joyner static void
28937d7af7f8SEric Joyner ice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
28947d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *cap)
28957d7af7f8SEric Joyner {
28967d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
28977d7af7f8SEric Joyner 
28987d7af7f8SEric Joyner 	dev_p->num_vfs_exposed = number;
2899*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %u\n",
29007d7af7f8SEric Joyner 		  dev_p->num_vfs_exposed);
29017d7af7f8SEric Joyner }
29027d7af7f8SEric Joyner 
29037d7af7f8SEric Joyner /**
29047d7af7f8SEric Joyner  * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
29057d7af7f8SEric Joyner  * @hw: pointer to the HW struct
29067d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
29077d7af7f8SEric Joyner  * @cap: capability element to parse
29087d7af7f8SEric Joyner  *
29097d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VSI for device capabilities.
29107d7af7f8SEric Joyner  */
29117d7af7f8SEric Joyner static void
29127d7af7f8SEric Joyner ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
29137d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
29147d7af7f8SEric Joyner {
29157d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
29167d7af7f8SEric Joyner 
29177d7af7f8SEric Joyner 	dev_p->num_vsi_allocd_to_host = number;
2918*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %u\n",
29197d7af7f8SEric Joyner 		  dev_p->num_vsi_allocd_to_host);
29207d7af7f8SEric Joyner }
29217d7af7f8SEric Joyner 
29227d7af7f8SEric Joyner /**
29238923de59SPiotr Kubaj  * ice_parse_nac_topo_dev_caps - Parse ICE_AQC_CAPS_NAC_TOPOLOGY cap
29248923de59SPiotr Kubaj  * @hw: pointer to the HW struct
29258923de59SPiotr Kubaj  * @dev_p: pointer to device capabilities structure
29268923de59SPiotr Kubaj  * @cap: capability element to parse
29278923de59SPiotr Kubaj  *
29288923de59SPiotr Kubaj  * Parse ICE_AQC_CAPS_NAC_TOPOLOGY for device capabilities.
29298923de59SPiotr Kubaj  */
29308923de59SPiotr Kubaj static void
29318923de59SPiotr Kubaj ice_parse_nac_topo_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
29328923de59SPiotr Kubaj 			    struct ice_aqc_list_caps_elem *cap)
29338923de59SPiotr Kubaj {
29348923de59SPiotr Kubaj 	dev_p->nac_topo.mode = LE32_TO_CPU(cap->number);
29358923de59SPiotr Kubaj 	dev_p->nac_topo.id = LE32_TO_CPU(cap->phys_id) & ICE_NAC_TOPO_ID_M;
29368923de59SPiotr Kubaj 
2937*f2635e84SEric Joyner 	ice_info(hw, "PF is configured in %s mode with IP instance ID %u\n",
2938*f2635e84SEric Joyner 		 (dev_p->nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) ?
2939*f2635e84SEric Joyner 		 "primary" : "secondary", dev_p->nac_topo.id);
29409e54973fSEric Joyner 
29418923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology is_primary = %d\n",
29428923de59SPiotr Kubaj 		  !!(dev_p->nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M));
29438923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology is_dual = %d\n",
29448923de59SPiotr Kubaj 		  !!(dev_p->nac_topo.mode & ICE_NAC_TOPO_DUAL_M));
2945*f2635e84SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology id = %u\n",
29468923de59SPiotr Kubaj 		  dev_p->nac_topo.id);
29478923de59SPiotr Kubaj }
29488923de59SPiotr Kubaj 
29498923de59SPiotr Kubaj /**
29509c30461dSEric Joyner  * ice_parse_sensor_reading_cap - Parse ICE_AQC_CAPS_SENSOR_READING cap
29519c30461dSEric Joyner  * @hw: pointer to the HW struct
29529c30461dSEric Joyner  * @dev_p: pointer to device capabilities structure
29539c30461dSEric Joyner  * @cap: capability element to parse
29549c30461dSEric Joyner  *
29559c30461dSEric Joyner  * Parse ICE_AQC_CAPS_SENSOR_READING for device capability for reading
29569c30461dSEric Joyner  * enabled sensors.
29579c30461dSEric Joyner  */
29589c30461dSEric Joyner static void
29599c30461dSEric Joyner ice_parse_sensor_reading_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
29609c30461dSEric Joyner 			     struct ice_aqc_list_caps_elem *cap)
29619c30461dSEric Joyner {
29629c30461dSEric Joyner 	dev_p->supported_sensors = LE32_TO_CPU(cap->number);
29639c30461dSEric Joyner 
29649c30461dSEric Joyner 	ice_debug(hw, ICE_DBG_INIT,
29659c30461dSEric Joyner 		  "dev caps: supported sensors (bitmap) = 0x%x\n",
29669c30461dSEric Joyner 		  dev_p->supported_sensors);
29679c30461dSEric Joyner }
29689c30461dSEric Joyner 
29699c30461dSEric Joyner /**
29707d7af7f8SEric Joyner  * ice_parse_dev_caps - Parse device capabilities
29717d7af7f8SEric Joyner  * @hw: pointer to the HW struct
29727d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
29737d7af7f8SEric Joyner  * @buf: buffer containing the device capability records
29747d7af7f8SEric Joyner  * @cap_count: the number of capabilities
29757d7af7f8SEric Joyner  *
29767d7af7f8SEric Joyner  * Helper device to parse device (0x000B) capabilities list. For
29777d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
29787d7af7f8SEric Joyner  * ice_parse_common_caps.
29797d7af7f8SEric Joyner  *
29807d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
29817d7af7f8SEric Joyner  * data into the device capabilities structured.
29827d7af7f8SEric Joyner  */
29837d7af7f8SEric Joyner static void
29847d7af7f8SEric Joyner ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
29857d7af7f8SEric Joyner 		   void *buf, u32 cap_count)
29867d7af7f8SEric Joyner {
29877d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
29887d7af7f8SEric Joyner 	u32 i;
29897d7af7f8SEric Joyner 
29907d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
29917d7af7f8SEric Joyner 
29927d7af7f8SEric Joyner 	ice_memset(dev_p, 0, sizeof(*dev_p), ICE_NONDMA_MEM);
29937d7af7f8SEric Joyner 
29947d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
29957d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
29967d7af7f8SEric Joyner 		bool found;
29977d7af7f8SEric Joyner 
29987d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &dev_p->common_cap,
29997d7af7f8SEric Joyner 					      &cap_resp[i], "dev caps");
30007d7af7f8SEric Joyner 
30017d7af7f8SEric Joyner 		switch (cap) {
30027d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VALID_FUNCTIONS:
30037d7af7f8SEric Joyner 			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
30047d7af7f8SEric Joyner 			break;
30057d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
30067d7af7f8SEric Joyner 			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
30077d7af7f8SEric Joyner 			break;
30087d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
30097d7af7f8SEric Joyner 			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
30107d7af7f8SEric Joyner 			break;
30118923de59SPiotr Kubaj 		case ICE_AQC_CAPS_NAC_TOPOLOGY:
30128923de59SPiotr Kubaj 			ice_parse_nac_topo_dev_caps(hw, dev_p, &cap_resp[i]);
30138923de59SPiotr Kubaj 			break;
30149c30461dSEric Joyner 		case ICE_AQC_CAPS_SENSOR_READING:
30159c30461dSEric Joyner 			ice_parse_sensor_reading_cap(hw, dev_p, &cap_resp[i]);
30169c30461dSEric Joyner 			break;
30177d7af7f8SEric Joyner 		default:
30187d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
30197d7af7f8SEric Joyner 			if (!found)
3020*f2635e84SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%u]: 0x%x\n",
30217d7af7f8SEric Joyner 					  i, cap);
30227d7af7f8SEric Joyner 			break;
30237d7af7f8SEric Joyner 		}
30247d7af7f8SEric Joyner 	}
30257d7af7f8SEric Joyner 
30267d7af7f8SEric Joyner 	ice_print_led_caps(hw, &dev_p->common_cap, "dev caps", true);
30277d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &dev_p->common_cap, "dev caps", true);
30287d7af7f8SEric Joyner 
30297d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
30307d7af7f8SEric Joyner }
30317d7af7f8SEric Joyner 
30327d7af7f8SEric Joyner /**
3033*f2635e84SEric Joyner  * ice_aq_get_netlist_node
3034*f2635e84SEric Joyner  * @hw: pointer to the hw struct
3035*f2635e84SEric Joyner  * @cmd: get_link_topo AQ structure
3036*f2635e84SEric Joyner  * @node_part_number: output node part number if node found
3037*f2635e84SEric Joyner  * @node_handle: output node handle parameter if node found
3038*f2635e84SEric Joyner  */
3039*f2635e84SEric Joyner int
3040*f2635e84SEric Joyner ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
3041*f2635e84SEric Joyner 			u8 *node_part_number, u16 *node_handle)
3042*f2635e84SEric Joyner {
3043*f2635e84SEric Joyner 	struct ice_aq_desc desc;
3044*f2635e84SEric Joyner 
3045*f2635e84SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
3046*f2635e84SEric Joyner 	desc.params.get_link_topo = *cmd;
3047*f2635e84SEric Joyner 
3048*f2635e84SEric Joyner 	if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL))
3049*f2635e84SEric Joyner 		return ICE_ERR_NOT_SUPPORTED;
3050*f2635e84SEric Joyner 
3051*f2635e84SEric Joyner 	if (node_handle)
3052*f2635e84SEric Joyner 		*node_handle =
3053*f2635e84SEric Joyner 			LE16_TO_CPU(desc.params.get_link_topo.addr.handle);
3054*f2635e84SEric Joyner 	if (node_part_number)
3055*f2635e84SEric Joyner 		*node_part_number = desc.params.get_link_topo.node_part_num;
3056*f2635e84SEric Joyner 
3057*f2635e84SEric Joyner 	return 0;
3058*f2635e84SEric Joyner }
3059*f2635e84SEric Joyner 
3060*f2635e84SEric Joyner #define MAX_NETLIST_SIZE 10
3061*f2635e84SEric Joyner /**
3062*f2635e84SEric Joyner  * ice_find_netlist_node
3063*f2635e84SEric Joyner  * @hw: pointer to the hw struct
3064*f2635e84SEric Joyner  * @node_type_ctx: type of netlist node to look for
3065*f2635e84SEric Joyner  * @node_part_number: node part number to look for
3066*f2635e84SEric Joyner  * @node_handle: output parameter if node found - optional
3067*f2635e84SEric Joyner  *
3068*f2635e84SEric Joyner  * Scan the netlist for a node handle of the given node type and part number.
3069*f2635e84SEric Joyner  *
3070*f2635e84SEric Joyner  * If node_handle is non-NULL it will be modified on function exit. It is only
3071*f2635e84SEric Joyner  * valid if the function returns zero, and should be ignored on any non-zero
3072*f2635e84SEric Joyner  * return value.
3073*f2635e84SEric Joyner  *
3074*f2635e84SEric Joyner  * Returns: 0 if the node is found, ICE_ERR_DOES_NOT_EXIST if no handle was
3075*f2635e84SEric Joyner  * found, and an error code on failure to access the AQ.
3076*f2635e84SEric Joyner  */
3077*f2635e84SEric Joyner int
3078*f2635e84SEric Joyner ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number,
3079*f2635e84SEric Joyner 		      u16 *node_handle)
3080*f2635e84SEric Joyner {
3081*f2635e84SEric Joyner 	u8 idx;
3082*f2635e84SEric Joyner 
3083*f2635e84SEric Joyner 	for (idx = 0; idx < MAX_NETLIST_SIZE; idx++) {
3084*f2635e84SEric Joyner 		struct ice_aqc_get_link_topo cmd;
3085*f2635e84SEric Joyner 		u8 rec_node_part_number;
3086*f2635e84SEric Joyner 		int status;
3087*f2635e84SEric Joyner 
3088*f2635e84SEric Joyner 		memset(&cmd, 0, sizeof(cmd));
3089*f2635e84SEric Joyner 
3090*f2635e84SEric Joyner 		cmd.addr.topo_params.node_type_ctx =
3091*f2635e84SEric Joyner 			(node_type_ctx << ICE_AQC_LINK_TOPO_NODE_TYPE_S);
3092*f2635e84SEric Joyner 		cmd.addr.topo_params.index = idx;
3093*f2635e84SEric Joyner 
3094*f2635e84SEric Joyner 		status = ice_aq_get_netlist_node(hw, &cmd,
3095*f2635e84SEric Joyner 						 &rec_node_part_number,
3096*f2635e84SEric Joyner 						 node_handle);
3097*f2635e84SEric Joyner 		if (status)
3098*f2635e84SEric Joyner 			return status;
3099*f2635e84SEric Joyner 
3100*f2635e84SEric Joyner 		if (rec_node_part_number == node_part_number)
3101*f2635e84SEric Joyner 			return 0;
3102*f2635e84SEric Joyner 	}
3103*f2635e84SEric Joyner 
3104*f2635e84SEric Joyner 	return ICE_ERR_DOES_NOT_EXIST;
3105*f2635e84SEric Joyner }
3106*f2635e84SEric Joyner 
3107*f2635e84SEric Joyner /**
31087d7af7f8SEric Joyner  * ice_aq_list_caps - query function/device capabilities
31097d7af7f8SEric Joyner  * @hw: pointer to the HW struct
31107d7af7f8SEric Joyner  * @buf: a buffer to hold the capabilities
31117d7af7f8SEric Joyner  * @buf_size: size of the buffer
31127d7af7f8SEric Joyner  * @cap_count: if not NULL, set to the number of capabilities reported
31137d7af7f8SEric Joyner  * @opc: capabilities type to discover, device or function
311471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
311571d10453SEric Joyner  *
31167d7af7f8SEric Joyner  * Get the function (0x000A) or device (0x000B) capabilities description from
31177d7af7f8SEric Joyner  * firmware and store it in the buffer.
31187d7af7f8SEric Joyner  *
31197d7af7f8SEric Joyner  * If the cap_count pointer is not NULL, then it is set to the number of
31207d7af7f8SEric Joyner  * capabilities firmware will report. Note that if the buffer size is too
31217d7af7f8SEric Joyner  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
31227d7af7f8SEric Joyner  * cap_count will still be updated in this case. It is recommended that the
31237d7af7f8SEric Joyner  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
31247d7af7f8SEric Joyner  * firmware could return) to avoid this.
312571d10453SEric Joyner  */
3126*f2635e84SEric Joyner static int
31277d7af7f8SEric Joyner ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
312871d10453SEric Joyner 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
312971d10453SEric Joyner {
313071d10453SEric Joyner 	struct ice_aqc_list_caps *cmd;
313171d10453SEric Joyner 	struct ice_aq_desc desc;
3132*f2635e84SEric Joyner 	int status;
313371d10453SEric Joyner 
313471d10453SEric Joyner 	cmd = &desc.params.get_cap;
313571d10453SEric Joyner 
313671d10453SEric Joyner 	if (opc != ice_aqc_opc_list_func_caps &&
313771d10453SEric Joyner 	    opc != ice_aqc_opc_list_dev_caps)
313871d10453SEric Joyner 		return ICE_ERR_PARAM;
313971d10453SEric Joyner 
314071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
314171d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
31427d7af7f8SEric Joyner 
31437d7af7f8SEric Joyner 	if (cap_count)
314471d10453SEric Joyner 		*cap_count = LE32_TO_CPU(cmd->count);
31457d7af7f8SEric Joyner 
314671d10453SEric Joyner 	return status;
314771d10453SEric Joyner }
314871d10453SEric Joyner 
314971d10453SEric Joyner /**
31507d7af7f8SEric Joyner  * ice_discover_dev_caps - Read and extract device capabilities
315171d10453SEric Joyner  * @hw: pointer to the hardware structure
31527d7af7f8SEric Joyner  * @dev_caps: pointer to device capabilities structure
31537d7af7f8SEric Joyner  *
31547d7af7f8SEric Joyner  * Read the device capabilities and extract them into the dev_caps structure
31557d7af7f8SEric Joyner  * for later use.
315671d10453SEric Joyner  */
3157*f2635e84SEric Joyner static int
31587d7af7f8SEric Joyner ice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
315971d10453SEric Joyner {
31607d7af7f8SEric Joyner 	u32 cap_count = 0;
316171d10453SEric Joyner 	void *cbuf;
3162*f2635e84SEric Joyner 	int status;
316371d10453SEric Joyner 
31647d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
316571d10453SEric Joyner 	if (!cbuf)
316671d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
316771d10453SEric Joyner 
31687d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
31697d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
31707d7af7f8SEric Joyner 	 * possible size that firmware can return.
31717d7af7f8SEric Joyner 	 */
31727d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
31737d7af7f8SEric Joyner 
31747d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
31757d7af7f8SEric Joyner 				  ice_aqc_opc_list_dev_caps, NULL);
31767d7af7f8SEric Joyner 	if (!status)
31777d7af7f8SEric Joyner 		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
317871d10453SEric Joyner 	ice_free(hw, cbuf);
317971d10453SEric Joyner 
31807d7af7f8SEric Joyner 	return status;
31817d7af7f8SEric Joyner }
318271d10453SEric Joyner 
31837d7af7f8SEric Joyner /**
31847d7af7f8SEric Joyner  * ice_discover_func_caps - Read and extract function capabilities
31857d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
31867d7af7f8SEric Joyner  * @func_caps: pointer to function capabilities structure
31877d7af7f8SEric Joyner  *
31887d7af7f8SEric Joyner  * Read the function capabilities and extract them into the func_caps structure
31897d7af7f8SEric Joyner  * for later use.
31907d7af7f8SEric Joyner  */
3191*f2635e84SEric Joyner static int
31927d7af7f8SEric Joyner ice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
31937d7af7f8SEric Joyner {
31947d7af7f8SEric Joyner 	u32 cap_count = 0;
31957d7af7f8SEric Joyner 	void *cbuf;
3196*f2635e84SEric Joyner 	int status;
31977d7af7f8SEric Joyner 
31987d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
31997d7af7f8SEric Joyner 	if (!cbuf)
32007d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
32017d7af7f8SEric Joyner 
32027d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
32037d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
32047d7af7f8SEric Joyner 	 * possible size that firmware can return.
32057d7af7f8SEric Joyner 	 */
32067d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
32077d7af7f8SEric Joyner 
32087d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
32097d7af7f8SEric Joyner 				  ice_aqc_opc_list_func_caps, NULL);
32107d7af7f8SEric Joyner 	if (!status)
32117d7af7f8SEric Joyner 		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
32127d7af7f8SEric Joyner 	ice_free(hw, cbuf);
321371d10453SEric Joyner 
321471d10453SEric Joyner 	return status;
321571d10453SEric Joyner }
321671d10453SEric Joyner 
321771d10453SEric Joyner /**
321871d10453SEric Joyner  * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
321971d10453SEric Joyner  * @hw: pointer to the hardware structure
322071d10453SEric Joyner  */
322171d10453SEric Joyner void ice_set_safe_mode_caps(struct ice_hw *hw)
322271d10453SEric Joyner {
322371d10453SEric Joyner 	struct ice_hw_func_caps *func_caps = &hw->func_caps;
322471d10453SEric Joyner 	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
3225d08b8680SEric Joyner 	struct ice_hw_common_caps cached_caps;
322671d10453SEric Joyner 	u32 num_funcs;
322771d10453SEric Joyner 
322871d10453SEric Joyner 	/* cache some func_caps values that should be restored after memset */
3229d08b8680SEric Joyner 	cached_caps = func_caps->common_cap;
323071d10453SEric Joyner 
323171d10453SEric Joyner 	/* unset func capabilities */
323271d10453SEric Joyner 	memset(func_caps, 0, sizeof(*func_caps));
323371d10453SEric Joyner 
3234d08b8680SEric Joyner #define ICE_RESTORE_FUNC_CAP(name) \
3235d08b8680SEric Joyner 	func_caps->common_cap.name = cached_caps.name
3236d08b8680SEric Joyner 
323771d10453SEric Joyner 	/* restore cached values */
3238d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(valid_functions);
3239d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(txq_first_id);
3240d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(rxq_first_id);
3241d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
3242d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(max_mtu);
3243d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(nvm_unified_update);
324471d10453SEric Joyner 
324571d10453SEric Joyner 	/* one Tx and one Rx queue in safe mode */
324671d10453SEric Joyner 	func_caps->common_cap.num_rxq = 1;
324771d10453SEric Joyner 	func_caps->common_cap.num_txq = 1;
324871d10453SEric Joyner 
324971d10453SEric Joyner 	/* two MSIX vectors, one for traffic and one for misc causes */
325071d10453SEric Joyner 	func_caps->common_cap.num_msix_vectors = 2;
325171d10453SEric Joyner 	func_caps->guar_num_vsi = 1;
325271d10453SEric Joyner 
325371d10453SEric Joyner 	/* cache some dev_caps values that should be restored after memset */
3254d08b8680SEric Joyner 	cached_caps = dev_caps->common_cap;
325571d10453SEric Joyner 	num_funcs = dev_caps->num_funcs;
325671d10453SEric Joyner 
325771d10453SEric Joyner 	/* unset dev capabilities */
325871d10453SEric Joyner 	memset(dev_caps, 0, sizeof(*dev_caps));
325971d10453SEric Joyner 
3260d08b8680SEric Joyner #define ICE_RESTORE_DEV_CAP(name) \
3261d08b8680SEric Joyner 	dev_caps->common_cap.name = cached_caps.name
3262d08b8680SEric Joyner 
326371d10453SEric Joyner 	/* restore cached values */
3264d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(valid_functions);
3265d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(txq_first_id);
3266d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(rxq_first_id);
3267d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(msix_vector_first_id);
3268d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(max_mtu);
3269d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(nvm_unified_update);
327071d10453SEric Joyner 	dev_caps->num_funcs = num_funcs;
327171d10453SEric Joyner 
327271d10453SEric Joyner 	/* one Tx and one Rx queue per function in safe mode */
327371d10453SEric Joyner 	dev_caps->common_cap.num_rxq = num_funcs;
327471d10453SEric Joyner 	dev_caps->common_cap.num_txq = num_funcs;
327571d10453SEric Joyner 
327671d10453SEric Joyner 	/* two MSIX vectors per function */
327771d10453SEric Joyner 	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
327871d10453SEric Joyner }
327971d10453SEric Joyner 
328071d10453SEric Joyner /**
328171d10453SEric Joyner  * ice_get_caps - get info about the HW
328271d10453SEric Joyner  * @hw: pointer to the hardware structure
328371d10453SEric Joyner  */
3284*f2635e84SEric Joyner int ice_get_caps(struct ice_hw *hw)
328571d10453SEric Joyner {
3286*f2635e84SEric Joyner 	int status;
328771d10453SEric Joyner 
32887d7af7f8SEric Joyner 	status = ice_discover_dev_caps(hw, &hw->dev_caps);
32897d7af7f8SEric Joyner 	if (status)
329071d10453SEric Joyner 		return status;
32917d7af7f8SEric Joyner 
32927d7af7f8SEric Joyner 	return ice_discover_func_caps(hw, &hw->func_caps);
329371d10453SEric Joyner }
329471d10453SEric Joyner 
329571d10453SEric Joyner /**
329671d10453SEric Joyner  * ice_aq_manage_mac_write - manage MAC address write command
329771d10453SEric Joyner  * @hw: pointer to the HW struct
329871d10453SEric Joyner  * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
329971d10453SEric Joyner  * @flags: flags to control write behavior
330071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
330171d10453SEric Joyner  *
330271d10453SEric Joyner  * This function is used to write MAC address to the NVM (0x0108).
330371d10453SEric Joyner  */
3304*f2635e84SEric Joyner int
330571d10453SEric Joyner ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
330671d10453SEric Joyner 			struct ice_sq_cd *cd)
330771d10453SEric Joyner {
330871d10453SEric Joyner 	struct ice_aqc_manage_mac_write *cmd;
330971d10453SEric Joyner 	struct ice_aq_desc desc;
331071d10453SEric Joyner 
331171d10453SEric Joyner 	cmd = &desc.params.mac_write;
331271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
331371d10453SEric Joyner 
331471d10453SEric Joyner 	cmd->flags = flags;
3315d08b8680SEric Joyner 	ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_NONDMA);
331671d10453SEric Joyner 
331771d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
331871d10453SEric Joyner }
331971d10453SEric Joyner 
332071d10453SEric Joyner /**
332171d10453SEric Joyner  * ice_aq_clear_pxe_mode
332271d10453SEric Joyner  * @hw: pointer to the HW struct
332371d10453SEric Joyner  *
332471d10453SEric Joyner  * Tell the firmware that the driver is taking over from PXE (0x0110).
332571d10453SEric Joyner  */
3326*f2635e84SEric Joyner static int ice_aq_clear_pxe_mode(struct ice_hw *hw)
332771d10453SEric Joyner {
332871d10453SEric Joyner 	struct ice_aq_desc desc;
332971d10453SEric Joyner 
333071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
333171d10453SEric Joyner 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
333271d10453SEric Joyner 
333371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
333471d10453SEric Joyner }
333571d10453SEric Joyner 
333671d10453SEric Joyner /**
333771d10453SEric Joyner  * ice_clear_pxe_mode - clear pxe operations mode
333871d10453SEric Joyner  * @hw: pointer to the HW struct
333971d10453SEric Joyner  *
334071d10453SEric Joyner  * Make sure all PXE mode settings are cleared, including things
334171d10453SEric Joyner  * like descriptor fetch/write-back mode.
334271d10453SEric Joyner  */
334371d10453SEric Joyner void ice_clear_pxe_mode(struct ice_hw *hw)
334471d10453SEric Joyner {
334571d10453SEric Joyner 	if (ice_check_sq_alive(hw, &hw->adminq))
334671d10453SEric Joyner 		ice_aq_clear_pxe_mode(hw);
334771d10453SEric Joyner }
334871d10453SEric Joyner 
334971d10453SEric Joyner /**
33509e54973fSEric Joyner  * ice_aq_set_port_params - set physical port parameters
335171d10453SEric Joyner  * @pi: pointer to the port info struct
335271d10453SEric Joyner  * @bad_frame_vsi: defines the VSI to which bad frames are forwarded
335371d10453SEric Joyner  * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI
335471d10453SEric Joyner  * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded
335571d10453SEric Joyner  * @double_vlan: if set double VLAN is enabled
335671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
335771d10453SEric Joyner  *
335871d10453SEric Joyner  * Set Physical port parameters (0x0203)
335971d10453SEric Joyner  */
3360*f2635e84SEric Joyner int
336171d10453SEric Joyner ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
336271d10453SEric Joyner 		       bool save_bad_pac, bool pad_short_pac, bool double_vlan,
336371d10453SEric Joyner 		       struct ice_sq_cd *cd)
336471d10453SEric Joyner {
336571d10453SEric Joyner 	struct ice_aqc_set_port_params *cmd;
336671d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
336771d10453SEric Joyner 	struct ice_aq_desc desc;
336871d10453SEric Joyner 	u16 cmd_flags = 0;
336971d10453SEric Joyner 
337071d10453SEric Joyner 	cmd = &desc.params.set_port_params;
337171d10453SEric Joyner 
337271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
3373*f2635e84SEric Joyner 	cmd->lb_mode = pi->loopback_mode |
3374*f2635e84SEric Joyner 	               ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_VALID;
337571d10453SEric Joyner 	cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi);
337671d10453SEric Joyner 	if (save_bad_pac)
337771d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS;
337871d10453SEric Joyner 	if (pad_short_pac)
337971d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS;
338071d10453SEric Joyner 	if (double_vlan)
338171d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
338271d10453SEric Joyner 	cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
338371d10453SEric Joyner 
338471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
338571d10453SEric Joyner }
338671d10453SEric Joyner 
338771d10453SEric Joyner /**
338856429daeSEric Joyner  * ice_is_100m_speed_supported
338956429daeSEric Joyner  * @hw: pointer to the HW struct
339056429daeSEric Joyner  *
339156429daeSEric Joyner  * returns true if 100M speeds are supported by the device,
339256429daeSEric Joyner  * false otherwise.
339356429daeSEric Joyner  */
339456429daeSEric Joyner bool ice_is_100m_speed_supported(struct ice_hw *hw)
339556429daeSEric Joyner {
339656429daeSEric Joyner 	switch (hw->device_id) {
339756429daeSEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
339856429daeSEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
339956429daeSEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
34008923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_SGMII:
340156429daeSEric Joyner 		return true;
340256429daeSEric Joyner 	default:
340356429daeSEric Joyner 		return false;
340456429daeSEric Joyner 	}
340556429daeSEric Joyner }
340656429daeSEric Joyner 
340756429daeSEric Joyner /**
340871d10453SEric Joyner  * ice_get_link_speed_based_on_phy_type - returns link speed
340971d10453SEric Joyner  * @phy_type_low: lower part of phy_type
341071d10453SEric Joyner  * @phy_type_high: higher part of phy_type
341171d10453SEric Joyner  *
341271d10453SEric Joyner  * This helper function will convert an entry in PHY type structure
341371d10453SEric Joyner  * [phy_type_low, phy_type_high] to its corresponding link speed.
341471d10453SEric Joyner  * Note: In the structure of [phy_type_low, phy_type_high], there should
341571d10453SEric Joyner  * be one bit set, as this function will convert one PHY type to its
341671d10453SEric Joyner  * speed.
34179dc2f6e2SEric Joyner  * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
34189dc2f6e2SEric Joyner  * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
341971d10453SEric Joyner  */
342071d10453SEric Joyner static u16
342171d10453SEric Joyner ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
342271d10453SEric Joyner {
342371d10453SEric Joyner 	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
342471d10453SEric Joyner 	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
342571d10453SEric Joyner 
342671d10453SEric Joyner 	switch (phy_type_low) {
342771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100BASE_TX:
342871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100M_SGMII:
342971d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
343071d10453SEric Joyner 		break;
343171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_T:
343271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_SX:
343371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_LX:
343471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_KX:
343571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1G_SGMII:
343671d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
343771d10453SEric Joyner 		break;
343871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_T:
343971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_X:
344071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_KX:
344171d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
344271d10453SEric Joyner 		break;
344371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_T:
344471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_KR:
344571d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
344671d10453SEric Joyner 		break;
344771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_T:
344871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
344971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_SR:
345071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_LR:
345171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
345271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
345371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
345471d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
345571d10453SEric Joyner 		break;
345671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_T:
345771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR:
345871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
345971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
346071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_SR:
346171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_LR:
346271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR:
346371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
346471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
346571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
346671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
346771d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
346871d10453SEric Joyner 		break;
346971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
347071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
347171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
347271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
347371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
347471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI:
347571d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
347671d10453SEric Joyner 		break;
347771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
347871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
347971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
348071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
348171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
348271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2:
348371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
348471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2:
348571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CP:
348671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR:
348771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_FR:
348871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR:
348971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
349071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
349171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1:
349271d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
349371d10453SEric Joyner 		break;
349471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
349571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
349671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
349771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
349871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
349971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4:
350071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
350171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4:
350271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
350371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
350471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
350571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
350671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_DR:
350771d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
350871d10453SEric Joyner 		break;
350971d10453SEric Joyner 	default:
351071d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
351171d10453SEric Joyner 		break;
351271d10453SEric Joyner 	}
351371d10453SEric Joyner 
351471d10453SEric Joyner 	switch (phy_type_high) {
351571d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
351671d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
351771d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
351871d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
351971d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2:
352071d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
352171d10453SEric Joyner 		break;
3522*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_CR4_PAM4:
3523*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_SR4:
3524*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_FR4:
3525*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_LR4:
3526*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_DR4:
3527*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_KR4_PAM4:
3528*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_AUI4_AOC_ACC:
3529*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_AUI4:
3530*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_AUI8_AOC_ACC:
3531*f2635e84SEric Joyner 	case ICE_PHY_TYPE_HIGH_200G_AUI8:
3532*f2635e84SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_200GB;
3533*f2635e84SEric Joyner 		break;
353471d10453SEric Joyner 	default:
353571d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
353671d10453SEric Joyner 		break;
353771d10453SEric Joyner 	}
353871d10453SEric Joyner 
353971d10453SEric Joyner 	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
354071d10453SEric Joyner 	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
354171d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
354271d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
354371d10453SEric Joyner 		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
354471d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
354571d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
354671d10453SEric Joyner 		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
354771d10453SEric Joyner 		return speed_phy_type_low;
354871d10453SEric Joyner 	else
354971d10453SEric Joyner 		return speed_phy_type_high;
355071d10453SEric Joyner }
355171d10453SEric Joyner 
355271d10453SEric Joyner /**
355371d10453SEric Joyner  * ice_update_phy_type
355471d10453SEric Joyner  * @phy_type_low: pointer to the lower part of phy_type
355571d10453SEric Joyner  * @phy_type_high: pointer to the higher part of phy_type
355671d10453SEric Joyner  * @link_speeds_bitmap: targeted link speeds bitmap
355771d10453SEric Joyner  *
355871d10453SEric Joyner  * Note: For the link_speeds_bitmap structure, you can check it at
355971d10453SEric Joyner  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
356071d10453SEric Joyner  * link_speeds_bitmap include multiple speeds.
356171d10453SEric Joyner  *
356271d10453SEric Joyner  * Each entry in this [phy_type_low, phy_type_high] structure will
356371d10453SEric Joyner  * present a certain link speed. This helper function will turn on bits
356471d10453SEric Joyner  * in [phy_type_low, phy_type_high] structure based on the value of
356571d10453SEric Joyner  * link_speeds_bitmap input parameter.
356671d10453SEric Joyner  */
356771d10453SEric Joyner void
356871d10453SEric Joyner ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
356971d10453SEric Joyner 		    u16 link_speeds_bitmap)
357071d10453SEric Joyner {
357171d10453SEric Joyner 	u64 pt_high;
357271d10453SEric Joyner 	u64 pt_low;
357371d10453SEric Joyner 	int index;
357471d10453SEric Joyner 	u16 speed;
357571d10453SEric Joyner 
357671d10453SEric Joyner 	/* We first check with low part of phy_type */
357771d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
357871d10453SEric Joyner 		pt_low = BIT_ULL(index);
357971d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
358071d10453SEric Joyner 
358171d10453SEric Joyner 		if (link_speeds_bitmap & speed)
358271d10453SEric Joyner 			*phy_type_low |= BIT_ULL(index);
358371d10453SEric Joyner 	}
358471d10453SEric Joyner 
358571d10453SEric Joyner 	/* We then check with high part of phy_type */
358671d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
358771d10453SEric Joyner 		pt_high = BIT_ULL(index);
358871d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
358971d10453SEric Joyner 
359071d10453SEric Joyner 		if (link_speeds_bitmap & speed)
359171d10453SEric Joyner 			*phy_type_high |= BIT_ULL(index);
359271d10453SEric Joyner 	}
359371d10453SEric Joyner }
359471d10453SEric Joyner 
359571d10453SEric Joyner /**
359671d10453SEric Joyner  * ice_aq_set_phy_cfg
359771d10453SEric Joyner  * @hw: pointer to the HW struct
359871d10453SEric Joyner  * @pi: port info structure of the interested logical port
359971d10453SEric Joyner  * @cfg: structure with PHY configuration data to be set
360071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
360171d10453SEric Joyner  *
360271d10453SEric Joyner  * Set the various PHY configuration parameters supported on the Port.
360371d10453SEric Joyner  * One or more of the Set PHY config parameters may be ignored in an MFP
360471d10453SEric Joyner  * mode as the PF may not have the privilege to set some of the PHY Config
360571d10453SEric Joyner  * parameters. This status will be indicated by the command response (0x0601).
360671d10453SEric Joyner  */
3607*f2635e84SEric Joyner int
360871d10453SEric Joyner ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
360971d10453SEric Joyner 		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
361071d10453SEric Joyner {
361171d10453SEric Joyner 	struct ice_aq_desc desc;
3612*f2635e84SEric Joyner 	int status;
361371d10453SEric Joyner 
361471d10453SEric Joyner 	if (!cfg)
361571d10453SEric Joyner 		return ICE_ERR_PARAM;
361671d10453SEric Joyner 
361771d10453SEric Joyner 	/* Ensure that only valid bits of cfg->caps can be turned on. */
361871d10453SEric Joyner 	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
36197d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
362071d10453SEric Joyner 			  cfg->caps);
362171d10453SEric Joyner 
362271d10453SEric Joyner 		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
362371d10453SEric Joyner 	}
362471d10453SEric Joyner 
362571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
362671d10453SEric Joyner 	desc.params.set_phy.lport_num = pi->lport;
362771d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
362871d10453SEric Joyner 
36297d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
363071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
363171d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_low));
363271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
363371d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_high));
363471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", cfg->caps);
363571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
363671d10453SEric Joyner 		  cfg->low_power_ctrl_an);
363771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", cfg->eee_cap);
363871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n", cfg->eeer_value);
36397d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_fec_opt = 0x%x\n",
36407d7af7f8SEric Joyner 		  cfg->link_fec_opt);
364171d10453SEric Joyner 
364271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
364371d10453SEric Joyner 
36447d7af7f8SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
3645*f2635e84SEric Joyner 		status = 0;
36467d7af7f8SEric Joyner 
364771d10453SEric Joyner 	if (!status)
364871d10453SEric Joyner 		pi->phy.curr_user_phy_cfg = *cfg;
364971d10453SEric Joyner 
365071d10453SEric Joyner 	return status;
365171d10453SEric Joyner }
365271d10453SEric Joyner 
365371d10453SEric Joyner /**
365471d10453SEric Joyner  * ice_update_link_info - update status of the HW network link
365571d10453SEric Joyner  * @pi: port info structure of the interested logical port
365671d10453SEric Joyner  */
3657*f2635e84SEric Joyner int ice_update_link_info(struct ice_port_info *pi)
365871d10453SEric Joyner {
365971d10453SEric Joyner 	struct ice_link_status *li;
3660*f2635e84SEric Joyner 	int status;
366171d10453SEric Joyner 
366271d10453SEric Joyner 	if (!pi)
366371d10453SEric Joyner 		return ICE_ERR_PARAM;
366471d10453SEric Joyner 
366571d10453SEric Joyner 	li = &pi->phy.link_info;
366671d10453SEric Joyner 
366771d10453SEric Joyner 	status = ice_aq_get_link_info(pi, true, NULL, NULL);
366871d10453SEric Joyner 	if (status)
366971d10453SEric Joyner 		return status;
367071d10453SEric Joyner 
367171d10453SEric Joyner 	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
367271d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
367371d10453SEric Joyner 		struct ice_hw *hw;
367471d10453SEric Joyner 
367571d10453SEric Joyner 		hw = pi->hw;
367671d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
367771d10453SEric Joyner 			ice_malloc(hw, sizeof(*pcaps));
367871d10453SEric Joyner 		if (!pcaps)
367971d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
368071d10453SEric Joyner 
36819cf1841cSEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
368271d10453SEric Joyner 					     pcaps, NULL);
368371d10453SEric Joyner 
3684*f2635e84SEric Joyner 		if (!status)
3685d08b8680SEric Joyner 			ice_memcpy(li->module_type, &pcaps->module_type,
3686d08b8680SEric Joyner 				   sizeof(li->module_type),
3687d08b8680SEric Joyner 				   ICE_NONDMA_TO_NONDMA);
3688d08b8680SEric Joyner 
368971d10453SEric Joyner 		ice_free(hw, pcaps);
369071d10453SEric Joyner 	}
369171d10453SEric Joyner 
369271d10453SEric Joyner 	return status;
369371d10453SEric Joyner }
369471d10453SEric Joyner 
369571d10453SEric Joyner /**
369671d10453SEric Joyner  * ice_cache_phy_user_req
369771d10453SEric Joyner  * @pi: port information structure
369871d10453SEric Joyner  * @cache_data: PHY logging data
369971d10453SEric Joyner  * @cache_mode: PHY logging mode
370071d10453SEric Joyner  *
370171d10453SEric Joyner  * Log the user request on (FC, FEC, SPEED) for later user.
370271d10453SEric Joyner  */
370371d10453SEric Joyner static void
370471d10453SEric Joyner ice_cache_phy_user_req(struct ice_port_info *pi,
370571d10453SEric Joyner 		       struct ice_phy_cache_mode_data cache_data,
370671d10453SEric Joyner 		       enum ice_phy_cache_mode cache_mode)
370771d10453SEric Joyner {
370871d10453SEric Joyner 	if (!pi)
370971d10453SEric Joyner 		return;
371071d10453SEric Joyner 
371171d10453SEric Joyner 	switch (cache_mode) {
371271d10453SEric Joyner 	case ICE_FC_MODE:
371371d10453SEric Joyner 		pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
371471d10453SEric Joyner 		break;
371571d10453SEric Joyner 	case ICE_SPEED_MODE:
371671d10453SEric Joyner 		pi->phy.curr_user_speed_req =
371771d10453SEric Joyner 			cache_data.data.curr_user_speed_req;
371871d10453SEric Joyner 		break;
371971d10453SEric Joyner 	case ICE_FEC_MODE:
372071d10453SEric Joyner 		pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
372171d10453SEric Joyner 		break;
372271d10453SEric Joyner 	default:
372371d10453SEric Joyner 		break;
372471d10453SEric Joyner 	}
372571d10453SEric Joyner }
372671d10453SEric Joyner 
372771d10453SEric Joyner /**
372871d10453SEric Joyner  * ice_caps_to_fc_mode
372971d10453SEric Joyner  * @caps: PHY capabilities
373071d10453SEric Joyner  *
373171d10453SEric Joyner  * Convert PHY FC capabilities to ice FC mode
373271d10453SEric Joyner  */
373371d10453SEric Joyner enum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
373471d10453SEric Joyner {
373571d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
373671d10453SEric Joyner 	    caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
373771d10453SEric Joyner 		return ICE_FC_FULL;
373871d10453SEric Joyner 
373971d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
374071d10453SEric Joyner 		return ICE_FC_TX_PAUSE;
374171d10453SEric Joyner 
374271d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
374371d10453SEric Joyner 		return ICE_FC_RX_PAUSE;
374471d10453SEric Joyner 
374571d10453SEric Joyner 	return ICE_FC_NONE;
374671d10453SEric Joyner }
374771d10453SEric Joyner 
374871d10453SEric Joyner /**
374971d10453SEric Joyner  * ice_caps_to_fec_mode
375071d10453SEric Joyner  * @caps: PHY capabilities
375171d10453SEric Joyner  * @fec_options: Link FEC options
375271d10453SEric Joyner  *
375371d10453SEric Joyner  * Convert PHY FEC capabilities to ice FEC mode
375471d10453SEric Joyner  */
375571d10453SEric Joyner enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
375671d10453SEric Joyner {
37578923de59SPiotr Kubaj 	if (caps & ICE_AQC_PHY_EN_AUTO_FEC) {
37588923de59SPiotr Kubaj 		if (fec_options & ICE_AQC_PHY_FEC_DIS)
37598923de59SPiotr Kubaj 			return ICE_FEC_DIS_AUTO;
37608923de59SPiotr Kubaj 		else
376171d10453SEric Joyner 			return ICE_FEC_AUTO;
37628923de59SPiotr Kubaj 	}
376371d10453SEric Joyner 
376471d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
376571d10453SEric Joyner 			   ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
376671d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
376771d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_REQ))
376871d10453SEric Joyner 		return ICE_FEC_BASER;
376971d10453SEric Joyner 
377071d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
377171d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_544_REQ |
377271d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
377371d10453SEric Joyner 		return ICE_FEC_RS;
377471d10453SEric Joyner 
377571d10453SEric Joyner 	return ICE_FEC_NONE;
377671d10453SEric Joyner }
377771d10453SEric Joyner 
377871d10453SEric Joyner /**
37797d7af7f8SEric Joyner  * ice_cfg_phy_fc - Configure PHY FC data based on FC mode
378071d10453SEric Joyner  * @pi: port information structure
37817d7af7f8SEric Joyner  * @cfg: PHY configuration data to set FC mode
37827d7af7f8SEric Joyner  * @req_mode: FC mode to configure
378371d10453SEric Joyner  */
3784*f2635e84SEric Joyner static int
37857d7af7f8SEric Joyner ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
37867d7af7f8SEric Joyner 	       enum ice_fc_mode req_mode)
378771d10453SEric Joyner {
378871d10453SEric Joyner 	struct ice_phy_cache_mode_data cache_data;
37897d7af7f8SEric Joyner 	u8 pause_mask = 0x0;
37907d7af7f8SEric Joyner 
37917d7af7f8SEric Joyner 	if (!pi || !cfg)
37927d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
37937d7af7f8SEric Joyner 	switch (req_mode) {
37947d7af7f8SEric Joyner 	case ICE_FC_AUTO:
37957d7af7f8SEric Joyner 	{
379671d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
3797*f2635e84SEric Joyner 		int status;
379871d10453SEric Joyner 
379971d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
38007d7af7f8SEric Joyner 			ice_malloc(pi->hw, sizeof(*pcaps));
380171d10453SEric Joyner 		if (!pcaps)
380271d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
380371d10453SEric Joyner 		/* Query the value of FC that both the NIC and attached media
380471d10453SEric Joyner 		 * can do.
380571d10453SEric Joyner 		 */
38069cf1841cSEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
380771d10453SEric Joyner 					     pcaps, NULL);
380871d10453SEric Joyner 		if (status) {
38097d7af7f8SEric Joyner 			ice_free(pi->hw, pcaps);
38107d7af7f8SEric Joyner 			return status;
381171d10453SEric Joyner 		}
381271d10453SEric Joyner 
381371d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE;
381471d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE;
38157d7af7f8SEric Joyner 
38167d7af7f8SEric Joyner 		ice_free(pi->hw, pcaps);
381771d10453SEric Joyner 		break;
38187d7af7f8SEric Joyner 	}
381971d10453SEric Joyner 	case ICE_FC_FULL:
382071d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
382171d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
382271d10453SEric Joyner 		break;
382371d10453SEric Joyner 	case ICE_FC_RX_PAUSE:
382471d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
382571d10453SEric Joyner 		break;
382671d10453SEric Joyner 	case ICE_FC_TX_PAUSE:
382771d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
382871d10453SEric Joyner 		break;
382971d10453SEric Joyner 	default:
383071d10453SEric Joyner 		break;
383171d10453SEric Joyner 	}
383271d10453SEric Joyner 
38337d7af7f8SEric Joyner 	/* clear the old pause settings */
38347d7af7f8SEric Joyner 	cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
38357d7af7f8SEric Joyner 		ICE_AQC_PHY_EN_RX_LINK_PAUSE);
38367d7af7f8SEric Joyner 
38377d7af7f8SEric Joyner 	/* set the new capabilities */
38387d7af7f8SEric Joyner 	cfg->caps |= pause_mask;
38397d7af7f8SEric Joyner 
38407d7af7f8SEric Joyner 	/* Cache user FC request */
38417d7af7f8SEric Joyner 	cache_data.data.curr_user_fc_req = req_mode;
38427d7af7f8SEric Joyner 	ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
38437d7af7f8SEric Joyner 
3844*f2635e84SEric Joyner 	return 0;
38457d7af7f8SEric Joyner }
38467d7af7f8SEric Joyner 
38477d7af7f8SEric Joyner /**
38487d7af7f8SEric Joyner  * ice_set_fc
38497d7af7f8SEric Joyner  * @pi: port information structure
38507d7af7f8SEric Joyner  * @aq_failures: pointer to status code, specific to ice_set_fc routine
38517d7af7f8SEric Joyner  * @ena_auto_link_update: enable automatic link update
38527d7af7f8SEric Joyner  *
38537d7af7f8SEric Joyner  * Set the requested flow control mode.
38547d7af7f8SEric Joyner  */
3855*f2635e84SEric Joyner int
38567d7af7f8SEric Joyner ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
38577d7af7f8SEric Joyner {
38587d7af7f8SEric Joyner 	struct ice_aqc_set_phy_cfg_data  cfg = { 0 };
38597d7af7f8SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
38607d7af7f8SEric Joyner 	struct ice_hw *hw;
3861*f2635e84SEric Joyner 	int status;
38627d7af7f8SEric Joyner 
38637d7af7f8SEric Joyner 	if (!pi || !aq_failures)
38647d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
38657d7af7f8SEric Joyner 
38667d7af7f8SEric Joyner 	*aq_failures = 0;
38677d7af7f8SEric Joyner 	hw = pi->hw;
38687d7af7f8SEric Joyner 
38697d7af7f8SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
38707d7af7f8SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
38717d7af7f8SEric Joyner 	if (!pcaps)
38727d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
38737d7af7f8SEric Joyner 
387471d10453SEric Joyner 	/* Get the current PHY config */
38759cf1841cSEric Joyner 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG,
38769cf1841cSEric Joyner 				     pcaps, NULL);
38779cf1841cSEric Joyner 
387871d10453SEric Joyner 	if (status) {
387971d10453SEric Joyner 		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
388071d10453SEric Joyner 		goto out;
388171d10453SEric Joyner 	}
388271d10453SEric Joyner 
388371d10453SEric Joyner 	ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
388471d10453SEric Joyner 
38857d7af7f8SEric Joyner 	/* Configure the set PHY data */
38867d7af7f8SEric Joyner 	status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
38877d7af7f8SEric Joyner 	if (status) {
38887d7af7f8SEric Joyner 		if (status != ICE_ERR_BAD_PTR)
38897d7af7f8SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
389071d10453SEric Joyner 
38917d7af7f8SEric Joyner 		goto out;
38927d7af7f8SEric Joyner 	}
389371d10453SEric Joyner 
389471d10453SEric Joyner 	/* If the capabilities have changed, then set the new config */
389571d10453SEric Joyner 	if (cfg.caps != pcaps->caps) {
389671d10453SEric Joyner 		int retry_count, retry_max = 10;
389771d10453SEric Joyner 
389871d10453SEric Joyner 		/* Auto restart link so settings take effect */
389971d10453SEric Joyner 		if (ena_auto_link_update)
390071d10453SEric Joyner 			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
390171d10453SEric Joyner 
390271d10453SEric Joyner 		status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
390371d10453SEric Joyner 		if (status) {
390471d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
390571d10453SEric Joyner 			goto out;
390671d10453SEric Joyner 		}
390771d10453SEric Joyner 
390871d10453SEric Joyner 		/* Update the link info
390971d10453SEric Joyner 		 * It sometimes takes a really long time for link to
391071d10453SEric Joyner 		 * come back from the atomic reset. Thus, we wait a
391171d10453SEric Joyner 		 * little bit.
391271d10453SEric Joyner 		 */
391371d10453SEric Joyner 		for (retry_count = 0; retry_count < retry_max; retry_count++) {
391471d10453SEric Joyner 			status = ice_update_link_info(pi);
391571d10453SEric Joyner 
3916*f2635e84SEric Joyner 			if (!status)
391771d10453SEric Joyner 				break;
391871d10453SEric Joyner 
391971d10453SEric Joyner 			ice_msec_delay(100, true);
392071d10453SEric Joyner 		}
392171d10453SEric Joyner 
392271d10453SEric Joyner 		if (status)
392371d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
392471d10453SEric Joyner 	}
392571d10453SEric Joyner 
392671d10453SEric Joyner out:
392771d10453SEric Joyner 	ice_free(hw, pcaps);
392871d10453SEric Joyner 	return status;
392971d10453SEric Joyner }
393071d10453SEric Joyner 
393171d10453SEric Joyner /**
393271d10453SEric Joyner  * ice_phy_caps_equals_cfg
393371d10453SEric Joyner  * @phy_caps: PHY capabilities
393471d10453SEric Joyner  * @phy_cfg: PHY configuration
393571d10453SEric Joyner  *
393671d10453SEric Joyner  * Helper function to determine if PHY capabilities matches PHY
393771d10453SEric Joyner  * configuration
393871d10453SEric Joyner  */
393971d10453SEric Joyner bool
394071d10453SEric Joyner ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
394171d10453SEric Joyner 			struct ice_aqc_set_phy_cfg_data *phy_cfg)
394271d10453SEric Joyner {
394371d10453SEric Joyner 	u8 caps_mask, cfg_mask;
394471d10453SEric Joyner 
394571d10453SEric Joyner 	if (!phy_caps || !phy_cfg)
394671d10453SEric Joyner 		return false;
394771d10453SEric Joyner 
394871d10453SEric Joyner 	/* These bits are not common between capabilities and configuration.
394971d10453SEric Joyner 	 * Do not use them to determine equality.
395071d10453SEric Joyner 	 */
395171d10453SEric Joyner 	caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
395271d10453SEric Joyner 					      ICE_AQC_PHY_EN_MOD_QUAL);
395371d10453SEric Joyner 	cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
395471d10453SEric Joyner 
395571d10453SEric Joyner 	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
395671d10453SEric Joyner 	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
395771d10453SEric Joyner 	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
395871d10453SEric Joyner 	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
395971d10453SEric Joyner 	    phy_caps->eee_cap != phy_cfg->eee_cap ||
396071d10453SEric Joyner 	    phy_caps->eeer_value != phy_cfg->eeer_value ||
396171d10453SEric Joyner 	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
396271d10453SEric Joyner 		return false;
396371d10453SEric Joyner 
396471d10453SEric Joyner 	return true;
396571d10453SEric Joyner }
396671d10453SEric Joyner 
396771d10453SEric Joyner /**
396871d10453SEric Joyner  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
396971d10453SEric Joyner  * @pi: port information structure
397056429daeSEric Joyner  * @caps: PHY ability structure to copy data from
397171d10453SEric Joyner  * @cfg: PHY configuration structure to copy data to
397271d10453SEric Joyner  *
397371d10453SEric Joyner  * Helper function to copy AQC PHY get ability data to PHY set configuration
397471d10453SEric Joyner  * data structure
397571d10453SEric Joyner  */
397671d10453SEric Joyner void
397771d10453SEric Joyner ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
397871d10453SEric Joyner 			 struct ice_aqc_get_phy_caps_data *caps,
397971d10453SEric Joyner 			 struct ice_aqc_set_phy_cfg_data *cfg)
398071d10453SEric Joyner {
398171d10453SEric Joyner 	if (!pi || !caps || !cfg)
398271d10453SEric Joyner 		return;
398371d10453SEric Joyner 
398471d10453SEric Joyner 	ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
398571d10453SEric Joyner 	cfg->phy_type_low = caps->phy_type_low;
398671d10453SEric Joyner 	cfg->phy_type_high = caps->phy_type_high;
398771d10453SEric Joyner 	cfg->caps = caps->caps;
398871d10453SEric Joyner 	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
398971d10453SEric Joyner 	cfg->eee_cap = caps->eee_cap;
399071d10453SEric Joyner 	cfg->eeer_value = caps->eeer_value;
399171d10453SEric Joyner 	cfg->link_fec_opt = caps->link_fec_options;
399271d10453SEric Joyner 	cfg->module_compliance_enforcement =
399371d10453SEric Joyner 		caps->module_compliance_enforcement;
399471d10453SEric Joyner }
399571d10453SEric Joyner 
399671d10453SEric Joyner /**
399771d10453SEric Joyner  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
399871d10453SEric Joyner  * @pi: port information structure
399971d10453SEric Joyner  * @cfg: PHY configuration data to set FEC mode
400071d10453SEric Joyner  * @fec: FEC mode to configure
400171d10453SEric Joyner  */
4002*f2635e84SEric Joyner int
400371d10453SEric Joyner ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
400471d10453SEric Joyner 		enum ice_fec_mode fec)
400571d10453SEric Joyner {
400671d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
400771d10453SEric Joyner 	struct ice_hw *hw;
4008*f2635e84SEric Joyner 	int status = 0;
400971d10453SEric Joyner 
401071d10453SEric Joyner 	if (!pi || !cfg)
401171d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
401271d10453SEric Joyner 
401371d10453SEric Joyner 	hw = pi->hw;
401471d10453SEric Joyner 
401571d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
401671d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
401771d10453SEric Joyner 	if (!pcaps)
401871d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
401971d10453SEric Joyner 
40209cf1841cSEric Joyner 	status = ice_aq_get_phy_caps(pi, false,
40219cf1841cSEric Joyner 				     (ice_fw_supports_report_dflt_cfg(hw) ?
40229cf1841cSEric Joyner 				      ICE_AQC_REPORT_DFLT_CFG :
40239cf1841cSEric Joyner 				      ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);
40249cf1841cSEric Joyner 
402571d10453SEric Joyner 	if (status)
402671d10453SEric Joyner 		goto out;
402771d10453SEric Joyner 
40287d7af7f8SEric Joyner 	cfg->caps |= (pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC);
40297d7af7f8SEric Joyner 	cfg->link_fec_opt = pcaps->link_fec_options;
40307d7af7f8SEric Joyner 
403171d10453SEric Joyner 	switch (fec) {
403271d10453SEric Joyner 	case ICE_FEC_BASER:
403371d10453SEric Joyner 		/* Clear RS bits, and AND BASE-R ability
403471d10453SEric Joyner 		 * bits and OR request bits.
403571d10453SEric Joyner 		 */
403671d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
403771d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
403871d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
403971d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_REQ;
404071d10453SEric Joyner 		break;
404171d10453SEric Joyner 	case ICE_FEC_RS:
404271d10453SEric Joyner 		/* Clear BASE-R bits, and AND RS ability
404371d10453SEric Joyner 		 * bits and OR request bits.
404471d10453SEric Joyner 		 */
404571d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
404671d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
404771d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_RS_544_REQ;
404871d10453SEric Joyner 		break;
404971d10453SEric Joyner 	case ICE_FEC_NONE:
405071d10453SEric Joyner 		/* Clear all FEC option bits. */
405171d10453SEric Joyner 		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
405271d10453SEric Joyner 		break;
40538923de59SPiotr Kubaj 	case ICE_FEC_DIS_AUTO:
40548923de59SPiotr Kubaj 		/* Set No FEC and auto FEC */
40559c30461dSEric Joyner 		if (!ice_fw_supports_fec_dis_auto(hw)) {
40569c30461dSEric Joyner 			status = ICE_ERR_NOT_SUPPORTED;
40579c30461dSEric Joyner 			goto out;
40589c30461dSEric Joyner 		}
40598923de59SPiotr Kubaj 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_DIS;
40608923de59SPiotr Kubaj 		/* fall-through */
406171d10453SEric Joyner 	case ICE_FEC_AUTO:
406271d10453SEric Joyner 		/* AND auto FEC bit, and all caps bits. */
406371d10453SEric Joyner 		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
406471d10453SEric Joyner 		cfg->link_fec_opt |= pcaps->link_fec_options;
406571d10453SEric Joyner 		break;
406671d10453SEric Joyner 	default:
406771d10453SEric Joyner 		status = ICE_ERR_PARAM;
406871d10453SEric Joyner 		break;
406971d10453SEric Joyner 	}
407071d10453SEric Joyner 
40719cf1841cSEric Joyner 	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw) &&
40729cf1841cSEric Joyner 	    !ice_fw_supports_report_dflt_cfg(pi->hw)) {
407371d10453SEric Joyner 		struct ice_link_default_override_tlv tlv;
407471d10453SEric Joyner 
407571d10453SEric Joyner 		if (ice_get_link_default_override(&tlv, pi))
407671d10453SEric Joyner 			goto out;
407771d10453SEric Joyner 
407871d10453SEric Joyner 		if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
407971d10453SEric Joyner 		    (tlv.options & ICE_LINK_OVERRIDE_EN))
408071d10453SEric Joyner 			cfg->link_fec_opt = tlv.fec_options;
408171d10453SEric Joyner 	}
408271d10453SEric Joyner 
408371d10453SEric Joyner out:
408471d10453SEric Joyner 	ice_free(hw, pcaps);
408571d10453SEric Joyner 
408671d10453SEric Joyner 	return status;
408771d10453SEric Joyner }
408871d10453SEric Joyner 
408971d10453SEric Joyner /**
409071d10453SEric Joyner  * ice_get_link_status - get status of the HW network link
409171d10453SEric Joyner  * @pi: port information structure
409271d10453SEric Joyner  * @link_up: pointer to bool (true/false = linkup/linkdown)
409371d10453SEric Joyner  *
409471d10453SEric Joyner  * Variable link_up is true if link is up, false if link is down.
409571d10453SEric Joyner  * The variable link_up is invalid if status is non zero. As a
409671d10453SEric Joyner  * result of this call, link status reporting becomes enabled
409771d10453SEric Joyner  */
4098*f2635e84SEric Joyner int ice_get_link_status(struct ice_port_info *pi, bool *link_up)
409971d10453SEric Joyner {
410071d10453SEric Joyner 	struct ice_phy_info *phy_info;
4101*f2635e84SEric Joyner 	int status = 0;
410271d10453SEric Joyner 
410371d10453SEric Joyner 	if (!pi || !link_up)
410471d10453SEric Joyner 		return ICE_ERR_PARAM;
410571d10453SEric Joyner 
410671d10453SEric Joyner 	phy_info = &pi->phy;
410771d10453SEric Joyner 
410871d10453SEric Joyner 	if (phy_info->get_link_info) {
410971d10453SEric Joyner 		status = ice_update_link_info(pi);
411071d10453SEric Joyner 
411171d10453SEric Joyner 		if (status)
41127d7af7f8SEric Joyner 			ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n",
411371d10453SEric Joyner 				  status);
411471d10453SEric Joyner 	}
411571d10453SEric Joyner 
411671d10453SEric Joyner 	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
411771d10453SEric Joyner 
411871d10453SEric Joyner 	return status;
411971d10453SEric Joyner }
412071d10453SEric Joyner 
412171d10453SEric Joyner /**
412271d10453SEric Joyner  * ice_aq_set_link_restart_an
412371d10453SEric Joyner  * @pi: pointer to the port information structure
412471d10453SEric Joyner  * @ena_link: if true: enable link, if false: disable link
412571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
412671d10453SEric Joyner  *
412771d10453SEric Joyner  * Sets up the link and restarts the Auto-Negotiation over the link.
412871d10453SEric Joyner  */
4129*f2635e84SEric Joyner int
413071d10453SEric Joyner ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
413171d10453SEric Joyner 			   struct ice_sq_cd *cd)
413271d10453SEric Joyner {
4133*f2635e84SEric Joyner 	int status = ICE_ERR_AQ_ERROR;
413471d10453SEric Joyner 	struct ice_aqc_restart_an *cmd;
413571d10453SEric Joyner 	struct ice_aq_desc desc;
413671d10453SEric Joyner 
413771d10453SEric Joyner 	cmd = &desc.params.restart_an;
413871d10453SEric Joyner 
413971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
414071d10453SEric Joyner 
414171d10453SEric Joyner 	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
414271d10453SEric Joyner 	cmd->lport_num = pi->lport;
414371d10453SEric Joyner 	if (ena_link)
414471d10453SEric Joyner 		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
414571d10453SEric Joyner 	else
414671d10453SEric Joyner 		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
414771d10453SEric Joyner 
41489c30461dSEric Joyner 	status = ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
41499c30461dSEric Joyner 	if (status)
41509c30461dSEric Joyner 		return status;
41519c30461dSEric Joyner 
41529c30461dSEric Joyner 	if (ena_link)
41539c30461dSEric Joyner 		pi->phy.curr_user_phy_cfg.caps |= ICE_AQC_PHY_EN_LINK;
41549c30461dSEric Joyner 	else
41559c30461dSEric Joyner 		pi->phy.curr_user_phy_cfg.caps &= ~ICE_AQC_PHY_EN_LINK;
41569c30461dSEric Joyner 
4157*f2635e84SEric Joyner 	return 0;
415871d10453SEric Joyner }
415971d10453SEric Joyner 
416071d10453SEric Joyner /**
416171d10453SEric Joyner  * ice_aq_set_event_mask
416271d10453SEric Joyner  * @hw: pointer to the HW struct
416371d10453SEric Joyner  * @port_num: port number of the physical function
416471d10453SEric Joyner  * @mask: event mask to be set
416571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
416671d10453SEric Joyner  *
416771d10453SEric Joyner  * Set event mask (0x0613)
416871d10453SEric Joyner  */
4169*f2635e84SEric Joyner int
417071d10453SEric Joyner ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
417171d10453SEric Joyner 		      struct ice_sq_cd *cd)
417271d10453SEric Joyner {
417371d10453SEric Joyner 	struct ice_aqc_set_event_mask *cmd;
417471d10453SEric Joyner 	struct ice_aq_desc desc;
417571d10453SEric Joyner 
417671d10453SEric Joyner 	cmd = &desc.params.set_event_mask;
417771d10453SEric Joyner 
417871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
417971d10453SEric Joyner 
418071d10453SEric Joyner 	cmd->lport_num = port_num;
418171d10453SEric Joyner 
418271d10453SEric Joyner 	cmd->event_mask = CPU_TO_LE16(mask);
418371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
418471d10453SEric Joyner }
418571d10453SEric Joyner 
418671d10453SEric Joyner /**
418771d10453SEric Joyner  * ice_aq_set_mac_loopback
418871d10453SEric Joyner  * @hw: pointer to the HW struct
418971d10453SEric Joyner  * @ena_lpbk: Enable or Disable loopback
419071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
419171d10453SEric Joyner  *
419271d10453SEric Joyner  * Enable/disable loopback on a given port
419371d10453SEric Joyner  */
4194*f2635e84SEric Joyner int
419571d10453SEric Joyner ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
419671d10453SEric Joyner {
419771d10453SEric Joyner 	struct ice_aqc_set_mac_lb *cmd;
419871d10453SEric Joyner 	struct ice_aq_desc desc;
419971d10453SEric Joyner 
420071d10453SEric Joyner 	cmd = &desc.params.set_mac_lb;
420171d10453SEric Joyner 
420271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
420371d10453SEric Joyner 	if (ena_lpbk)
420471d10453SEric Joyner 		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
420571d10453SEric Joyner 
420671d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
420771d10453SEric Joyner }
420871d10453SEric Joyner 
420971d10453SEric Joyner /**
421071d10453SEric Joyner  * ice_aq_set_port_id_led
421171d10453SEric Joyner  * @pi: pointer to the port information
421271d10453SEric Joyner  * @is_orig_mode: is this LED set to original mode (by the net-list)
421371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
421471d10453SEric Joyner  *
421571d10453SEric Joyner  * Set LED value for the given port (0x06e9)
421671d10453SEric Joyner  */
4217*f2635e84SEric Joyner int
421871d10453SEric Joyner ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
421971d10453SEric Joyner 		       struct ice_sq_cd *cd)
422071d10453SEric Joyner {
422171d10453SEric Joyner 	struct ice_aqc_set_port_id_led *cmd;
422271d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
422371d10453SEric Joyner 	struct ice_aq_desc desc;
422471d10453SEric Joyner 
422571d10453SEric Joyner 	cmd = &desc.params.set_port_id_led;
422671d10453SEric Joyner 
422771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
422871d10453SEric Joyner 
422971d10453SEric Joyner 	if (is_orig_mode)
423071d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
423171d10453SEric Joyner 	else
423271d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
423371d10453SEric Joyner 
423471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
423571d10453SEric Joyner }
423671d10453SEric Joyner 
423771d10453SEric Joyner /**
423871d10453SEric Joyner  * ice_aq_sff_eeprom
423971d10453SEric Joyner  * @hw: pointer to the HW struct
424071d10453SEric Joyner  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
424171d10453SEric Joyner  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
424271d10453SEric Joyner  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
424371d10453SEric Joyner  * @page: QSFP page
424471d10453SEric Joyner  * @set_page: set or ignore the page
424571d10453SEric Joyner  * @data: pointer to data buffer to be read/written to the I2C device.
424671d10453SEric Joyner  * @length: 1-16 for read, 1 for write.
424771d10453SEric Joyner  * @write: 0 read, 1 for write.
424871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
424971d10453SEric Joyner  *
425071d10453SEric Joyner  * Read/Write SFF EEPROM (0x06EE)
425171d10453SEric Joyner  */
4252*f2635e84SEric Joyner int
425371d10453SEric Joyner ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
425471d10453SEric Joyner 		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
425571d10453SEric Joyner 		  bool write, struct ice_sq_cd *cd)
425671d10453SEric Joyner {
425771d10453SEric Joyner 	struct ice_aqc_sff_eeprom *cmd;
425871d10453SEric Joyner 	struct ice_aq_desc desc;
4259*f2635e84SEric Joyner 	int status;
426071d10453SEric Joyner 
426171d10453SEric Joyner 	if (!data || (mem_addr & 0xff00))
426271d10453SEric Joyner 		return ICE_ERR_PARAM;
426371d10453SEric Joyner 
426471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
426571d10453SEric Joyner 	cmd = &desc.params.read_write_sff_param;
4266d08b8680SEric Joyner 	desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD);
426771d10453SEric Joyner 	cmd->lport_num = (u8)(lport & 0xff);
426871d10453SEric Joyner 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
426971d10453SEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(((bus_addr >> 1) &
427071d10453SEric Joyner 					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
427171d10453SEric Joyner 					((set_page <<
427271d10453SEric Joyner 					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
427371d10453SEric Joyner 					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
427471d10453SEric Joyner 	cmd->i2c_mem_addr = CPU_TO_LE16(mem_addr & 0xff);
427571d10453SEric Joyner 	cmd->eeprom_page = CPU_TO_LE16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
427671d10453SEric Joyner 	if (write)
427771d10453SEric Joyner 		cmd->i2c_bus_addr |= CPU_TO_LE16(ICE_AQC_SFF_IS_WRITE);
427871d10453SEric Joyner 
427971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
428071d10453SEric Joyner 	return status;
428171d10453SEric Joyner }
428271d10453SEric Joyner 
428371d10453SEric Joyner /**
428456429daeSEric Joyner  * ice_aq_prog_topo_dev_nvm
428556429daeSEric Joyner  * @hw: pointer to the hardware structure
428656429daeSEric Joyner  * @topo_params: pointer to structure storing topology parameters for a device
428756429daeSEric Joyner  * @cd: pointer to command details structure or NULL
428856429daeSEric Joyner  *
428956429daeSEric Joyner  * Program Topology Device NVM (0x06F2)
429056429daeSEric Joyner  *
429156429daeSEric Joyner  */
4292*f2635e84SEric Joyner int
429356429daeSEric Joyner ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
429456429daeSEric Joyner 			 struct ice_aqc_link_topo_params *topo_params,
429556429daeSEric Joyner 			 struct ice_sq_cd *cd)
429656429daeSEric Joyner {
429756429daeSEric Joyner 	struct ice_aqc_prog_topo_dev_nvm *cmd;
429856429daeSEric Joyner 	struct ice_aq_desc desc;
429956429daeSEric Joyner 
430056429daeSEric Joyner 	cmd = &desc.params.prog_topo_dev_nvm;
430156429daeSEric Joyner 
430256429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm);
430356429daeSEric Joyner 
430456429daeSEric Joyner 	ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
430556429daeSEric Joyner 		   ICE_NONDMA_TO_NONDMA);
430656429daeSEric Joyner 
430756429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
430856429daeSEric Joyner }
430956429daeSEric Joyner 
431056429daeSEric Joyner /**
431156429daeSEric Joyner  * ice_aq_read_topo_dev_nvm
431256429daeSEric Joyner  * @hw: pointer to the hardware structure
431356429daeSEric Joyner  * @topo_params: pointer to structure storing topology parameters for a device
431456429daeSEric Joyner  * @start_address: byte offset in the topology device NVM
431556429daeSEric Joyner  * @data: pointer to data buffer
431656429daeSEric Joyner  * @data_size: number of bytes to be read from the topology device NVM
431756429daeSEric Joyner  * @cd: pointer to command details structure or NULL
431856429daeSEric Joyner  * Read Topology Device NVM (0x06F3)
431956429daeSEric Joyner  *
432056429daeSEric Joyner  */
4321*f2635e84SEric Joyner int
432256429daeSEric Joyner ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
432356429daeSEric Joyner 			 struct ice_aqc_link_topo_params *topo_params,
432456429daeSEric Joyner 			 u32 start_address, u8 *data, u8 data_size,
432556429daeSEric Joyner 			 struct ice_sq_cd *cd)
432656429daeSEric Joyner {
432756429daeSEric Joyner 	struct ice_aqc_read_topo_dev_nvm *cmd;
432856429daeSEric Joyner 	struct ice_aq_desc desc;
4329*f2635e84SEric Joyner 	int status;
433056429daeSEric Joyner 
433156429daeSEric Joyner 	if (!data || data_size == 0 ||
433256429daeSEric Joyner 	    data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
433356429daeSEric Joyner 		return ICE_ERR_PARAM;
433456429daeSEric Joyner 
433556429daeSEric Joyner 	cmd = &desc.params.read_topo_dev_nvm;
433656429daeSEric Joyner 
433756429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm);
433856429daeSEric Joyner 
43398923de59SPiotr Kubaj 	desc.datalen = CPU_TO_LE16(data_size);
434056429daeSEric Joyner 	ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
434156429daeSEric Joyner 		   ICE_NONDMA_TO_NONDMA);
434256429daeSEric Joyner 	cmd->start_address = CPU_TO_LE32(start_address);
434356429daeSEric Joyner 
434456429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
434556429daeSEric Joyner 	if (status)
434656429daeSEric Joyner 		return status;
434756429daeSEric Joyner 
434856429daeSEric Joyner 	ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA);
434956429daeSEric Joyner 
4350*f2635e84SEric Joyner 	return 0;
435156429daeSEric Joyner }
435256429daeSEric Joyner 
43539c30461dSEric Joyner static u16 ice_lut_type_to_size(u16 lut_type)
43549c30461dSEric Joyner {
43559c30461dSEric Joyner 	switch (lut_type) {
43569c30461dSEric Joyner 	case ICE_LUT_VSI:
43579c30461dSEric Joyner 		return ICE_LUT_VSI_SIZE;
43589c30461dSEric Joyner 	case ICE_LUT_GLOBAL:
43599c30461dSEric Joyner 		return ICE_LUT_GLOBAL_SIZE;
43609c30461dSEric Joyner 	case ICE_LUT_PF:
43619c30461dSEric Joyner 		return ICE_LUT_PF_SIZE;
43629e54973fSEric Joyner 	case ICE_LUT_PF_SMALL:
43639e54973fSEric Joyner 		return ICE_LUT_PF_SMALL_SIZE;
43649c30461dSEric Joyner 	default:
43659c30461dSEric Joyner 		return 0;
43669c30461dSEric Joyner 	}
43679c30461dSEric Joyner }
43689c30461dSEric Joyner 
43699c30461dSEric Joyner static u16 ice_lut_size_to_flag(u16 lut_size)
43709c30461dSEric Joyner {
43719c30461dSEric Joyner 	u16 f = 0;
43729c30461dSEric Joyner 
43739c30461dSEric Joyner 	switch (lut_size) {
43749c30461dSEric Joyner 	case ICE_LUT_GLOBAL_SIZE:
43759c30461dSEric Joyner 		f = ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG;
43769c30461dSEric Joyner 		break;
43779c30461dSEric Joyner 	case ICE_LUT_PF_SIZE:
43789c30461dSEric Joyner 		f = ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG;
43799c30461dSEric Joyner 		break;
43809c30461dSEric Joyner 	default:
43819c30461dSEric Joyner 		break;
43829c30461dSEric Joyner 	}
43839c30461dSEric Joyner 	return f << ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S;
43849c30461dSEric Joyner }
43859c30461dSEric Joyner 
43869c30461dSEric Joyner int ice_lut_size_to_type(int lut_size)
43879c30461dSEric Joyner {
43889c30461dSEric Joyner 	switch (lut_size) {
43899c30461dSEric Joyner 	case ICE_LUT_VSI_SIZE:
43909c30461dSEric Joyner 		return ICE_LUT_VSI;
43919c30461dSEric Joyner 	case ICE_LUT_GLOBAL_SIZE:
43929c30461dSEric Joyner 		return ICE_LUT_GLOBAL;
43939c30461dSEric Joyner 	case ICE_LUT_PF_SIZE:
43949c30461dSEric Joyner 		return ICE_LUT_PF;
43959e54973fSEric Joyner 	case ICE_LUT_PF_SMALL_SIZE:
43969e54973fSEric Joyner 		return ICE_LUT_PF_SMALL;
43979c30461dSEric Joyner 	default:
43989c30461dSEric Joyner 		return -1;
43999c30461dSEric Joyner 	}
44009c30461dSEric Joyner }
44019c30461dSEric Joyner 
440256429daeSEric Joyner /**
440371d10453SEric Joyner  * __ice_aq_get_set_rss_lut
440471d10453SEric Joyner  * @hw: pointer to the hardware structure
4405d08b8680SEric Joyner  * @params: RSS LUT parameters
440671d10453SEric Joyner  * @set: set true to set the table, false to get the table
440771d10453SEric Joyner  *
440871d10453SEric Joyner  * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
440971d10453SEric Joyner  */
4410*f2635e84SEric Joyner static int
4411d08b8680SEric Joyner __ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, bool set)
441271d10453SEric Joyner {
44139c30461dSEric Joyner 	u16 flags, vsi_id, lut_type, lut_size, glob_lut_idx = 0, vsi_handle;
441471d10453SEric Joyner 	struct ice_aqc_get_set_rss_lut *cmd_resp;
441571d10453SEric Joyner 	struct ice_aq_desc desc;
4416*f2635e84SEric Joyner 	int status;
4417d08b8680SEric Joyner 	u8 *lut;
4418d08b8680SEric Joyner 
4419d08b8680SEric Joyner 	if (!params)
4420d08b8680SEric Joyner 		return ICE_ERR_PARAM;
4421d08b8680SEric Joyner 
4422d08b8680SEric Joyner 	vsi_handle = params->vsi_handle;
4423d08b8680SEric Joyner 	lut = params->lut;
44249e54973fSEric Joyner 	lut_size = ice_lut_type_to_size(params->lut_type);
44259e54973fSEric Joyner 	lut_type = params->lut_type & ICE_LUT_TYPE_MASK;
44269c30461dSEric Joyner 	cmd_resp = &desc.params.get_set_rss_lut;
44279c30461dSEric Joyner 	if (lut_type == ICE_LUT_GLOBAL)
44289c30461dSEric Joyner 		glob_lut_idx = params->global_lut_id;
4429d08b8680SEric Joyner 
44309c30461dSEric Joyner 	if (!lut || !lut_size || !ice_is_vsi_valid(hw, vsi_handle))
4431d08b8680SEric Joyner 		return ICE_ERR_PARAM;
4432d08b8680SEric Joyner 
44339c30461dSEric Joyner 	if (lut_size > params->lut_size)
44349c30461dSEric Joyner 		return ICE_ERR_INVAL_SIZE;
443571d10453SEric Joyner 
44369c30461dSEric Joyner 	if (set && lut_size != params->lut_size)
44379c30461dSEric Joyner 		return ICE_ERR_PARAM;
44389c30461dSEric Joyner 
44399c30461dSEric Joyner 	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
444071d10453SEric Joyner 
444171d10453SEric Joyner 	if (set) {
444271d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut);
444371d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
444471d10453SEric Joyner 	} else {
444571d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut);
444671d10453SEric Joyner 	}
444771d10453SEric Joyner 
444871d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
444971d10453SEric Joyner 					 ICE_AQC_GSET_RSS_LUT_VSI_ID_S) &
445071d10453SEric Joyner 					ICE_AQC_GSET_RSS_LUT_VSI_ID_M) |
445171d10453SEric Joyner 				       ICE_AQC_GSET_RSS_LUT_VSI_VALID);
445271d10453SEric Joyner 
44539c30461dSEric Joyner 	flags = ice_lut_size_to_flag(lut_size) |
44549c30461dSEric Joyner 		 ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) &
44559c30461dSEric Joyner 		  ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M) |
44569c30461dSEric Joyner 		 ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) &
445771d10453SEric Joyner 		  ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M);
445871d10453SEric Joyner 
445971d10453SEric Joyner 	cmd_resp->flags = CPU_TO_LE16(flags);
446071d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
44619c30461dSEric Joyner 	params->lut_size = LE16_TO_CPU(desc.datalen);
446271d10453SEric Joyner 	return status;
446371d10453SEric Joyner }
446471d10453SEric Joyner 
446571d10453SEric Joyner /**
446671d10453SEric Joyner  * ice_aq_get_rss_lut
446771d10453SEric Joyner  * @hw: pointer to the hardware structure
4468d08b8680SEric Joyner  * @get_params: RSS LUT parameters used to specify which RSS LUT to get
446971d10453SEric Joyner  *
447071d10453SEric Joyner  * get the RSS lookup table, PF or VSI type
447171d10453SEric Joyner  */
4472*f2635e84SEric Joyner int
4473d08b8680SEric Joyner ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)
447471d10453SEric Joyner {
4475d08b8680SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, get_params, false);
447671d10453SEric Joyner }
447771d10453SEric Joyner 
447871d10453SEric Joyner /**
447971d10453SEric Joyner  * ice_aq_set_rss_lut
448071d10453SEric Joyner  * @hw: pointer to the hardware structure
4481d08b8680SEric Joyner  * @set_params: RSS LUT parameters used to specify how to set the RSS LUT
448271d10453SEric Joyner  *
448371d10453SEric Joyner  * set the RSS lookup table, PF or VSI type
448471d10453SEric Joyner  */
4485*f2635e84SEric Joyner int
4486d08b8680SEric Joyner ice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)
448771d10453SEric Joyner {
4488d08b8680SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, set_params, true);
448971d10453SEric Joyner }
449071d10453SEric Joyner 
449171d10453SEric Joyner /**
449271d10453SEric Joyner  * __ice_aq_get_set_rss_key
449371d10453SEric Joyner  * @hw: pointer to the HW struct
449471d10453SEric Joyner  * @vsi_id: VSI FW index
449571d10453SEric Joyner  * @key: pointer to key info struct
449671d10453SEric Joyner  * @set: set true to set the key, false to get the key
449771d10453SEric Joyner  *
449871d10453SEric Joyner  * get (0x0B04) or set (0x0B02) the RSS key per VSI
449971d10453SEric Joyner  */
4500*f2635e84SEric Joyner static int __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
450171d10453SEric Joyner 				    struct ice_aqc_get_set_rss_keys *key,
450271d10453SEric Joyner 				    bool set)
450371d10453SEric Joyner {
450471d10453SEric Joyner 	struct ice_aqc_get_set_rss_key *cmd_resp;
450571d10453SEric Joyner 	u16 key_size = sizeof(*key);
450671d10453SEric Joyner 	struct ice_aq_desc desc;
450771d10453SEric Joyner 
450871d10453SEric Joyner 	cmd_resp = &desc.params.get_set_rss_key;
450971d10453SEric Joyner 
451071d10453SEric Joyner 	if (set) {
451171d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
451271d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
451371d10453SEric Joyner 	} else {
451471d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
451571d10453SEric Joyner 	}
451671d10453SEric Joyner 
451771d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
451871d10453SEric Joyner 					 ICE_AQC_GSET_RSS_KEY_VSI_ID_S) &
451971d10453SEric Joyner 					ICE_AQC_GSET_RSS_KEY_VSI_ID_M) |
452071d10453SEric Joyner 				       ICE_AQC_GSET_RSS_KEY_VSI_VALID);
452171d10453SEric Joyner 
452271d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
452371d10453SEric Joyner }
452471d10453SEric Joyner 
452571d10453SEric Joyner /**
452671d10453SEric Joyner  * ice_aq_get_rss_key
452771d10453SEric Joyner  * @hw: pointer to the HW struct
452871d10453SEric Joyner  * @vsi_handle: software VSI handle
452971d10453SEric Joyner  * @key: pointer to key info struct
453071d10453SEric Joyner  *
453171d10453SEric Joyner  * get the RSS key per VSI
453271d10453SEric Joyner  */
4533*f2635e84SEric Joyner int
453471d10453SEric Joyner ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
453571d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *key)
453671d10453SEric Joyner {
453771d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
453871d10453SEric Joyner 		return ICE_ERR_PARAM;
453971d10453SEric Joyner 
454071d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
454171d10453SEric Joyner 					key, false);
454271d10453SEric Joyner }
454371d10453SEric Joyner 
454471d10453SEric Joyner /**
454571d10453SEric Joyner  * ice_aq_set_rss_key
454671d10453SEric Joyner  * @hw: pointer to the HW struct
454771d10453SEric Joyner  * @vsi_handle: software VSI handle
454871d10453SEric Joyner  * @keys: pointer to key info struct
454971d10453SEric Joyner  *
455071d10453SEric Joyner  * set the RSS key per VSI
455171d10453SEric Joyner  */
4552*f2635e84SEric Joyner int
455371d10453SEric Joyner ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
455471d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *keys)
455571d10453SEric Joyner {
455671d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
455771d10453SEric Joyner 		return ICE_ERR_PARAM;
455871d10453SEric Joyner 
455971d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
456071d10453SEric Joyner 					keys, true);
456171d10453SEric Joyner }
456271d10453SEric Joyner 
456371d10453SEric Joyner /**
456471d10453SEric Joyner  * ice_aq_add_lan_txq
456571d10453SEric Joyner  * @hw: pointer to the hardware structure
456671d10453SEric Joyner  * @num_qgrps: Number of added queue groups
456771d10453SEric Joyner  * @qg_list: list of queue groups to be added
456871d10453SEric Joyner  * @buf_size: size of buffer for indirect command
456971d10453SEric Joyner  * @cd: pointer to command details structure or NULL
457071d10453SEric Joyner  *
457171d10453SEric Joyner  * Add Tx LAN queue (0x0C30)
457271d10453SEric Joyner  *
457371d10453SEric Joyner  * NOTE:
457471d10453SEric Joyner  * Prior to calling add Tx LAN queue:
457571d10453SEric Joyner  * Initialize the following as part of the Tx queue context:
457671d10453SEric Joyner  * Completion queue ID if the queue uses Completion queue, Quanta profile,
457771d10453SEric Joyner  * Cache profile and Packet shaper profile.
457871d10453SEric Joyner  *
457971d10453SEric Joyner  * After add Tx LAN queue AQ command is completed:
458071d10453SEric Joyner  * Interrupts should be associated with specific queues,
458171d10453SEric Joyner  * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
458271d10453SEric Joyner  * flow.
458371d10453SEric Joyner  */
4584*f2635e84SEric Joyner int
458571d10453SEric Joyner ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
458671d10453SEric Joyner 		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
458771d10453SEric Joyner 		   struct ice_sq_cd *cd)
458871d10453SEric Joyner {
458971d10453SEric Joyner 	struct ice_aqc_add_tx_qgrp *list;
459071d10453SEric Joyner 	struct ice_aqc_add_txqs *cmd;
459171d10453SEric Joyner 	struct ice_aq_desc desc;
45927d7af7f8SEric Joyner 	u16 i, sum_size = 0;
459371d10453SEric Joyner 
459471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
459571d10453SEric Joyner 
459671d10453SEric Joyner 	cmd = &desc.params.add_txqs;
459771d10453SEric Joyner 
459871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
459971d10453SEric Joyner 
460071d10453SEric Joyner 	if (!qg_list)
460171d10453SEric Joyner 		return ICE_ERR_PARAM;
460271d10453SEric Joyner 
460371d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
460471d10453SEric Joyner 		return ICE_ERR_PARAM;
460571d10453SEric Joyner 
46067d7af7f8SEric Joyner 	for (i = 0, list = qg_list; i < num_qgrps; i++) {
46077d7af7f8SEric Joyner 		sum_size += ice_struct_size(list, txqs, list->num_txqs);
46087d7af7f8SEric Joyner 		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
46097d7af7f8SEric Joyner 						      list->num_txqs);
461071d10453SEric Joyner 	}
461171d10453SEric Joyner 
46127d7af7f8SEric Joyner 	if (buf_size != sum_size)
461371d10453SEric Joyner 		return ICE_ERR_PARAM;
461471d10453SEric Joyner 
461571d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
461671d10453SEric Joyner 
461771d10453SEric Joyner 	cmd->num_qgrps = num_qgrps;
461871d10453SEric Joyner 
461971d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
462071d10453SEric Joyner }
462171d10453SEric Joyner 
462271d10453SEric Joyner /**
462371d10453SEric Joyner  * ice_aq_dis_lan_txq
462471d10453SEric Joyner  * @hw: pointer to the hardware structure
462571d10453SEric Joyner  * @num_qgrps: number of groups in the list
462671d10453SEric Joyner  * @qg_list: the list of groups to disable
462771d10453SEric Joyner  * @buf_size: the total size of the qg_list buffer in bytes
462871d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
462971d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
463071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
463171d10453SEric Joyner  *
463271d10453SEric Joyner  * Disable LAN Tx queue (0x0C31)
463371d10453SEric Joyner  */
4634*f2635e84SEric Joyner static int
463571d10453SEric Joyner ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
463671d10453SEric Joyner 		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
463771d10453SEric Joyner 		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
463871d10453SEric Joyner 		   struct ice_sq_cd *cd)
463971d10453SEric Joyner {
46407d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *item;
464171d10453SEric Joyner 	struct ice_aqc_dis_txqs *cmd;
464271d10453SEric Joyner 	struct ice_aq_desc desc;
4643*f2635e84SEric Joyner 	int status;
464471d10453SEric Joyner 	u16 i, sz = 0;
464571d10453SEric Joyner 
464671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
464771d10453SEric Joyner 	cmd = &desc.params.dis_txqs;
464871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
464971d10453SEric Joyner 
465071d10453SEric Joyner 	/* qg_list can be NULL only in VM/VF reset flow */
465171d10453SEric Joyner 	if (!qg_list && !rst_src)
465271d10453SEric Joyner 		return ICE_ERR_PARAM;
465371d10453SEric Joyner 
465471d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
465571d10453SEric Joyner 		return ICE_ERR_PARAM;
465671d10453SEric Joyner 
465771d10453SEric Joyner 	cmd->num_entries = num_qgrps;
465871d10453SEric Joyner 
465971d10453SEric Joyner 	cmd->vmvf_and_timeout = CPU_TO_LE16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
466071d10453SEric Joyner 					    ICE_AQC_Q_DIS_TIMEOUT_M);
466171d10453SEric Joyner 
466271d10453SEric Joyner 	switch (rst_src) {
466371d10453SEric Joyner 	case ICE_VM_RESET:
466471d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
466571d10453SEric Joyner 		cmd->vmvf_and_timeout |=
466671d10453SEric Joyner 			CPU_TO_LE16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
466771d10453SEric Joyner 		break;
466871d10453SEric Joyner 	case ICE_VF_RESET:
466971d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
467071d10453SEric Joyner 		/* In this case, FW expects vmvf_num to be absolute VF ID */
467171d10453SEric Joyner 		cmd->vmvf_and_timeout |=
467271d10453SEric Joyner 			CPU_TO_LE16((vmvf_num + hw->func_caps.vf_base_id) &
467371d10453SEric Joyner 				    ICE_AQC_Q_DIS_VMVF_NUM_M);
467471d10453SEric Joyner 		break;
467571d10453SEric Joyner 	case ICE_NO_RESET:
467671d10453SEric Joyner 	default:
467771d10453SEric Joyner 		break;
467871d10453SEric Joyner 	}
467971d10453SEric Joyner 
468071d10453SEric Joyner 	/* flush pipe on time out */
468171d10453SEric Joyner 	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
468271d10453SEric Joyner 	/* If no queue group info, we are in a reset flow. Issue the AQ */
468371d10453SEric Joyner 	if (!qg_list)
468471d10453SEric Joyner 		goto do_aq;
468571d10453SEric Joyner 
468671d10453SEric Joyner 	/* set RD bit to indicate that command buffer is provided by the driver
468771d10453SEric Joyner 	 * and it needs to be read by the firmware
468871d10453SEric Joyner 	 */
468971d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
469071d10453SEric Joyner 
46917d7af7f8SEric Joyner 	for (i = 0, item = qg_list; i < num_qgrps; i++) {
46927d7af7f8SEric Joyner 		u16 item_size = ice_struct_size(item, q_id, item->num_qs);
469371d10453SEric Joyner 
469471d10453SEric Joyner 		/* If the num of queues is even, add 2 bytes of padding */
46957d7af7f8SEric Joyner 		if ((item->num_qs % 2) == 0)
46967d7af7f8SEric Joyner 			item_size += 2;
46977d7af7f8SEric Joyner 
46987d7af7f8SEric Joyner 		sz += item_size;
46997d7af7f8SEric Joyner 
47007d7af7f8SEric Joyner 		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
470171d10453SEric Joyner 	}
470271d10453SEric Joyner 
470371d10453SEric Joyner 	if (buf_size != sz)
470471d10453SEric Joyner 		return ICE_ERR_PARAM;
470571d10453SEric Joyner 
470671d10453SEric Joyner do_aq:
470771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
470871d10453SEric Joyner 	if (status) {
470971d10453SEric Joyner 		if (!qg_list)
471071d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
471171d10453SEric Joyner 				  vmvf_num, hw->adminq.sq_last_status);
471271d10453SEric Joyner 		else
471371d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
471471d10453SEric Joyner 				  LE16_TO_CPU(qg_list[0].q_id[0]),
471571d10453SEric Joyner 				  hw->adminq.sq_last_status);
471671d10453SEric Joyner 	}
471771d10453SEric Joyner 	return status;
471871d10453SEric Joyner }
471971d10453SEric Joyner 
472071d10453SEric Joyner /**
472171d10453SEric Joyner  * ice_aq_move_recfg_lan_txq
472271d10453SEric Joyner  * @hw: pointer to the hardware structure
472371d10453SEric Joyner  * @num_qs: number of queues to move/reconfigure
472471d10453SEric Joyner  * @is_move: true if this operation involves node movement
472571d10453SEric Joyner  * @is_tc_change: true if this operation involves a TC change
472671d10453SEric Joyner  * @subseq_call: true if this operation is a subsequent call
472771d10453SEric Joyner  * @flush_pipe: on timeout, true to flush pipe, false to return EAGAIN
472871d10453SEric Joyner  * @timeout: timeout in units of 100 usec (valid values 0-50)
472971d10453SEric Joyner  * @blocked_cgds: out param, bitmap of CGDs that timed out if returning EAGAIN
473071d10453SEric Joyner  * @buf: struct containing src/dest TEID and per-queue info
473171d10453SEric Joyner  * @buf_size: size of buffer for indirect command
473271d10453SEric Joyner  * @txqs_moved: out param, number of queues successfully moved
473371d10453SEric Joyner  * @cd: pointer to command details structure or NULL
473471d10453SEric Joyner  *
473571d10453SEric Joyner  * Move / Reconfigure Tx LAN queues (0x0C32)
473671d10453SEric Joyner  */
4737*f2635e84SEric Joyner int
473871d10453SEric Joyner ice_aq_move_recfg_lan_txq(struct ice_hw *hw, u8 num_qs, bool is_move,
473971d10453SEric Joyner 			  bool is_tc_change, bool subseq_call, bool flush_pipe,
474071d10453SEric Joyner 			  u8 timeout, u32 *blocked_cgds,
474171d10453SEric Joyner 			  struct ice_aqc_move_txqs_data *buf, u16 buf_size,
474271d10453SEric Joyner 			  u8 *txqs_moved, struct ice_sq_cd *cd)
474371d10453SEric Joyner {
474471d10453SEric Joyner 	struct ice_aqc_move_txqs *cmd;
474571d10453SEric Joyner 	struct ice_aq_desc desc;
4746*f2635e84SEric Joyner 	int status;
474771d10453SEric Joyner 
474871d10453SEric Joyner 	cmd = &desc.params.move_txqs;
474971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_move_recfg_txqs);
475071d10453SEric Joyner 
475171d10453SEric Joyner #define ICE_LAN_TXQ_MOVE_TIMEOUT_MAX 50
475271d10453SEric Joyner 	if (timeout > ICE_LAN_TXQ_MOVE_TIMEOUT_MAX)
475371d10453SEric Joyner 		return ICE_ERR_PARAM;
475471d10453SEric Joyner 
475571d10453SEric Joyner 	if (is_tc_change && !flush_pipe && !blocked_cgds)
475671d10453SEric Joyner 		return ICE_ERR_PARAM;
475771d10453SEric Joyner 
475871d10453SEric Joyner 	if (!is_move && !is_tc_change)
475971d10453SEric Joyner 		return ICE_ERR_PARAM;
476071d10453SEric Joyner 
476171d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
476271d10453SEric Joyner 
476371d10453SEric Joyner 	if (is_move)
476471d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_MOVE;
476571d10453SEric Joyner 
476671d10453SEric Joyner 	if (is_tc_change)
476771d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_TC_CHANGE;
476871d10453SEric Joyner 
476971d10453SEric Joyner 	if (subseq_call)
477071d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_SUBSEQ_CALL;
477171d10453SEric Joyner 
477271d10453SEric Joyner 	if (flush_pipe)
477371d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_FLUSH_PIPE;
477471d10453SEric Joyner 
477571d10453SEric Joyner 	cmd->num_qs = num_qs;
477671d10453SEric Joyner 	cmd->timeout = ((timeout << ICE_AQC_Q_CMD_TIMEOUT_S) &
477771d10453SEric Joyner 			ICE_AQC_Q_CMD_TIMEOUT_M);
477871d10453SEric Joyner 
477971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
478071d10453SEric Joyner 
478171d10453SEric Joyner 	if (!status && txqs_moved)
478271d10453SEric Joyner 		*txqs_moved = cmd->num_qs;
478371d10453SEric Joyner 
478471d10453SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EAGAIN &&
478571d10453SEric Joyner 	    is_tc_change && !flush_pipe)
478671d10453SEric Joyner 		*blocked_cgds = LE32_TO_CPU(cmd->blocked_cgds);
478771d10453SEric Joyner 
478871d10453SEric Joyner 	return status;
478971d10453SEric Joyner }
479071d10453SEric Joyner 
47918a13362dSEric Joyner /**
47928a13362dSEric Joyner  * ice_aq_add_rdma_qsets
47938a13362dSEric Joyner  * @hw: pointer to the hardware structure
47948a13362dSEric Joyner  * @num_qset_grps: Number of RDMA Qset groups
47958a13362dSEric Joyner  * @qset_list: list of qset groups to be added
47968a13362dSEric Joyner  * @buf_size: size of buffer for indirect command
47978a13362dSEric Joyner  * @cd: pointer to command details structure or NULL
47988a13362dSEric Joyner  *
47998a13362dSEric Joyner  * Add Tx RDMA Qsets (0x0C33)
48008a13362dSEric Joyner  */
4801*f2635e84SEric Joyner int
48028a13362dSEric Joyner ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps,
48038a13362dSEric Joyner 		      struct ice_aqc_add_rdma_qset_data *qset_list,
48048a13362dSEric Joyner 		      u16 buf_size, struct ice_sq_cd *cd)
48058a13362dSEric Joyner {
48068a13362dSEric Joyner 	struct ice_aqc_add_rdma_qset_data *list;
48078a13362dSEric Joyner 	struct ice_aqc_add_rdma_qset *cmd;
48088a13362dSEric Joyner 	struct ice_aq_desc desc;
48098a13362dSEric Joyner 	u16 i, sum_size = 0;
48108a13362dSEric Joyner 
48118a13362dSEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
48128a13362dSEric Joyner 
48138a13362dSEric Joyner 	cmd = &desc.params.add_rdma_qset;
48148a13362dSEric Joyner 
48158a13362dSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_rdma_qset);
48168a13362dSEric Joyner 
48178a13362dSEric Joyner 	if (!qset_list)
48188a13362dSEric Joyner 		return ICE_ERR_PARAM;
48198a13362dSEric Joyner 
48208a13362dSEric Joyner 	if (num_qset_grps > ICE_LAN_TXQ_MAX_QGRPS)
48218a13362dSEric Joyner 		return ICE_ERR_PARAM;
48228a13362dSEric Joyner 
48238a13362dSEric Joyner 	for (i = 0, list = qset_list; i < num_qset_grps; i++) {
48248a13362dSEric Joyner 		u16 num_qsets = LE16_TO_CPU(list->num_qsets);
48258a13362dSEric Joyner 
48268a13362dSEric Joyner 		sum_size += ice_struct_size(list, rdma_qsets, num_qsets);
48278a13362dSEric Joyner 		list = (struct ice_aqc_add_rdma_qset_data *)(list->rdma_qsets +
48288a13362dSEric Joyner 							     num_qsets);
48298a13362dSEric Joyner 	}
48308a13362dSEric Joyner 
48318a13362dSEric Joyner 	if (buf_size != sum_size)
48328a13362dSEric Joyner 		return ICE_ERR_PARAM;
48338a13362dSEric Joyner 
48348a13362dSEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
48358a13362dSEric Joyner 
48368a13362dSEric Joyner 	cmd->num_qset_grps = num_qset_grps;
48378a13362dSEric Joyner 
48388a13362dSEric Joyner 	return ice_aq_send_cmd(hw, &desc, qset_list, buf_size, cd);
48398a13362dSEric Joyner }
48408a13362dSEric Joyner 
484171d10453SEric Joyner /* End of FW Admin Queue command wrappers */
484271d10453SEric Joyner 
484371d10453SEric Joyner /**
484471d10453SEric Joyner  * ice_write_byte - write a byte to a packed context structure
484571d10453SEric Joyner  * @src_ctx:  the context structure to read from
484671d10453SEric Joyner  * @dest_ctx: the context to be written to
484771d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
484871d10453SEric Joyner  */
484971d10453SEric Joyner static void
485071d10453SEric Joyner ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
485171d10453SEric Joyner {
485271d10453SEric Joyner 	u8 src_byte, dest_byte, mask;
485371d10453SEric Joyner 	u8 *from, *dest;
485471d10453SEric Joyner 	u16 shift_width;
485571d10453SEric Joyner 
485671d10453SEric Joyner 	/* copy from the next struct field */
485771d10453SEric Joyner 	from = src_ctx + ce_info->offset;
485871d10453SEric Joyner 
485971d10453SEric Joyner 	/* prepare the bits and mask */
486071d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
486171d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
486271d10453SEric Joyner 
486371d10453SEric Joyner 	src_byte = *from;
486471d10453SEric Joyner 	src_byte &= mask;
486571d10453SEric Joyner 
486671d10453SEric Joyner 	/* shift to correct alignment */
486771d10453SEric Joyner 	mask <<= shift_width;
486871d10453SEric Joyner 	src_byte <<= shift_width;
486971d10453SEric Joyner 
487071d10453SEric Joyner 	/* get the current bits from the target bit string */
487171d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
487271d10453SEric Joyner 
4873*f2635e84SEric Joyner 	ice_memcpy(&dest_byte, dest, sizeof(dest_byte), ICE_NONDMA_TO_NONDMA);
487471d10453SEric Joyner 
487571d10453SEric Joyner 	dest_byte &= ~mask;	/* get the bits not changing */
487671d10453SEric Joyner 	dest_byte |= src_byte;	/* add in the new bits */
487771d10453SEric Joyner 
487871d10453SEric Joyner 	/* put it all back */
4879*f2635e84SEric Joyner 	ice_memcpy(dest, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_NONDMA);
488071d10453SEric Joyner }
488171d10453SEric Joyner 
488271d10453SEric Joyner /**
488371d10453SEric Joyner  * ice_write_word - write a word to a packed context structure
488471d10453SEric Joyner  * @src_ctx:  the context structure to read from
488571d10453SEric Joyner  * @dest_ctx: the context to be written to
488671d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
488771d10453SEric Joyner  */
488871d10453SEric Joyner static void
488971d10453SEric Joyner ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
489071d10453SEric Joyner {
489171d10453SEric Joyner 	u16 src_word, mask;
489271d10453SEric Joyner 	__le16 dest_word;
489371d10453SEric Joyner 	u8 *from, *dest;
489471d10453SEric Joyner 	u16 shift_width;
489571d10453SEric Joyner 
489671d10453SEric Joyner 	/* copy from the next struct field */
489771d10453SEric Joyner 	from = src_ctx + ce_info->offset;
489871d10453SEric Joyner 
489971d10453SEric Joyner 	/* prepare the bits and mask */
490071d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
490171d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
490271d10453SEric Joyner 
490371d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
490471d10453SEric Joyner 	 * will be in a different bit position on big endian machines
490571d10453SEric Joyner 	 */
490671d10453SEric Joyner 	src_word = *(u16 *)from;
490771d10453SEric Joyner 	src_word &= mask;
490871d10453SEric Joyner 
490971d10453SEric Joyner 	/* shift to correct alignment */
491071d10453SEric Joyner 	mask <<= shift_width;
491171d10453SEric Joyner 	src_word <<= shift_width;
491271d10453SEric Joyner 
491371d10453SEric Joyner 	/* get the current bits from the target bit string */
491471d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
491571d10453SEric Joyner 
4916*f2635e84SEric Joyner 	ice_memcpy(&dest_word, dest, sizeof(dest_word), ICE_NONDMA_TO_NONDMA);
491771d10453SEric Joyner 
491871d10453SEric Joyner 	dest_word &= ~(CPU_TO_LE16(mask));	/* get the bits not changing */
491971d10453SEric Joyner 	dest_word |= CPU_TO_LE16(src_word);	/* add in the new bits */
492071d10453SEric Joyner 
492171d10453SEric Joyner 	/* put it all back */
4922*f2635e84SEric Joyner 	ice_memcpy(dest, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_NONDMA);
492371d10453SEric Joyner }
492471d10453SEric Joyner 
492571d10453SEric Joyner /**
492671d10453SEric Joyner  * ice_write_dword - write a dword to a packed context structure
492771d10453SEric Joyner  * @src_ctx:  the context structure to read from
492871d10453SEric Joyner  * @dest_ctx: the context to be written to
492971d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
493071d10453SEric Joyner  */
493171d10453SEric Joyner static void
493271d10453SEric Joyner ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
493371d10453SEric Joyner {
493471d10453SEric Joyner 	u32 src_dword, mask;
493571d10453SEric Joyner 	__le32 dest_dword;
493671d10453SEric Joyner 	u8 *from, *dest;
493771d10453SEric Joyner 	u16 shift_width;
493871d10453SEric Joyner 
493971d10453SEric Joyner 	/* copy from the next struct field */
494071d10453SEric Joyner 	from = src_ctx + ce_info->offset;
494171d10453SEric Joyner 
494271d10453SEric Joyner 	/* prepare the bits and mask */
494371d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
494471d10453SEric Joyner 
494571d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
494671d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
494771d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
494871d10453SEric Joyner 	 */
494971d10453SEric Joyner 	if (ce_info->width < 32)
495071d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
495171d10453SEric Joyner 	else
495271d10453SEric Joyner 		mask = (u32)~0;
495371d10453SEric Joyner 
495471d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
495571d10453SEric Joyner 	 * will be in a different bit position on big endian machines
495671d10453SEric Joyner 	 */
495771d10453SEric Joyner 	src_dword = *(u32 *)from;
495871d10453SEric Joyner 	src_dword &= mask;
495971d10453SEric Joyner 
496071d10453SEric Joyner 	/* shift to correct alignment */
496171d10453SEric Joyner 	mask <<= shift_width;
496271d10453SEric Joyner 	src_dword <<= shift_width;
496371d10453SEric Joyner 
496471d10453SEric Joyner 	/* get the current bits from the target bit string */
496571d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
496671d10453SEric Joyner 
4967*f2635e84SEric Joyner 	ice_memcpy(&dest_dword, dest, sizeof(dest_dword), ICE_NONDMA_TO_NONDMA);
496871d10453SEric Joyner 
496971d10453SEric Joyner 	dest_dword &= ~(CPU_TO_LE32(mask));	/* get the bits not changing */
497071d10453SEric Joyner 	dest_dword |= CPU_TO_LE32(src_dword);	/* add in the new bits */
497171d10453SEric Joyner 
497271d10453SEric Joyner 	/* put it all back */
4973*f2635e84SEric Joyner 	ice_memcpy(dest, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_NONDMA);
497471d10453SEric Joyner }
497571d10453SEric Joyner 
497671d10453SEric Joyner /**
497771d10453SEric Joyner  * ice_write_qword - write a qword to a packed context structure
497871d10453SEric Joyner  * @src_ctx:  the context structure to read from
497971d10453SEric Joyner  * @dest_ctx: the context to be written to
498071d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
498171d10453SEric Joyner  */
498271d10453SEric Joyner static void
498371d10453SEric Joyner ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
498471d10453SEric Joyner {
498571d10453SEric Joyner 	u64 src_qword, mask;
498671d10453SEric Joyner 	__le64 dest_qword;
498771d10453SEric Joyner 	u8 *from, *dest;
498871d10453SEric Joyner 	u16 shift_width;
498971d10453SEric Joyner 
499071d10453SEric Joyner 	/* copy from the next struct field */
499171d10453SEric Joyner 	from = src_ctx + ce_info->offset;
499271d10453SEric Joyner 
499371d10453SEric Joyner 	/* prepare the bits and mask */
499471d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
499571d10453SEric Joyner 
499671d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
499771d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
499871d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
499971d10453SEric Joyner 	 */
500071d10453SEric Joyner 	if (ce_info->width < 64)
500171d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
500271d10453SEric Joyner 	else
500371d10453SEric Joyner 		mask = (u64)~0;
500471d10453SEric Joyner 
500571d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
500671d10453SEric Joyner 	 * will be in a different bit position on big endian machines
500771d10453SEric Joyner 	 */
500871d10453SEric Joyner 	src_qword = *(u64 *)from;
500971d10453SEric Joyner 	src_qword &= mask;
501071d10453SEric Joyner 
501171d10453SEric Joyner 	/* shift to correct alignment */
501271d10453SEric Joyner 	mask <<= shift_width;
501371d10453SEric Joyner 	src_qword <<= shift_width;
501471d10453SEric Joyner 
501571d10453SEric Joyner 	/* get the current bits from the target bit string */
501671d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
501771d10453SEric Joyner 
5018*f2635e84SEric Joyner 	ice_memcpy(&dest_qword, dest, sizeof(dest_qword), ICE_NONDMA_TO_NONDMA);
501971d10453SEric Joyner 
502071d10453SEric Joyner 	dest_qword &= ~(CPU_TO_LE64(mask));	/* get the bits not changing */
502171d10453SEric Joyner 	dest_qword |= CPU_TO_LE64(src_qword);	/* add in the new bits */
502271d10453SEric Joyner 
502371d10453SEric Joyner 	/* put it all back */
5024*f2635e84SEric Joyner 	ice_memcpy(dest, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_NONDMA);
502571d10453SEric Joyner }
502671d10453SEric Joyner 
502771d10453SEric Joyner /**
502871d10453SEric Joyner  * ice_set_ctx - set context bits in packed structure
50297d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
503071d10453SEric Joyner  * @src_ctx:  pointer to a generic non-packed context structure
503171d10453SEric Joyner  * @dest_ctx: pointer to memory for the packed structure
503271d10453SEric Joyner  * @ce_info:  a description of the structure to be transformed
503371d10453SEric Joyner  */
5034*f2635e84SEric Joyner int
50357d7af7f8SEric Joyner ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
50367d7af7f8SEric Joyner 	    const struct ice_ctx_ele *ce_info)
503771d10453SEric Joyner {
503871d10453SEric Joyner 	int f;
503971d10453SEric Joyner 
504071d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
504171d10453SEric Joyner 		/* We have to deal with each element of the FW response
504271d10453SEric Joyner 		 * using the correct size so that we are correct regardless
504371d10453SEric Joyner 		 * of the endianness of the machine.
504471d10453SEric Joyner 		 */
50457d7af7f8SEric Joyner 		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
50467d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
50477d7af7f8SEric Joyner 				  f, ce_info[f].width, ce_info[f].size_of);
50487d7af7f8SEric Joyner 			continue;
50497d7af7f8SEric Joyner 		}
505071d10453SEric Joyner 		switch (ce_info[f].size_of) {
505171d10453SEric Joyner 		case sizeof(u8):
505271d10453SEric Joyner 			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
505371d10453SEric Joyner 			break;
505471d10453SEric Joyner 		case sizeof(u16):
505571d10453SEric Joyner 			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
505671d10453SEric Joyner 			break;
505771d10453SEric Joyner 		case sizeof(u32):
505871d10453SEric Joyner 			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
505971d10453SEric Joyner 			break;
506071d10453SEric Joyner 		case sizeof(u64):
506171d10453SEric Joyner 			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
506271d10453SEric Joyner 			break;
506371d10453SEric Joyner 		default:
506471d10453SEric Joyner 			return ICE_ERR_INVAL_SIZE;
506571d10453SEric Joyner 		}
506671d10453SEric Joyner 	}
506771d10453SEric Joyner 
5068*f2635e84SEric Joyner 	return 0;
506971d10453SEric Joyner }
507071d10453SEric Joyner 
507171d10453SEric Joyner /**
507256429daeSEric Joyner  * ice_aq_get_internal_data
507356429daeSEric Joyner  * @hw: pointer to the hardware structure
507456429daeSEric Joyner  * @cluster_id: specific cluster to dump
507556429daeSEric Joyner  * @table_id: table ID within cluster
507656429daeSEric Joyner  * @start: index of line in the block to read
507756429daeSEric Joyner  * @buf: dump buffer
507856429daeSEric Joyner  * @buf_size: dump buffer size
507956429daeSEric Joyner  * @ret_buf_size: return buffer size (returned by FW)
50809e54973fSEric Joyner  * @ret_next_cluster: next cluster to read (returned by FW)
508156429daeSEric Joyner  * @ret_next_table: next block to read (returned by FW)
508256429daeSEric Joyner  * @ret_next_index: next index to read (returned by FW)
508356429daeSEric Joyner  * @cd: pointer to command details structure
508456429daeSEric Joyner  *
508556429daeSEric Joyner  * Get internal FW/HW data (0xFF08) for debug purposes.
508656429daeSEric Joyner  */
5087*f2635e84SEric Joyner int
50889e54973fSEric Joyner ice_aq_get_internal_data(struct ice_hw *hw, u16 cluster_id, u16 table_id,
508956429daeSEric Joyner 			 u32 start, void *buf, u16 buf_size, u16 *ret_buf_size,
50909e54973fSEric Joyner 			 u16 *ret_next_cluster, u16 *ret_next_table,
50919e54973fSEric Joyner 			 u32 *ret_next_index, struct ice_sq_cd *cd)
509256429daeSEric Joyner {
509356429daeSEric Joyner 	struct ice_aqc_debug_dump_internals *cmd;
509456429daeSEric Joyner 	struct ice_aq_desc desc;
5095*f2635e84SEric Joyner 	int status;
509656429daeSEric Joyner 
509756429daeSEric Joyner 	cmd = &desc.params.debug_dump;
509856429daeSEric Joyner 
509956429daeSEric Joyner 	if (buf_size == 0 || !buf)
510056429daeSEric Joyner 		return ICE_ERR_PARAM;
510156429daeSEric Joyner 
510256429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_debug_dump_internals);
510356429daeSEric Joyner 
51049e54973fSEric Joyner 	cmd->cluster_id = CPU_TO_LE16(cluster_id);
510556429daeSEric Joyner 	cmd->table_id = CPU_TO_LE16(table_id);
510656429daeSEric Joyner 	cmd->idx = CPU_TO_LE32(start);
510756429daeSEric Joyner 
510856429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
510956429daeSEric Joyner 
511056429daeSEric Joyner 	if (!status) {
511156429daeSEric Joyner 		if (ret_buf_size)
511256429daeSEric Joyner 			*ret_buf_size = LE16_TO_CPU(desc.datalen);
51139e54973fSEric Joyner 		if (ret_next_cluster)
51149e54973fSEric Joyner 			*ret_next_cluster = LE16_TO_CPU(cmd->cluster_id);
511556429daeSEric Joyner 		if (ret_next_table)
511656429daeSEric Joyner 			*ret_next_table = LE16_TO_CPU(cmd->table_id);
511756429daeSEric Joyner 		if (ret_next_index)
511856429daeSEric Joyner 			*ret_next_index = LE32_TO_CPU(cmd->idx);
511956429daeSEric Joyner 	}
512056429daeSEric Joyner 
512156429daeSEric Joyner 	return status;
512256429daeSEric Joyner }
512356429daeSEric Joyner 
512456429daeSEric Joyner /**
512571d10453SEric Joyner  * ice_read_byte - read context byte into struct
512671d10453SEric Joyner  * @src_ctx:  the context structure to read from
512771d10453SEric Joyner  * @dest_ctx: the context to be written to
512871d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
512971d10453SEric Joyner  */
513071d10453SEric Joyner static void
51319dc2f6e2SEric Joyner ice_read_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
513271d10453SEric Joyner {
513371d10453SEric Joyner 	u8 dest_byte, mask;
513471d10453SEric Joyner 	u8 *src, *target;
513571d10453SEric Joyner 	u16 shift_width;
513671d10453SEric Joyner 
513771d10453SEric Joyner 	/* prepare the bits and mask */
513871d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
513971d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
514071d10453SEric Joyner 
514171d10453SEric Joyner 	/* shift to correct alignment */
514271d10453SEric Joyner 	mask <<= shift_width;
514371d10453SEric Joyner 
514471d10453SEric Joyner 	/* get the current bits from the src bit string */
514571d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
514671d10453SEric Joyner 
5147*f2635e84SEric Joyner 	ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_NONDMA_TO_NONDMA);
514871d10453SEric Joyner 
51499dc2f6e2SEric Joyner 	dest_byte &= mask;
515071d10453SEric Joyner 
515171d10453SEric Joyner 	dest_byte >>= shift_width;
515271d10453SEric Joyner 
515371d10453SEric Joyner 	/* get the address from the struct field */
515471d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
515571d10453SEric Joyner 
515671d10453SEric Joyner 	/* put it back in the struct */
5157*f2635e84SEric Joyner 	ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_NONDMA);
515871d10453SEric Joyner }
515971d10453SEric Joyner 
516071d10453SEric Joyner /**
516171d10453SEric Joyner  * ice_read_word - read context word into struct
516271d10453SEric Joyner  * @src_ctx:  the context structure to read from
516371d10453SEric Joyner  * @dest_ctx: the context to be written to
516471d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
516571d10453SEric Joyner  */
516671d10453SEric Joyner static void
51679dc2f6e2SEric Joyner ice_read_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
516871d10453SEric Joyner {
516971d10453SEric Joyner 	u16 dest_word, mask;
517071d10453SEric Joyner 	u8 *src, *target;
517171d10453SEric Joyner 	__le16 src_word;
517271d10453SEric Joyner 	u16 shift_width;
517371d10453SEric Joyner 
517471d10453SEric Joyner 	/* prepare the bits and mask */
517571d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
517671d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
517771d10453SEric Joyner 
517871d10453SEric Joyner 	/* shift to correct alignment */
517971d10453SEric Joyner 	mask <<= shift_width;
518071d10453SEric Joyner 
518171d10453SEric Joyner 	/* get the current bits from the src bit string */
518271d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
518371d10453SEric Joyner 
5184*f2635e84SEric Joyner 	ice_memcpy(&src_word, src, sizeof(src_word), ICE_NONDMA_TO_NONDMA);
518571d10453SEric Joyner 
518671d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
518771d10453SEric Joyner 	 * correctly
518871d10453SEric Joyner 	 */
51899dc2f6e2SEric Joyner 	src_word &= CPU_TO_LE16(mask);
519071d10453SEric Joyner 
519171d10453SEric Joyner 	/* get the data back into host order before shifting */
519271d10453SEric Joyner 	dest_word = LE16_TO_CPU(src_word);
519371d10453SEric Joyner 
519471d10453SEric Joyner 	dest_word >>= shift_width;
519571d10453SEric Joyner 
519671d10453SEric Joyner 	/* get the address from the struct field */
519771d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
519871d10453SEric Joyner 
519971d10453SEric Joyner 	/* put it back in the struct */
5200*f2635e84SEric Joyner 	ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_NONDMA);
520171d10453SEric Joyner }
520271d10453SEric Joyner 
520371d10453SEric Joyner /**
520471d10453SEric Joyner  * ice_read_dword - read context dword into struct
520571d10453SEric Joyner  * @src_ctx:  the context structure to read from
520671d10453SEric Joyner  * @dest_ctx: the context to be written to
520771d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
520871d10453SEric Joyner  */
520971d10453SEric Joyner static void
52109dc2f6e2SEric Joyner ice_read_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
521171d10453SEric Joyner {
521271d10453SEric Joyner 	u32 dest_dword, mask;
521371d10453SEric Joyner 	__le32 src_dword;
521471d10453SEric Joyner 	u8 *src, *target;
521571d10453SEric Joyner 	u16 shift_width;
521671d10453SEric Joyner 
521771d10453SEric Joyner 	/* prepare the bits and mask */
521871d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
521971d10453SEric Joyner 
522071d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
522171d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
522271d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
522371d10453SEric Joyner 	 */
522471d10453SEric Joyner 	if (ce_info->width < 32)
522571d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
522671d10453SEric Joyner 	else
522771d10453SEric Joyner 		mask = (u32)~0;
522871d10453SEric Joyner 
522971d10453SEric Joyner 	/* shift to correct alignment */
523071d10453SEric Joyner 	mask <<= shift_width;
523171d10453SEric Joyner 
523271d10453SEric Joyner 	/* get the current bits from the src bit string */
523371d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
523471d10453SEric Joyner 
5235*f2635e84SEric Joyner 	ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_NONDMA_TO_NONDMA);
523671d10453SEric Joyner 
523771d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
523871d10453SEric Joyner 	 * correctly
523971d10453SEric Joyner 	 */
52409dc2f6e2SEric Joyner 	src_dword &= CPU_TO_LE32(mask);
524171d10453SEric Joyner 
524271d10453SEric Joyner 	/* get the data back into host order before shifting */
524371d10453SEric Joyner 	dest_dword = LE32_TO_CPU(src_dword);
524471d10453SEric Joyner 
524571d10453SEric Joyner 	dest_dword >>= shift_width;
524671d10453SEric Joyner 
524771d10453SEric Joyner 	/* get the address from the struct field */
524871d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
524971d10453SEric Joyner 
525071d10453SEric Joyner 	/* put it back in the struct */
5251*f2635e84SEric Joyner 	ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_NONDMA);
525271d10453SEric Joyner }
525371d10453SEric Joyner 
525471d10453SEric Joyner /**
525571d10453SEric Joyner  * ice_read_qword - read context qword into struct
525671d10453SEric Joyner  * @src_ctx:  the context structure to read from
525771d10453SEric Joyner  * @dest_ctx: the context to be written to
525871d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
525971d10453SEric Joyner  */
526071d10453SEric Joyner static void
52619dc2f6e2SEric Joyner ice_read_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
526271d10453SEric Joyner {
526371d10453SEric Joyner 	u64 dest_qword, mask;
526471d10453SEric Joyner 	__le64 src_qword;
526571d10453SEric Joyner 	u8 *src, *target;
526671d10453SEric Joyner 	u16 shift_width;
526771d10453SEric Joyner 
526871d10453SEric Joyner 	/* prepare the bits and mask */
526971d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
527071d10453SEric Joyner 
527171d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
527271d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
527371d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
527471d10453SEric Joyner 	 */
527571d10453SEric Joyner 	if (ce_info->width < 64)
527671d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
527771d10453SEric Joyner 	else
527871d10453SEric Joyner 		mask = (u64)~0;
527971d10453SEric Joyner 
528071d10453SEric Joyner 	/* shift to correct alignment */
528171d10453SEric Joyner 	mask <<= shift_width;
528271d10453SEric Joyner 
528371d10453SEric Joyner 	/* get the current bits from the src bit string */
528471d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
528571d10453SEric Joyner 
5286*f2635e84SEric Joyner 	ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_NONDMA_TO_NONDMA);
528771d10453SEric Joyner 
528871d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
528971d10453SEric Joyner 	 * correctly
529071d10453SEric Joyner 	 */
52919dc2f6e2SEric Joyner 	src_qword &= CPU_TO_LE64(mask);
529271d10453SEric Joyner 
529371d10453SEric Joyner 	/* get the data back into host order before shifting */
529471d10453SEric Joyner 	dest_qword = LE64_TO_CPU(src_qword);
529571d10453SEric Joyner 
529671d10453SEric Joyner 	dest_qword >>= shift_width;
529771d10453SEric Joyner 
529871d10453SEric Joyner 	/* get the address from the struct field */
529971d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
530071d10453SEric Joyner 
530171d10453SEric Joyner 	/* put it back in the struct */
5302*f2635e84SEric Joyner 	ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_NONDMA);
530371d10453SEric Joyner }
530471d10453SEric Joyner 
530571d10453SEric Joyner /**
530671d10453SEric Joyner  * ice_get_ctx - extract context bits from a packed structure
530771d10453SEric Joyner  * @src_ctx:  pointer to a generic packed context structure
530871d10453SEric Joyner  * @dest_ctx: pointer to a generic non-packed context structure
530971d10453SEric Joyner  * @ce_info:  a description of the structure to be read from
531071d10453SEric Joyner  */
5311*f2635e84SEric Joyner int
53129dc2f6e2SEric Joyner ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
531371d10453SEric Joyner {
531471d10453SEric Joyner 	int f;
531571d10453SEric Joyner 
531671d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
531771d10453SEric Joyner 		switch (ce_info[f].size_of) {
531871d10453SEric Joyner 		case 1:
531971d10453SEric Joyner 			ice_read_byte(src_ctx, dest_ctx, &ce_info[f]);
532071d10453SEric Joyner 			break;
532171d10453SEric Joyner 		case 2:
532271d10453SEric Joyner 			ice_read_word(src_ctx, dest_ctx, &ce_info[f]);
532371d10453SEric Joyner 			break;
532471d10453SEric Joyner 		case 4:
532571d10453SEric Joyner 			ice_read_dword(src_ctx, dest_ctx, &ce_info[f]);
532671d10453SEric Joyner 			break;
532771d10453SEric Joyner 		case 8:
532871d10453SEric Joyner 			ice_read_qword(src_ctx, dest_ctx, &ce_info[f]);
532971d10453SEric Joyner 			break;
533071d10453SEric Joyner 		default:
533171d10453SEric Joyner 			/* nothing to do, just keep going */
533271d10453SEric Joyner 			break;
533371d10453SEric Joyner 		}
533471d10453SEric Joyner 	}
533571d10453SEric Joyner 
5336*f2635e84SEric Joyner 	return 0;
533771d10453SEric Joyner }
533871d10453SEric Joyner 
533971d10453SEric Joyner /**
534071d10453SEric Joyner  * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
534171d10453SEric Joyner  * @hw: pointer to the HW struct
534271d10453SEric Joyner  * @vsi_handle: software VSI handle
534371d10453SEric Joyner  * @tc: TC number
534471d10453SEric Joyner  * @q_handle: software queue handle
534571d10453SEric Joyner  */
534671d10453SEric Joyner struct ice_q_ctx *
534771d10453SEric Joyner ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
534871d10453SEric Joyner {
534971d10453SEric Joyner 	struct ice_vsi_ctx *vsi;
535071d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
535171d10453SEric Joyner 
535271d10453SEric Joyner 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
535371d10453SEric Joyner 	if (!vsi)
535471d10453SEric Joyner 		return NULL;
535571d10453SEric Joyner 	if (q_handle >= vsi->num_lan_q_entries[tc])
535671d10453SEric Joyner 		return NULL;
535771d10453SEric Joyner 	if (!vsi->lan_q_ctx[tc])
535871d10453SEric Joyner 		return NULL;
535971d10453SEric Joyner 	q_ctx = vsi->lan_q_ctx[tc];
536071d10453SEric Joyner 	return &q_ctx[q_handle];
536171d10453SEric Joyner }
536271d10453SEric Joyner 
536371d10453SEric Joyner /**
536471d10453SEric Joyner  * ice_ena_vsi_txq
536571d10453SEric Joyner  * @pi: port information structure
536671d10453SEric Joyner  * @vsi_handle: software VSI handle
536771d10453SEric Joyner  * @tc: TC number
536871d10453SEric Joyner  * @q_handle: software queue handle
536971d10453SEric Joyner  * @num_qgrps: Number of added queue groups
537071d10453SEric Joyner  * @buf: list of queue groups to be added
537171d10453SEric Joyner  * @buf_size: size of buffer for indirect command
537271d10453SEric Joyner  * @cd: pointer to command details structure or NULL
537371d10453SEric Joyner  *
537471d10453SEric Joyner  * This function adds one LAN queue
537571d10453SEric Joyner  */
5376*f2635e84SEric Joyner int
537771d10453SEric Joyner ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
537871d10453SEric Joyner 		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
537971d10453SEric Joyner 		struct ice_sq_cd *cd)
538071d10453SEric Joyner {
538171d10453SEric Joyner 	struct ice_aqc_txsched_elem_data node = { 0 };
538271d10453SEric Joyner 	struct ice_sched_node *parent;
538371d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
538471d10453SEric Joyner 	struct ice_hw *hw;
5385*f2635e84SEric Joyner 	int status;
538671d10453SEric Joyner 
538771d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
538871d10453SEric Joyner 		return ICE_ERR_CFG;
538971d10453SEric Joyner 
539071d10453SEric Joyner 	if (num_qgrps > 1 || buf->num_txqs > 1)
539171d10453SEric Joyner 		return ICE_ERR_MAX_LIMIT;
539271d10453SEric Joyner 
539371d10453SEric Joyner 	hw = pi->hw;
539471d10453SEric Joyner 
539571d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
539671d10453SEric Joyner 		return ICE_ERR_PARAM;
539771d10453SEric Joyner 
539871d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
539971d10453SEric Joyner 
540071d10453SEric Joyner 	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
540171d10453SEric Joyner 	if (!q_ctx) {
540271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
540371d10453SEric Joyner 			  q_handle);
540471d10453SEric Joyner 		status = ICE_ERR_PARAM;
540571d10453SEric Joyner 		goto ena_txq_exit;
540671d10453SEric Joyner 	}
540771d10453SEric Joyner 
540871d10453SEric Joyner 	/* find a parent node */
540971d10453SEric Joyner 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
541071d10453SEric Joyner 					    ICE_SCHED_NODE_OWNER_LAN);
541171d10453SEric Joyner 	if (!parent) {
541271d10453SEric Joyner 		status = ICE_ERR_PARAM;
541371d10453SEric Joyner 		goto ena_txq_exit;
541471d10453SEric Joyner 	}
541571d10453SEric Joyner 
541671d10453SEric Joyner 	buf->parent_teid = parent->info.node_teid;
541771d10453SEric Joyner 	node.parent_teid = parent->info.node_teid;
541871d10453SEric Joyner 	/* Mark that the values in the "generic" section as valid. The default
541971d10453SEric Joyner 	 * value in the "generic" section is zero. This means that :
542071d10453SEric Joyner 	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
542171d10453SEric Joyner 	 * - 0 priority among siblings, indicated by Bit 1-3.
542271d10453SEric Joyner 	 * - WFQ, indicated by Bit 4.
542371d10453SEric Joyner 	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
542471d10453SEric Joyner 	 * Bit 5-6.
542571d10453SEric Joyner 	 * - Bit 7 is reserved.
542671d10453SEric Joyner 	 * Without setting the generic section as valid in valid_sections, the
542771d10453SEric Joyner 	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
542871d10453SEric Joyner 	 */
54297d7af7f8SEric Joyner 	buf->txqs[0].info.valid_sections =
54307d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
54317d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_EIR;
54327d7af7f8SEric Joyner 	buf->txqs[0].info.generic = 0;
54337d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_profile_idx =
54347d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
54357d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_alloc =
54367d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
54377d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_profile_idx =
54387d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
54397d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_alloc =
54407d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
544171d10453SEric Joyner 
544271d10453SEric Joyner 	/* add the LAN queue */
544371d10453SEric Joyner 	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
5444*f2635e84SEric Joyner 	if (status) {
544571d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
544671d10453SEric Joyner 			  LE16_TO_CPU(buf->txqs[0].txq_id),
544771d10453SEric Joyner 			  hw->adminq.sq_last_status);
544871d10453SEric Joyner 		goto ena_txq_exit;
544971d10453SEric Joyner 	}
545071d10453SEric Joyner 
545171d10453SEric Joyner 	node.node_teid = buf->txqs[0].q_teid;
545271d10453SEric Joyner 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
545371d10453SEric Joyner 	q_ctx->q_handle = q_handle;
545471d10453SEric Joyner 	q_ctx->q_teid = LE32_TO_CPU(node.node_teid);
545571d10453SEric Joyner 
545671d10453SEric Joyner 	/* add a leaf node into scheduler tree queue layer */
54579c30461dSEric Joyner 	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node, NULL);
545871d10453SEric Joyner 	if (!status)
545971d10453SEric Joyner 		status = ice_sched_replay_q_bw(pi, q_ctx);
546071d10453SEric Joyner 
546171d10453SEric Joyner ena_txq_exit:
546271d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
546371d10453SEric Joyner 	return status;
546471d10453SEric Joyner }
546571d10453SEric Joyner 
546671d10453SEric Joyner /**
546771d10453SEric Joyner  * ice_dis_vsi_txq
546871d10453SEric Joyner  * @pi: port information structure
546971d10453SEric Joyner  * @vsi_handle: software VSI handle
547071d10453SEric Joyner  * @tc: TC number
547171d10453SEric Joyner  * @num_queues: number of queues
547271d10453SEric Joyner  * @q_handles: pointer to software queue handle array
547371d10453SEric Joyner  * @q_ids: pointer to the q_id array
547471d10453SEric Joyner  * @q_teids: pointer to queue node teids
547571d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
547671d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
547771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
547871d10453SEric Joyner  *
547971d10453SEric Joyner  * This function removes queues and their corresponding nodes in SW DB
548071d10453SEric Joyner  */
5481*f2635e84SEric Joyner int
548271d10453SEric Joyner ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
548371d10453SEric Joyner 		u16 *q_handles, u16 *q_ids, u32 *q_teids,
548471d10453SEric Joyner 		enum ice_disq_rst_src rst_src, u16 vmvf_num,
548571d10453SEric Joyner 		struct ice_sq_cd *cd)
548671d10453SEric Joyner {
54877d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *qg_list;
548871d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
5489*f2635e84SEric Joyner 	int status = ICE_ERR_DOES_NOT_EXIST;
54907d7af7f8SEric Joyner 	struct ice_hw *hw;
54917d7af7f8SEric Joyner 	u16 i, buf_size;
549271d10453SEric Joyner 
549371d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
549471d10453SEric Joyner 		return ICE_ERR_CFG;
549571d10453SEric Joyner 
54967d7af7f8SEric Joyner 	hw = pi->hw;
54977d7af7f8SEric Joyner 
549871d10453SEric Joyner 	if (!num_queues) {
549971d10453SEric Joyner 		/* if queue is disabled already yet the disable queue command
550071d10453SEric Joyner 		 * has to be sent to complete the VF reset, then call
550171d10453SEric Joyner 		 * ice_aq_dis_lan_txq without any queue information
550271d10453SEric Joyner 		 */
550371d10453SEric Joyner 		if (rst_src)
55047d7af7f8SEric Joyner 			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
550571d10453SEric Joyner 						  vmvf_num, NULL);
550671d10453SEric Joyner 		return ICE_ERR_CFG;
550771d10453SEric Joyner 	}
550871d10453SEric Joyner 
55097d7af7f8SEric Joyner 	buf_size = ice_struct_size(qg_list, q_id, 1);
55107d7af7f8SEric Joyner 	qg_list = (struct ice_aqc_dis_txq_item *)ice_malloc(hw, buf_size);
55117d7af7f8SEric Joyner 	if (!qg_list)
55127d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
55137d7af7f8SEric Joyner 
551471d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
551571d10453SEric Joyner 
551671d10453SEric Joyner 	for (i = 0; i < num_queues; i++) {
551771d10453SEric Joyner 		struct ice_sched_node *node;
551871d10453SEric Joyner 
551971d10453SEric Joyner 		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
552071d10453SEric Joyner 		if (!node)
552171d10453SEric Joyner 			continue;
55227d7af7f8SEric Joyner 		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
552371d10453SEric Joyner 		if (!q_ctx) {
55247d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
552571d10453SEric Joyner 				  q_handles[i]);
552671d10453SEric Joyner 			continue;
552771d10453SEric Joyner 		}
552871d10453SEric Joyner 		if (q_ctx->q_handle != q_handles[i]) {
55297d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
553071d10453SEric Joyner 				  q_ctx->q_handle, q_handles[i]);
553171d10453SEric Joyner 			continue;
553271d10453SEric Joyner 		}
55337d7af7f8SEric Joyner 		qg_list->parent_teid = node->info.parent_teid;
55347d7af7f8SEric Joyner 		qg_list->num_qs = 1;
55357d7af7f8SEric Joyner 		qg_list->q_id[0] = CPU_TO_LE16(q_ids[i]);
55367d7af7f8SEric Joyner 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
55377d7af7f8SEric Joyner 					    vmvf_num, cd);
553871d10453SEric Joyner 
5539*f2635e84SEric Joyner 		if (status)
554071d10453SEric Joyner 			break;
554171d10453SEric Joyner 		ice_free_sched_node(pi, node);
554271d10453SEric Joyner 		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
554371d10453SEric Joyner 	}
554471d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
55457d7af7f8SEric Joyner 	ice_free(hw, qg_list);
554671d10453SEric Joyner 	return status;
554771d10453SEric Joyner }
554871d10453SEric Joyner 
554971d10453SEric Joyner /**
555071d10453SEric Joyner  * ice_cfg_vsi_qs - configure the new/existing VSI queues
555171d10453SEric Joyner  * @pi: port information structure
555271d10453SEric Joyner  * @vsi_handle: software VSI handle
555371d10453SEric Joyner  * @tc_bitmap: TC bitmap
555471d10453SEric Joyner  * @maxqs: max queues array per TC
555571d10453SEric Joyner  * @owner: LAN or RDMA
555671d10453SEric Joyner  *
555771d10453SEric Joyner  * This function adds/updates the VSI queues per TC.
555871d10453SEric Joyner  */
5559*f2635e84SEric Joyner static int
556071d10453SEric Joyner ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
556171d10453SEric Joyner 	       u16 *maxqs, u8 owner)
556271d10453SEric Joyner {
5563*f2635e84SEric Joyner 	int status = 0;
556471d10453SEric Joyner 	u8 i;
556571d10453SEric Joyner 
556671d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
556771d10453SEric Joyner 		return ICE_ERR_CFG;
556871d10453SEric Joyner 
556971d10453SEric Joyner 	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
557071d10453SEric Joyner 		return ICE_ERR_PARAM;
557171d10453SEric Joyner 
557271d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
557371d10453SEric Joyner 
557471d10453SEric Joyner 	ice_for_each_traffic_class(i) {
557571d10453SEric Joyner 		/* configuration is possible only if TC node is present */
557671d10453SEric Joyner 		if (!ice_sched_get_tc_node(pi, i))
557771d10453SEric Joyner 			continue;
557871d10453SEric Joyner 
557971d10453SEric Joyner 		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
558071d10453SEric Joyner 					   ice_is_tc_ena(tc_bitmap, i));
558171d10453SEric Joyner 		if (status)
558271d10453SEric Joyner 			break;
558371d10453SEric Joyner 	}
558471d10453SEric Joyner 
558571d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
558671d10453SEric Joyner 	return status;
558771d10453SEric Joyner }
558871d10453SEric Joyner 
558971d10453SEric Joyner /**
559071d10453SEric Joyner  * ice_cfg_vsi_lan - configure VSI LAN queues
559171d10453SEric Joyner  * @pi: port information structure
559271d10453SEric Joyner  * @vsi_handle: software VSI handle
559371d10453SEric Joyner  * @tc_bitmap: TC bitmap
559471d10453SEric Joyner  * @max_lanqs: max LAN queues array per TC
559571d10453SEric Joyner  *
559671d10453SEric Joyner  * This function adds/updates the VSI LAN queues per TC.
559771d10453SEric Joyner  */
5598*f2635e84SEric Joyner int
559971d10453SEric Joyner ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
560071d10453SEric Joyner 		u16 *max_lanqs)
560171d10453SEric Joyner {
560271d10453SEric Joyner 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
560371d10453SEric Joyner 			      ICE_SCHED_NODE_OWNER_LAN);
560471d10453SEric Joyner }
560571d10453SEric Joyner 
560671d10453SEric Joyner /**
56078a13362dSEric Joyner  * ice_cfg_vsi_rdma - configure the VSI RDMA queues
56088a13362dSEric Joyner  * @pi: port information structure
56098a13362dSEric Joyner  * @vsi_handle: software VSI handle
56108a13362dSEric Joyner  * @tc_bitmap: TC bitmap
56118a13362dSEric Joyner  * @max_rdmaqs: max RDMA queues array per TC
56128a13362dSEric Joyner  *
56138a13362dSEric Joyner  * This function adds/updates the VSI RDMA queues per TC.
56148a13362dSEric Joyner  */
5615*f2635e84SEric Joyner int
56168a13362dSEric Joyner ice_cfg_vsi_rdma(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
56178a13362dSEric Joyner 		 u16 *max_rdmaqs)
56188a13362dSEric Joyner {
56198a13362dSEric Joyner 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_rdmaqs,
56208a13362dSEric Joyner 			      ICE_SCHED_NODE_OWNER_RDMA);
56218a13362dSEric Joyner }
56228a13362dSEric Joyner 
56238a13362dSEric Joyner /**
56248a13362dSEric Joyner  * ice_ena_vsi_rdma_qset
56258a13362dSEric Joyner  * @pi: port information structure
56268a13362dSEric Joyner  * @vsi_handle: software VSI handle
56278a13362dSEric Joyner  * @tc: TC number
56288a13362dSEric Joyner  * @rdma_qset: pointer to RDMA qset
56298a13362dSEric Joyner  * @num_qsets: number of RDMA qsets
56308a13362dSEric Joyner  * @qset_teid: pointer to qset node teids
56318a13362dSEric Joyner  *
56328a13362dSEric Joyner  * This function adds RDMA qset
56338a13362dSEric Joyner  */
5634*f2635e84SEric Joyner int
56358a13362dSEric Joyner ice_ena_vsi_rdma_qset(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
56368a13362dSEric Joyner 		      u16 *rdma_qset, u16 num_qsets, u32 *qset_teid)
56378a13362dSEric Joyner {
56388a13362dSEric Joyner 	struct ice_aqc_txsched_elem_data node = { 0 };
56398a13362dSEric Joyner 	struct ice_aqc_add_rdma_qset_data *buf;
56408a13362dSEric Joyner 	struct ice_sched_node *parent;
56418a13362dSEric Joyner 	struct ice_hw *hw;
56428a13362dSEric Joyner 	u16 i, buf_size;
5643*f2635e84SEric Joyner 	int status;
56448a13362dSEric Joyner 
56458a13362dSEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
56468a13362dSEric Joyner 		return ICE_ERR_CFG;
56478a13362dSEric Joyner 	hw = pi->hw;
56488a13362dSEric Joyner 
56498a13362dSEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
56508a13362dSEric Joyner 		return ICE_ERR_PARAM;
56518a13362dSEric Joyner 
56528a13362dSEric Joyner 	buf_size = ice_struct_size(buf, rdma_qsets, num_qsets);
56538a13362dSEric Joyner 	buf = (struct ice_aqc_add_rdma_qset_data *)ice_malloc(hw, buf_size);
56548a13362dSEric Joyner 	if (!buf)
56558a13362dSEric Joyner 		return ICE_ERR_NO_MEMORY;
56568a13362dSEric Joyner 	ice_acquire_lock(&pi->sched_lock);
56578a13362dSEric Joyner 
56588a13362dSEric Joyner 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
56598a13362dSEric Joyner 					    ICE_SCHED_NODE_OWNER_RDMA);
56608a13362dSEric Joyner 	if (!parent) {
56618a13362dSEric Joyner 		status = ICE_ERR_PARAM;
56628a13362dSEric Joyner 		goto rdma_error_exit;
56638a13362dSEric Joyner 	}
56648a13362dSEric Joyner 	buf->parent_teid = parent->info.node_teid;
56658a13362dSEric Joyner 	node.parent_teid = parent->info.node_teid;
56668a13362dSEric Joyner 
56678a13362dSEric Joyner 	buf->num_qsets = CPU_TO_LE16(num_qsets);
56688a13362dSEric Joyner 	for (i = 0; i < num_qsets; i++) {
56698a13362dSEric Joyner 		buf->rdma_qsets[i].tx_qset_id = CPU_TO_LE16(rdma_qset[i]);
56708a13362dSEric Joyner 		buf->rdma_qsets[i].info.valid_sections =
56718a13362dSEric Joyner 			ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
56728a13362dSEric Joyner 			ICE_AQC_ELEM_VALID_EIR;
56738a13362dSEric Joyner 		buf->rdma_qsets[i].info.generic = 0;
56748a13362dSEric Joyner 		buf->rdma_qsets[i].info.cir_bw.bw_profile_idx =
56758a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
56768a13362dSEric Joyner 		buf->rdma_qsets[i].info.cir_bw.bw_alloc =
56778a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
56788a13362dSEric Joyner 		buf->rdma_qsets[i].info.eir_bw.bw_profile_idx =
56798a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
56808a13362dSEric Joyner 		buf->rdma_qsets[i].info.eir_bw.bw_alloc =
56818a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
56828a13362dSEric Joyner 	}
56838a13362dSEric Joyner 	status = ice_aq_add_rdma_qsets(hw, 1, buf, buf_size, NULL);
5684*f2635e84SEric Joyner 	if (status) {
56858a13362dSEric Joyner 		ice_debug(hw, ICE_DBG_RDMA, "add RDMA qset failed\n");
56868a13362dSEric Joyner 		goto rdma_error_exit;
56878a13362dSEric Joyner 	}
56888a13362dSEric Joyner 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
56898a13362dSEric Joyner 	for (i = 0; i < num_qsets; i++) {
56908a13362dSEric Joyner 		node.node_teid = buf->rdma_qsets[i].qset_teid;
56918a13362dSEric Joyner 		status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1,
56929c30461dSEric Joyner 					    &node, NULL);
56938a13362dSEric Joyner 		if (status)
56948a13362dSEric Joyner 			break;
56958a13362dSEric Joyner 		qset_teid[i] = LE32_TO_CPU(node.node_teid);
56968a13362dSEric Joyner 	}
56978a13362dSEric Joyner rdma_error_exit:
56988a13362dSEric Joyner 	ice_release_lock(&pi->sched_lock);
56998a13362dSEric Joyner 	ice_free(hw, buf);
57008a13362dSEric Joyner 	return status;
57018a13362dSEric Joyner }
57028a13362dSEric Joyner 
57038a13362dSEric Joyner /**
57048a13362dSEric Joyner  * ice_dis_vsi_rdma_qset - free RDMA resources
57058a13362dSEric Joyner  * @pi: port_info struct
57068a13362dSEric Joyner  * @count: number of RDMA qsets to free
57078a13362dSEric Joyner  * @qset_teid: TEID of qset node
57088a13362dSEric Joyner  * @q_id: list of queue IDs being disabled
57098a13362dSEric Joyner  */
5710*f2635e84SEric Joyner int
57118a13362dSEric Joyner ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
57128a13362dSEric Joyner 		      u16 *q_id)
57138a13362dSEric Joyner {
57148a13362dSEric Joyner 	struct ice_aqc_dis_txq_item *qg_list;
57158a13362dSEric Joyner 	struct ice_hw *hw;
5716*f2635e84SEric Joyner 	int status = 0;
57178a13362dSEric Joyner 	u16 qg_size;
57188a13362dSEric Joyner 	int i;
57198a13362dSEric Joyner 
57208a13362dSEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
57218a13362dSEric Joyner 		return ICE_ERR_CFG;
57228a13362dSEric Joyner 
57238a13362dSEric Joyner 	hw = pi->hw;
57248a13362dSEric Joyner 
57258a13362dSEric Joyner 	qg_size = ice_struct_size(qg_list, q_id, 1);
57268a13362dSEric Joyner 	qg_list = (struct ice_aqc_dis_txq_item *)ice_malloc(hw, qg_size);
57278a13362dSEric Joyner 	if (!qg_list)
57288a13362dSEric Joyner 		return ICE_ERR_NO_MEMORY;
57298a13362dSEric Joyner 
57308a13362dSEric Joyner 	ice_acquire_lock(&pi->sched_lock);
57318a13362dSEric Joyner 
57328a13362dSEric Joyner 	for (i = 0; i < count; i++) {
57338a13362dSEric Joyner 		struct ice_sched_node *node;
57348a13362dSEric Joyner 
57358a13362dSEric Joyner 		node = ice_sched_find_node_by_teid(pi->root, qset_teid[i]);
57368a13362dSEric Joyner 		if (!node)
57378a13362dSEric Joyner 			continue;
57388a13362dSEric Joyner 
57398a13362dSEric Joyner 		qg_list->parent_teid = node->info.parent_teid;
57408a13362dSEric Joyner 		qg_list->num_qs = 1;
57418a13362dSEric Joyner 		qg_list->q_id[0] =
57428a13362dSEric Joyner 			CPU_TO_LE16(q_id[i] |
57438a13362dSEric Joyner 				    ICE_AQC_Q_DIS_BUF_ELEM_TYPE_RDMA_QSET);
57448a13362dSEric Joyner 
57458a13362dSEric Joyner 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, qg_size,
57468a13362dSEric Joyner 					    ICE_NO_RESET, 0, NULL);
57478a13362dSEric Joyner 		if (status)
57488a13362dSEric Joyner 			break;
57498a13362dSEric Joyner 
57508a13362dSEric Joyner 		ice_free_sched_node(pi, node);
57518a13362dSEric Joyner 	}
57528a13362dSEric Joyner 
57538a13362dSEric Joyner 	ice_release_lock(&pi->sched_lock);
57548a13362dSEric Joyner 	ice_free(hw, qg_list);
57558a13362dSEric Joyner 	return status;
57568a13362dSEric Joyner }
57578a13362dSEric Joyner 
57588a13362dSEric Joyner /**
57599c30461dSEric Joyner  * ice_aq_get_sensor_reading
57609c30461dSEric Joyner  * @hw: pointer to the HW struct
57619c30461dSEric Joyner  * @sensor: sensor type
57629c30461dSEric Joyner  * @format: requested response format
57639c30461dSEric Joyner  * @data: pointer to data to be read from the sensor
57649c30461dSEric Joyner  * @cd: pointer to command details structure or NULL
57659c30461dSEric Joyner  *
57669c30461dSEric Joyner  * Get sensor reading (0x0632)
57679c30461dSEric Joyner  */
5768*f2635e84SEric Joyner int
57699c30461dSEric Joyner ice_aq_get_sensor_reading(struct ice_hw *hw, u8 sensor, u8 format,
57709c30461dSEric Joyner 			  struct ice_aqc_get_sensor_reading_resp *data,
57719c30461dSEric Joyner 			  struct ice_sq_cd *cd)
57729c30461dSEric Joyner {
57739c30461dSEric Joyner 	struct ice_aqc_get_sensor_reading *cmd;
57749c30461dSEric Joyner 	struct ice_aq_desc desc;
5775*f2635e84SEric Joyner 	int status;
57769c30461dSEric Joyner 
57779c30461dSEric Joyner 	if (!data)
57789c30461dSEric Joyner 		return ICE_ERR_PARAM;
57799c30461dSEric Joyner 
57809c30461dSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sensor_reading);
57819c30461dSEric Joyner 	cmd = &desc.params.get_sensor_reading;
57829c30461dSEric Joyner 	cmd->sensor = sensor;
57839c30461dSEric Joyner 	cmd->format = format;
57849c30461dSEric Joyner 
57859c30461dSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
57869c30461dSEric Joyner 
57879c30461dSEric Joyner 	if (!status)
57889c30461dSEric Joyner 		ice_memcpy(data, &desc.params.get_sensor_reading_resp,
57899c30461dSEric Joyner 			   sizeof(*data), ICE_NONDMA_TO_NONDMA);
57909c30461dSEric Joyner 
57919c30461dSEric Joyner 	return status;
57929c30461dSEric Joyner }
57939c30461dSEric Joyner 
57949c30461dSEric Joyner /**
57957d7af7f8SEric Joyner  * ice_is_main_vsi - checks whether the VSI is main VSI
57967d7af7f8SEric Joyner  * @hw: pointer to the HW struct
57977d7af7f8SEric Joyner  * @vsi_handle: VSI handle
57987d7af7f8SEric Joyner  *
57997d7af7f8SEric Joyner  * Checks whether the VSI is the main VSI (the first PF VSI created on
58007d7af7f8SEric Joyner  * given PF).
58017d7af7f8SEric Joyner  */
58027d7af7f8SEric Joyner static bool ice_is_main_vsi(struct ice_hw *hw, u16 vsi_handle)
58037d7af7f8SEric Joyner {
58047d7af7f8SEric Joyner 	return vsi_handle == ICE_MAIN_VSI_HANDLE && hw->vsi_ctx[vsi_handle];
58057d7af7f8SEric Joyner }
58067d7af7f8SEric Joyner 
58077d7af7f8SEric Joyner /**
580871d10453SEric Joyner  * ice_replay_pre_init - replay pre initialization
580971d10453SEric Joyner  * @hw: pointer to the HW struct
58107d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function initializes filters
581171d10453SEric Joyner  *
581271d10453SEric Joyner  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
581371d10453SEric Joyner  */
5814*f2635e84SEric Joyner int
58157d7af7f8SEric Joyner ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
581671d10453SEric Joyner {
5817*f2635e84SEric Joyner 	int status;
581871d10453SEric Joyner 	u8 i;
581971d10453SEric Joyner 
582071d10453SEric Joyner 	/* Delete old entries from replay filter list head if there is any */
58217d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
582271d10453SEric Joyner 	/* In start of replay, move entries into replay_rules list, it
582371d10453SEric Joyner 	 * will allow adding rules entries back to filt_rules list,
582471d10453SEric Joyner 	 * which is operational list.
582571d10453SEric Joyner 	 */
582671d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++)
582771d10453SEric Joyner 		LIST_REPLACE_INIT(&sw->recp_list[i].filt_rules,
582871d10453SEric Joyner 				  &sw->recp_list[i].filt_replay_rules);
582971d10453SEric Joyner 	ice_sched_replay_agg_vsi_preinit(hw);
583071d10453SEric Joyner 
58317d7af7f8SEric Joyner 	status = ice_sched_replay_root_node_bw(hw->port_info);
58327d7af7f8SEric Joyner 	if (status)
58337d7af7f8SEric Joyner 		return status;
58347d7af7f8SEric Joyner 
583571d10453SEric Joyner 	return ice_sched_replay_tc_node_bw(hw->port_info);
583671d10453SEric Joyner }
583771d10453SEric Joyner 
583871d10453SEric Joyner /**
583971d10453SEric Joyner  * ice_replay_vsi - replay VSI configuration
584071d10453SEric Joyner  * @hw: pointer to the HW struct
584171d10453SEric Joyner  * @vsi_handle: driver VSI handle
584271d10453SEric Joyner  *
584371d10453SEric Joyner  * Restore all VSI configuration after reset. It is required to call this
584471d10453SEric Joyner  * function with main VSI first.
584571d10453SEric Joyner  */
5846*f2635e84SEric Joyner int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
584771d10453SEric Joyner {
58487d7af7f8SEric Joyner 	struct ice_switch_info *sw = hw->switch_info;
58497d7af7f8SEric Joyner 	struct ice_port_info *pi = hw->port_info;
5850*f2635e84SEric Joyner 	int status;
585171d10453SEric Joyner 
585271d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
585371d10453SEric Joyner 		return ICE_ERR_PARAM;
585471d10453SEric Joyner 
585571d10453SEric Joyner 	/* Replay pre-initialization if there is any */
58567d7af7f8SEric Joyner 	if (ice_is_main_vsi(hw, vsi_handle)) {
58577d7af7f8SEric Joyner 		status = ice_replay_pre_init(hw, sw);
585871d10453SEric Joyner 		if (status)
585971d10453SEric Joyner 			return status;
586071d10453SEric Joyner 	}
586171d10453SEric Joyner 	/* Replay per VSI all RSS configurations */
586271d10453SEric Joyner 	status = ice_replay_rss_cfg(hw, vsi_handle);
586371d10453SEric Joyner 	if (status)
586471d10453SEric Joyner 		return status;
586571d10453SEric Joyner 	/* Replay per VSI all filters */
58667d7af7f8SEric Joyner 	status = ice_replay_vsi_all_fltr(hw, pi, vsi_handle);
586771d10453SEric Joyner 	if (!status)
586871d10453SEric Joyner 		status = ice_replay_vsi_agg(hw, vsi_handle);
586971d10453SEric Joyner 	return status;
587071d10453SEric Joyner }
587171d10453SEric Joyner 
587271d10453SEric Joyner /**
587371d10453SEric Joyner  * ice_replay_post - post replay configuration cleanup
587471d10453SEric Joyner  * @hw: pointer to the HW struct
587571d10453SEric Joyner  *
587671d10453SEric Joyner  * Post replay cleanup.
587771d10453SEric Joyner  */
587871d10453SEric Joyner void ice_replay_post(struct ice_hw *hw)
587971d10453SEric Joyner {
588071d10453SEric Joyner 	/* Delete old entries from replay filter list head */
588171d10453SEric Joyner 	ice_rm_all_sw_replay_rule_info(hw);
588271d10453SEric Joyner 	ice_sched_replay_agg(hw);
588371d10453SEric Joyner }
588471d10453SEric Joyner 
588571d10453SEric Joyner /**
588671d10453SEric Joyner  * ice_stat_update40 - read 40 bit stat from the chip and update stat values
588771d10453SEric Joyner  * @hw: ptr to the hardware info
588871d10453SEric Joyner  * @reg: offset of 64 bit HW register to read from
588971d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
589071d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
589171d10453SEric Joyner  * @cur_stat: ptr to current stat value
589271d10453SEric Joyner  */
589371d10453SEric Joyner void
589471d10453SEric Joyner ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
589571d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
589671d10453SEric Joyner {
589771d10453SEric Joyner 	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
589871d10453SEric Joyner 
589971d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
590071d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
590171d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
590271d10453SEric Joyner 	 * count up from zero.
590371d10453SEric Joyner 	 */
590471d10453SEric Joyner 	if (!prev_stat_loaded) {
590571d10453SEric Joyner 		*prev_stat = new_data;
590671d10453SEric Joyner 		return;
590771d10453SEric Joyner 	}
590871d10453SEric Joyner 
590971d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
591071d10453SEric Joyner 	 * add it to the software stat value.
591171d10453SEric Joyner 	 */
591271d10453SEric Joyner 	if (new_data >= *prev_stat)
591371d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
591471d10453SEric Joyner 	else
591571d10453SEric Joyner 		/* to manage the potential roll-over */
591671d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
591771d10453SEric Joyner 
591871d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
591971d10453SEric Joyner 	*prev_stat = new_data;
592071d10453SEric Joyner }
592171d10453SEric Joyner 
592271d10453SEric Joyner /**
592371d10453SEric Joyner  * ice_stat_update32 - read 32 bit stat from the chip and update stat values
592471d10453SEric Joyner  * @hw: ptr to the hardware info
592571d10453SEric Joyner  * @reg: offset of HW register to read from
592671d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
592771d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
592871d10453SEric Joyner  * @cur_stat: ptr to current stat value
592971d10453SEric Joyner  */
593071d10453SEric Joyner void
593171d10453SEric Joyner ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
593271d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
593371d10453SEric Joyner {
593471d10453SEric Joyner 	u32 new_data;
593571d10453SEric Joyner 
593671d10453SEric Joyner 	new_data = rd32(hw, reg);
593771d10453SEric Joyner 
593871d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
593971d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
594071d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
594171d10453SEric Joyner 	 * count up from zero.
594271d10453SEric Joyner 	 */
594371d10453SEric Joyner 	if (!prev_stat_loaded) {
594471d10453SEric Joyner 		*prev_stat = new_data;
594571d10453SEric Joyner 		return;
594671d10453SEric Joyner 	}
594771d10453SEric Joyner 
594871d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
594971d10453SEric Joyner 	 * add it to the software stat value.
595071d10453SEric Joyner 	 */
595171d10453SEric Joyner 	if (new_data >= *prev_stat)
595271d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
595371d10453SEric Joyner 	else
595471d10453SEric Joyner 		/* to manage the potential roll-over */
595571d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
595671d10453SEric Joyner 
595771d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
595871d10453SEric Joyner 	*prev_stat = new_data;
595971d10453SEric Joyner }
596071d10453SEric Joyner 
596171d10453SEric Joyner /**
596271d10453SEric Joyner  * ice_stat_update_repc - read GLV_REPC stats from chip and update stat values
596371d10453SEric Joyner  * @hw: ptr to the hardware info
596471d10453SEric Joyner  * @vsi_handle: VSI handle
596571d10453SEric Joyner  * @prev_stat_loaded: bool to specify if the previous stat values are loaded
596671d10453SEric Joyner  * @cur_stats: ptr to current stats structure
596771d10453SEric Joyner  *
596871d10453SEric Joyner  * The GLV_REPC statistic register actually tracks two 16bit statistics, and
596971d10453SEric Joyner  * thus cannot be read using the normal ice_stat_update32 function.
597071d10453SEric Joyner  *
597171d10453SEric Joyner  * Read the GLV_REPC register associated with the given VSI, and update the
597271d10453SEric Joyner  * rx_no_desc and rx_error values in the ice_eth_stats structure.
597371d10453SEric Joyner  *
597471d10453SEric Joyner  * Because the statistics in GLV_REPC stick at 0xFFFF, the register must be
597571d10453SEric Joyner  * cleared each time it's read.
597671d10453SEric Joyner  *
597771d10453SEric Joyner  * Note that the GLV_RDPC register also counts the causes that would trigger
597871d10453SEric Joyner  * GLV_REPC. However, it does not give the finer grained detail about why the
597971d10453SEric Joyner  * packets are being dropped. The GLV_REPC values can be used to distinguish
598071d10453SEric Joyner  * whether Rx packets are dropped due to errors or due to no available
598171d10453SEric Joyner  * descriptors.
598271d10453SEric Joyner  */
598371d10453SEric Joyner void
598471d10453SEric Joyner ice_stat_update_repc(struct ice_hw *hw, u16 vsi_handle, bool prev_stat_loaded,
598571d10453SEric Joyner 		     struct ice_eth_stats *cur_stats)
598671d10453SEric Joyner {
598771d10453SEric Joyner 	u16 vsi_num, no_desc, error_cnt;
598871d10453SEric Joyner 	u32 repc;
598971d10453SEric Joyner 
599071d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
599171d10453SEric Joyner 		return;
599271d10453SEric Joyner 
599371d10453SEric Joyner 	vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
599471d10453SEric Joyner 
599571d10453SEric Joyner 	/* If we haven't loaded stats yet, just clear the current value */
599671d10453SEric Joyner 	if (!prev_stat_loaded) {
599771d10453SEric Joyner 		wr32(hw, GLV_REPC(vsi_num), 0);
599871d10453SEric Joyner 		return;
599971d10453SEric Joyner 	}
600071d10453SEric Joyner 
600171d10453SEric Joyner 	repc = rd32(hw, GLV_REPC(vsi_num));
600271d10453SEric Joyner 	no_desc = (repc & GLV_REPC_NO_DESC_CNT_M) >> GLV_REPC_NO_DESC_CNT_S;
600371d10453SEric Joyner 	error_cnt = (repc & GLV_REPC_ERROR_CNT_M) >> GLV_REPC_ERROR_CNT_S;
600471d10453SEric Joyner 
600571d10453SEric Joyner 	/* Clear the count by writing to the stats register */
600671d10453SEric Joyner 	wr32(hw, GLV_REPC(vsi_num), 0);
600771d10453SEric Joyner 
600871d10453SEric Joyner 	cur_stats->rx_no_desc += no_desc;
600971d10453SEric Joyner 	cur_stats->rx_errors += error_cnt;
601071d10453SEric Joyner }
601171d10453SEric Joyner 
601271d10453SEric Joyner /**
601371d10453SEric Joyner  * ice_aq_alternate_write
601471d10453SEric Joyner  * @hw: pointer to the hardware structure
601571d10453SEric Joyner  * @reg_addr0: address of first dword to be written
601671d10453SEric Joyner  * @reg_val0: value to be written under 'reg_addr0'
601771d10453SEric Joyner  * @reg_addr1: address of second dword to be written
601871d10453SEric Joyner  * @reg_val1: value to be written under 'reg_addr1'
601971d10453SEric Joyner  *
602071d10453SEric Joyner  * Write one or two dwords to alternate structure. Fields are indicated
602171d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers.
602271d10453SEric Joyner  */
6023*f2635e84SEric Joyner int
602471d10453SEric Joyner ice_aq_alternate_write(struct ice_hw *hw, u32 reg_addr0, u32 reg_val0,
602571d10453SEric Joyner 		       u32 reg_addr1, u32 reg_val1)
602671d10453SEric Joyner {
602771d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
602871d10453SEric Joyner 	struct ice_aq_desc desc;
6029*f2635e84SEric Joyner 	int status;
603071d10453SEric Joyner 
603171d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
603271d10453SEric Joyner 
603371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_alt_direct);
603471d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
603571d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
603671d10453SEric Joyner 	cmd->dword0_value = CPU_TO_LE32(reg_val0);
603771d10453SEric Joyner 	cmd->dword1_value = CPU_TO_LE32(reg_val1);
603871d10453SEric Joyner 
603971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
604071d10453SEric Joyner 
604171d10453SEric Joyner 	return status;
604271d10453SEric Joyner }
604371d10453SEric Joyner 
604471d10453SEric Joyner /**
604571d10453SEric Joyner  * ice_aq_alternate_read
604671d10453SEric Joyner  * @hw: pointer to the hardware structure
604771d10453SEric Joyner  * @reg_addr0: address of first dword to be read
604871d10453SEric Joyner  * @reg_val0: pointer for data read from 'reg_addr0'
604971d10453SEric Joyner  * @reg_addr1: address of second dword to be read
605071d10453SEric Joyner  * @reg_val1: pointer for data read from 'reg_addr1'
605171d10453SEric Joyner  *
605271d10453SEric Joyner  * Read one or two dwords from alternate structure. Fields are indicated
605371d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer
605471d10453SEric Joyner  * is not passed then only register at 'reg_addr0' is read.
605571d10453SEric Joyner  */
6056*f2635e84SEric Joyner int
605771d10453SEric Joyner ice_aq_alternate_read(struct ice_hw *hw, u32 reg_addr0, u32 *reg_val0,
605871d10453SEric Joyner 		      u32 reg_addr1, u32 *reg_val1)
605971d10453SEric Joyner {
606071d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
606171d10453SEric Joyner 	struct ice_aq_desc desc;
6062*f2635e84SEric Joyner 	int status;
606371d10453SEric Joyner 
606471d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
606571d10453SEric Joyner 
606671d10453SEric Joyner 	if (!reg_val0)
606771d10453SEric Joyner 		return ICE_ERR_PARAM;
606871d10453SEric Joyner 
606971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_alt_direct);
607071d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
607171d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
607271d10453SEric Joyner 
607371d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
607471d10453SEric Joyner 
6075*f2635e84SEric Joyner 	if (!status) {
607671d10453SEric Joyner 		*reg_val0 = LE32_TO_CPU(cmd->dword0_value);
607771d10453SEric Joyner 
607871d10453SEric Joyner 		if (reg_val1)
607971d10453SEric Joyner 			*reg_val1 = LE32_TO_CPU(cmd->dword1_value);
608071d10453SEric Joyner 	}
608171d10453SEric Joyner 
608271d10453SEric Joyner 	return status;
608371d10453SEric Joyner }
608471d10453SEric Joyner 
608571d10453SEric Joyner /**
608671d10453SEric Joyner  *  ice_aq_alternate_write_done
608771d10453SEric Joyner  *  @hw: pointer to the HW structure.
608871d10453SEric Joyner  *  @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS
608971d10453SEric Joyner  *  @reset_needed: indicates the SW should trigger GLOBAL reset
609071d10453SEric Joyner  *
609171d10453SEric Joyner  *  Indicates to the FW that alternate structures have been changed.
609271d10453SEric Joyner  */
6093*f2635e84SEric Joyner int
609471d10453SEric Joyner ice_aq_alternate_write_done(struct ice_hw *hw, u8 bios_mode, bool *reset_needed)
609571d10453SEric Joyner {
609671d10453SEric Joyner 	struct ice_aqc_done_alt_write *cmd;
609771d10453SEric Joyner 	struct ice_aq_desc desc;
6098*f2635e84SEric Joyner 	int status;
609971d10453SEric Joyner 
610071d10453SEric Joyner 	cmd = &desc.params.done_alt_write;
610171d10453SEric Joyner 
610271d10453SEric Joyner 	if (!reset_needed)
610371d10453SEric Joyner 		return ICE_ERR_PARAM;
610471d10453SEric Joyner 
610571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_done_alt_write);
610671d10453SEric Joyner 	cmd->flags = bios_mode;
610771d10453SEric Joyner 
610871d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
610971d10453SEric Joyner 	if (!status)
611071d10453SEric Joyner 		*reset_needed = (LE16_TO_CPU(cmd->flags) &
611171d10453SEric Joyner 				 ICE_AQC_RESP_RESET_NEEDED) != 0;
611271d10453SEric Joyner 
611371d10453SEric Joyner 	return status;
611471d10453SEric Joyner }
611571d10453SEric Joyner 
611671d10453SEric Joyner /**
611771d10453SEric Joyner  *  ice_aq_alternate_clear
611871d10453SEric Joyner  *  @hw: pointer to the HW structure.
611971d10453SEric Joyner  *
612071d10453SEric Joyner  *  Clear the alternate structures of the port from which the function
612171d10453SEric Joyner  *  is called.
612271d10453SEric Joyner  */
6123*f2635e84SEric Joyner int ice_aq_alternate_clear(struct ice_hw *hw)
612471d10453SEric Joyner {
612571d10453SEric Joyner 	struct ice_aq_desc desc;
6126*f2635e84SEric Joyner 	int status;
612771d10453SEric Joyner 
612871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_port_alt_write);
612971d10453SEric Joyner 
613071d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
613171d10453SEric Joyner 
613271d10453SEric Joyner 	return status;
613371d10453SEric Joyner }
613471d10453SEric Joyner 
613571d10453SEric Joyner /**
613671d10453SEric Joyner  * ice_sched_query_elem - query element information from HW
613771d10453SEric Joyner  * @hw: pointer to the HW struct
613871d10453SEric Joyner  * @node_teid: node TEID to be queried
613971d10453SEric Joyner  * @buf: buffer to element information
614071d10453SEric Joyner  *
614171d10453SEric Joyner  * This function queries HW element information
614271d10453SEric Joyner  */
6143*f2635e84SEric Joyner int
614471d10453SEric Joyner ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
61457d7af7f8SEric Joyner 		     struct ice_aqc_txsched_elem_data *buf)
614671d10453SEric Joyner {
614771d10453SEric Joyner 	u16 buf_size, num_elem_ret = 0;
6148*f2635e84SEric Joyner 	int status;
614971d10453SEric Joyner 
615071d10453SEric Joyner 	buf_size = sizeof(*buf);
615171d10453SEric Joyner 	ice_memset(buf, 0, buf_size, ICE_NONDMA_MEM);
61527d7af7f8SEric Joyner 	buf->node_teid = CPU_TO_LE32(node_teid);
615371d10453SEric Joyner 	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
615471d10453SEric Joyner 					  NULL);
6155*f2635e84SEric Joyner 	if (status || num_elem_ret != 1)
615671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
615771d10453SEric Joyner 	return status;
615871d10453SEric Joyner }
615971d10453SEric Joyner 
616071d10453SEric Joyner /**
616171d10453SEric Joyner  * ice_get_fw_mode - returns FW mode
616271d10453SEric Joyner  * @hw: pointer to the HW struct
616371d10453SEric Joyner  */
616471d10453SEric Joyner enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
616571d10453SEric Joyner {
616671d10453SEric Joyner #define ICE_FW_MODE_DBG_M BIT(0)
616771d10453SEric Joyner #define ICE_FW_MODE_REC_M BIT(1)
616871d10453SEric Joyner #define ICE_FW_MODE_ROLLBACK_M BIT(2)
616971d10453SEric Joyner 	u32 fw_mode;
617071d10453SEric Joyner 
617171d10453SEric Joyner 	/* check the current FW mode */
6172*f2635e84SEric Joyner 	fw_mode = rd32(hw, GL_MNG_FWSM) & E800_GL_MNG_FWSM_FW_MODES_M;
617371d10453SEric Joyner 	if (fw_mode & ICE_FW_MODE_DBG_M)
617471d10453SEric Joyner 		return ICE_FW_MODE_DBG;
617571d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_REC_M)
617671d10453SEric Joyner 		return ICE_FW_MODE_REC;
617771d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_ROLLBACK_M)
617871d10453SEric Joyner 		return ICE_FW_MODE_ROLLBACK;
617971d10453SEric Joyner 	else
618071d10453SEric Joyner 		return ICE_FW_MODE_NORMAL;
618171d10453SEric Joyner }
618271d10453SEric Joyner 
618371d10453SEric Joyner /**
61849dc2f6e2SEric Joyner  * ice_get_cur_lldp_persist_status
618571d10453SEric Joyner  * @hw: pointer to the HW struct
618671d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
618771d10453SEric Joyner  *
618871d10453SEric Joyner  * Get the current status of LLDP persistent
618971d10453SEric Joyner  */
6190*f2635e84SEric Joyner int
619171d10453SEric Joyner ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
619271d10453SEric Joyner {
619371d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
619471d10453SEric Joyner 	__le32 raw_data;
619571d10453SEric Joyner 	u32 data, mask;
6196*f2635e84SEric Joyner 	int ret;
619771d10453SEric Joyner 
619871d10453SEric Joyner 	if (!lldp_status)
619971d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
620071d10453SEric Joyner 
620171d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
620271d10453SEric Joyner 	if (ret)
620371d10453SEric Joyner 		return ret;
620471d10453SEric Joyner 
620571d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LLDP_PRESERVED_MOD_ID,
620671d10453SEric Joyner 			      ICE_AQC_NVM_CUR_LLDP_PERSIST_RD_OFFSET,
620771d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data,
620871d10453SEric Joyner 			      false, true, NULL);
620971d10453SEric Joyner 	if (!ret) {
621071d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
621171d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
621271d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
621371d10453SEric Joyner 		data = data & mask;
621471d10453SEric Joyner 		*lldp_status = data >>
621571d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
621671d10453SEric Joyner 	}
621771d10453SEric Joyner 
621871d10453SEric Joyner 	ice_release_nvm(hw);
621971d10453SEric Joyner 
622071d10453SEric Joyner 	return ret;
622171d10453SEric Joyner }
622271d10453SEric Joyner 
622371d10453SEric Joyner /**
622471d10453SEric Joyner  * ice_get_dflt_lldp_persist_status
622571d10453SEric Joyner  * @hw: pointer to the HW struct
622671d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
622771d10453SEric Joyner  *
622871d10453SEric Joyner  * Get the default status of LLDP persistent
622971d10453SEric Joyner  */
6230*f2635e84SEric Joyner int
623171d10453SEric Joyner ice_get_dflt_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
623271d10453SEric Joyner {
623371d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
623471d10453SEric Joyner 	u32 data, mask, loc_data, loc_data_tmp;
623571d10453SEric Joyner 	__le16 loc_raw_data;
623671d10453SEric Joyner 	__le32 raw_data;
6237*f2635e84SEric Joyner 	int ret;
623871d10453SEric Joyner 
623971d10453SEric Joyner 	if (!lldp_status)
624071d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
624171d10453SEric Joyner 
624271d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
624371d10453SEric Joyner 	if (ret)
624471d10453SEric Joyner 		return ret;
624571d10453SEric Joyner 
624671d10453SEric Joyner 	/* Read the offset of EMP_SR_PTR */
624771d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT,
624871d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_OFFSET,
624971d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_RD_LEN,
625071d10453SEric Joyner 			      &loc_raw_data, false, true, NULL);
625171d10453SEric Joyner 	if (ret)
625271d10453SEric Joyner 		goto exit;
625371d10453SEric Joyner 
625471d10453SEric Joyner 	loc_data = LE16_TO_CPU(loc_raw_data);
625571d10453SEric Joyner 	if (loc_data & ICE_AQC_NVM_EMP_SR_PTR_TYPE_M) {
625671d10453SEric Joyner 		loc_data &= ICE_AQC_NVM_EMP_SR_PTR_M;
625771d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_SECTOR_UNIT;
625871d10453SEric Joyner 	} else {
625971d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_WORD_UNIT;
626071d10453SEric Joyner 	}
626171d10453SEric Joyner 
626271d10453SEric Joyner 	/* Read the offset of LLDP configuration pointer */
626371d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_PTR_OFFSET;
626471d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
626571d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_CFG_PTR_RD_LEN, &loc_raw_data,
626671d10453SEric Joyner 			      false, true, NULL);
626771d10453SEric Joyner 	if (ret)
626871d10453SEric Joyner 		goto exit;
626971d10453SEric Joyner 
627071d10453SEric Joyner 	loc_data_tmp = LE16_TO_CPU(loc_raw_data);
627171d10453SEric Joyner 	loc_data_tmp *= ICE_AQC_NVM_WORD_UNIT;
627271d10453SEric Joyner 	loc_data += loc_data_tmp;
627371d10453SEric Joyner 
627471d10453SEric Joyner 	/* We need to skip LLDP configuration section length (2 bytes) */
627571d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_HEADER_LEN;
627671d10453SEric Joyner 
627771d10453SEric Joyner 	/* Read the LLDP Default Configure */
627871d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
627971d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data, false,
628071d10453SEric Joyner 			      true, NULL);
628171d10453SEric Joyner 	if (!ret) {
628271d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
628371d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
628471d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
628571d10453SEric Joyner 		data = data & mask;
628671d10453SEric Joyner 		*lldp_status = data >>
628771d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
628871d10453SEric Joyner 	}
628971d10453SEric Joyner 
629071d10453SEric Joyner exit:
629171d10453SEric Joyner 	ice_release_nvm(hw);
629271d10453SEric Joyner 
629371d10453SEric Joyner 	return ret;
629471d10453SEric Joyner }
629571d10453SEric Joyner 
629671d10453SEric Joyner /**
629756429daeSEric Joyner  * ice_aq_read_i2c
629856429daeSEric Joyner  * @hw: pointer to the hw struct
629956429daeSEric Joyner  * @topo_addr: topology address for a device to communicate with
630056429daeSEric Joyner  * @bus_addr: 7-bit I2C bus address
630156429daeSEric Joyner  * @addr: I2C memory address (I2C offset) with up to 16 bits
630256429daeSEric Joyner  * @params: I2C parameters: bit [7] - Repeated start, bits [6:5] data offset size,
630356429daeSEric Joyner  *			    bit [4] - I2C address type, bits [3:0] - data size to read (0-16 bytes)
630456429daeSEric Joyner  * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
630556429daeSEric Joyner  * @cd: pointer to command details structure or NULL
630656429daeSEric Joyner  *
630756429daeSEric Joyner  * Read I2C (0x06E2)
630856429daeSEric Joyner  */
6309*f2635e84SEric Joyner int
631056429daeSEric Joyner ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
631156429daeSEric Joyner 		u16 bus_addr, __le16 addr, u8 params, u8 *data,
631256429daeSEric Joyner 		struct ice_sq_cd *cd)
631356429daeSEric Joyner {
631456429daeSEric Joyner 	struct ice_aq_desc desc = { 0 };
631556429daeSEric Joyner 	struct ice_aqc_i2c *cmd;
631656429daeSEric Joyner 	u8 data_size;
6317*f2635e84SEric Joyner 	int status;
631856429daeSEric Joyner 
631956429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
632056429daeSEric Joyner 	cmd = &desc.params.read_write_i2c;
632156429daeSEric Joyner 
632256429daeSEric Joyner 	if (!data)
632356429daeSEric Joyner 		return ICE_ERR_PARAM;
632456429daeSEric Joyner 
632556429daeSEric Joyner 	data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
632656429daeSEric Joyner 
632756429daeSEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
632856429daeSEric Joyner 	cmd->topo_addr = topo_addr;
632956429daeSEric Joyner 	cmd->i2c_params = params;
633056429daeSEric Joyner 	cmd->i2c_addr = addr;
633156429daeSEric Joyner 
633256429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
633356429daeSEric Joyner 	if (!status) {
633456429daeSEric Joyner 		struct ice_aqc_read_i2c_resp *resp;
633556429daeSEric Joyner 		u8 i;
633656429daeSEric Joyner 
633756429daeSEric Joyner 		resp = &desc.params.read_i2c_resp;
633856429daeSEric Joyner 		for (i = 0; i < data_size; i++) {
633956429daeSEric Joyner 			*data = resp->i2c_data[i];
634056429daeSEric Joyner 			data++;
634156429daeSEric Joyner 		}
634256429daeSEric Joyner 	}
634356429daeSEric Joyner 
634456429daeSEric Joyner 	return status;
634556429daeSEric Joyner }
634656429daeSEric Joyner 
634756429daeSEric Joyner /**
634856429daeSEric Joyner  * ice_aq_write_i2c
634956429daeSEric Joyner  * @hw: pointer to the hw struct
635056429daeSEric Joyner  * @topo_addr: topology address for a device to communicate with
635156429daeSEric Joyner  * @bus_addr: 7-bit I2C bus address
635256429daeSEric Joyner  * @addr: I2C memory address (I2C offset) with up to 16 bits
635356429daeSEric Joyner  * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
635456429daeSEric Joyner  * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
635556429daeSEric Joyner  * @cd: pointer to command details structure or NULL
635656429daeSEric Joyner  *
635756429daeSEric Joyner  * Write I2C (0x06E3)
635856429daeSEric Joyner  */
6359*f2635e84SEric Joyner int
636056429daeSEric Joyner ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
63619e54973fSEric Joyner 		 u16 bus_addr, __le16 addr, u8 params, const u8 *data,
636256429daeSEric Joyner 		 struct ice_sq_cd *cd)
636356429daeSEric Joyner {
636456429daeSEric Joyner 	struct ice_aq_desc desc = { 0 };
636556429daeSEric Joyner 	struct ice_aqc_i2c *cmd;
636656429daeSEric Joyner 	u8 i, data_size;
636756429daeSEric Joyner 
636856429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
636956429daeSEric Joyner 	cmd = &desc.params.read_write_i2c;
637056429daeSEric Joyner 
637156429daeSEric Joyner 	data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
637256429daeSEric Joyner 
637356429daeSEric Joyner 	/* data_size limited to 4 */
637456429daeSEric Joyner 	if (data_size > 4)
637556429daeSEric Joyner 		return ICE_ERR_PARAM;
637656429daeSEric Joyner 
637756429daeSEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
637856429daeSEric Joyner 	cmd->topo_addr = topo_addr;
637956429daeSEric Joyner 	cmd->i2c_params = params;
638056429daeSEric Joyner 	cmd->i2c_addr = addr;
638156429daeSEric Joyner 
638256429daeSEric Joyner 	for (i = 0; i < data_size; i++) {
638356429daeSEric Joyner 		cmd->i2c_data[i] = *data;
638456429daeSEric Joyner 		data++;
638556429daeSEric Joyner 	}
638656429daeSEric Joyner 
638756429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
638856429daeSEric Joyner }
638956429daeSEric Joyner 
639056429daeSEric Joyner /**
639156429daeSEric Joyner  * ice_aq_set_gpio
639256429daeSEric Joyner  * @hw: pointer to the hw struct
639356429daeSEric Joyner  * @gpio_ctrl_handle: GPIO controller node handle
639456429daeSEric Joyner  * @pin_idx: IO Number of the GPIO that needs to be set
639556429daeSEric Joyner  * @value: SW provide IO value to set in the LSB
639656429daeSEric Joyner  * @cd: pointer to command details structure or NULL
639756429daeSEric Joyner  *
639856429daeSEric Joyner  * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
639956429daeSEric Joyner  */
6400*f2635e84SEric Joyner int
640156429daeSEric Joyner ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
640256429daeSEric Joyner 		struct ice_sq_cd *cd)
640356429daeSEric Joyner {
640456429daeSEric Joyner 	struct ice_aqc_gpio *cmd;
640556429daeSEric Joyner 	struct ice_aq_desc desc;
640656429daeSEric Joyner 
640756429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
640856429daeSEric Joyner 	cmd = &desc.params.read_write_gpio;
64098923de59SPiotr Kubaj 	cmd->gpio_ctrl_handle = CPU_TO_LE16(gpio_ctrl_handle);
641056429daeSEric Joyner 	cmd->gpio_num = pin_idx;
641156429daeSEric Joyner 	cmd->gpio_val = value ? 1 : 0;
641256429daeSEric Joyner 
641356429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
641456429daeSEric Joyner }
641556429daeSEric Joyner 
641656429daeSEric Joyner /**
641756429daeSEric Joyner  * ice_aq_get_gpio
641856429daeSEric Joyner  * @hw: pointer to the hw struct
641956429daeSEric Joyner  * @gpio_ctrl_handle: GPIO controller node handle
642056429daeSEric Joyner  * @pin_idx: IO Number of the GPIO that needs to be set
642156429daeSEric Joyner  * @value: IO value read
642256429daeSEric Joyner  * @cd: pointer to command details structure or NULL
642356429daeSEric Joyner  *
642456429daeSEric Joyner  * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
642556429daeSEric Joyner  * the topology
642656429daeSEric Joyner  */
6427*f2635e84SEric Joyner int
642856429daeSEric Joyner ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
642956429daeSEric Joyner 		bool *value, struct ice_sq_cd *cd)
643056429daeSEric Joyner {
643156429daeSEric Joyner 	struct ice_aqc_gpio *cmd;
643256429daeSEric Joyner 	struct ice_aq_desc desc;
6433*f2635e84SEric Joyner 	int status;
643456429daeSEric Joyner 
643556429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
643656429daeSEric Joyner 	cmd = &desc.params.read_write_gpio;
64378923de59SPiotr Kubaj 	cmd->gpio_ctrl_handle = CPU_TO_LE16(gpio_ctrl_handle);
643856429daeSEric Joyner 	cmd->gpio_num = pin_idx;
643956429daeSEric Joyner 
644056429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
644156429daeSEric Joyner 	if (status)
644256429daeSEric Joyner 		return status;
644356429daeSEric Joyner 
644456429daeSEric Joyner 	*value = !!cmd->gpio_val;
6445*f2635e84SEric Joyner 	return 0;
644656429daeSEric Joyner }
644756429daeSEric Joyner 
644856429daeSEric Joyner /**
64498923de59SPiotr Kubaj  * ice_is_fw_api_min_ver
64508923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
64518923de59SPiotr Kubaj  * @maj: major version
64528923de59SPiotr Kubaj  * @min: minor version
64538923de59SPiotr Kubaj  * @patch: patch version
64548923de59SPiotr Kubaj  *
64558923de59SPiotr Kubaj  * Checks if the firmware is minimum version
64568923de59SPiotr Kubaj  */
64578923de59SPiotr Kubaj static bool ice_is_fw_api_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch)
64588923de59SPiotr Kubaj {
64598923de59SPiotr Kubaj 	if (hw->api_maj_ver == maj) {
64608923de59SPiotr Kubaj 		if (hw->api_min_ver > min)
64618923de59SPiotr Kubaj 			return true;
64628923de59SPiotr Kubaj 		if (hw->api_min_ver == min && hw->api_patch >= patch)
64638923de59SPiotr Kubaj 			return true;
64648923de59SPiotr Kubaj 	} else if (hw->api_maj_ver > maj) {
64658923de59SPiotr Kubaj 		return true;
64668923de59SPiotr Kubaj 	}
64678923de59SPiotr Kubaj 
64688923de59SPiotr Kubaj 	return false;
64698923de59SPiotr Kubaj }
64708923de59SPiotr Kubaj 
64718923de59SPiotr Kubaj /**
64728923de59SPiotr Kubaj  * ice_is_fw_min_ver
64738923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
64748923de59SPiotr Kubaj  * @branch: branch version
64758923de59SPiotr Kubaj  * @maj: major version
64768923de59SPiotr Kubaj  * @min: minor version
64778923de59SPiotr Kubaj  * @patch: patch version
64788923de59SPiotr Kubaj  *
64798923de59SPiotr Kubaj  * Checks if the firmware is minimum version
64808923de59SPiotr Kubaj  */
64818923de59SPiotr Kubaj static bool ice_is_fw_min_ver(struct ice_hw *hw, u8 branch, u8 maj, u8 min,
64828923de59SPiotr Kubaj 			      u8 patch)
64838923de59SPiotr Kubaj {
64848923de59SPiotr Kubaj 	if (hw->fw_branch == branch) {
64858923de59SPiotr Kubaj 		if (hw->fw_maj_ver > maj)
64868923de59SPiotr Kubaj 			return true;
64878923de59SPiotr Kubaj 		if (hw->fw_maj_ver == maj) {
64888923de59SPiotr Kubaj 			if (hw->fw_min_ver > min)
64898923de59SPiotr Kubaj 				return true;
64908923de59SPiotr Kubaj 			if (hw->fw_min_ver == min && hw->fw_patch >= patch)
64918923de59SPiotr Kubaj 				return true;
64928923de59SPiotr Kubaj 		}
64938923de59SPiotr Kubaj 	}
64948923de59SPiotr Kubaj 
64958923de59SPiotr Kubaj 	return false;
64968923de59SPiotr Kubaj }
64978923de59SPiotr Kubaj 
64988923de59SPiotr Kubaj /**
649971d10453SEric Joyner  * ice_fw_supports_link_override
650071d10453SEric Joyner  * @hw: pointer to the hardware structure
650171d10453SEric Joyner  *
650271d10453SEric Joyner  * Checks if the firmware supports link override
650371d10453SEric Joyner  */
650471d10453SEric Joyner bool ice_fw_supports_link_override(struct ice_hw *hw)
650571d10453SEric Joyner {
65068923de59SPiotr Kubaj 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LINK_OVERRIDE_MAJ,
65078923de59SPiotr Kubaj 				     ICE_FW_API_LINK_OVERRIDE_MIN,
65088923de59SPiotr Kubaj 				     ICE_FW_API_LINK_OVERRIDE_PATCH);
650971d10453SEric Joyner }
651071d10453SEric Joyner 
651171d10453SEric Joyner /**
651271d10453SEric Joyner  * ice_get_link_default_override
651371d10453SEric Joyner  * @ldo: pointer to the link default override struct
651471d10453SEric Joyner  * @pi: pointer to the port info struct
651571d10453SEric Joyner  *
651671d10453SEric Joyner  * Gets the link default override for a port
651771d10453SEric Joyner  */
6518*f2635e84SEric Joyner int
651971d10453SEric Joyner ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
652071d10453SEric Joyner 			      struct ice_port_info *pi)
652171d10453SEric Joyner {
652271d10453SEric Joyner 	u16 i, tlv, tlv_len, tlv_start, buf, offset;
652371d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
6524*f2635e84SEric Joyner 	int status;
652571d10453SEric Joyner 
652671d10453SEric Joyner 	status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
652771d10453SEric Joyner 					ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
652871d10453SEric Joyner 	if (status) {
65297d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n");
653071d10453SEric Joyner 		return status;
653171d10453SEric Joyner 	}
653271d10453SEric Joyner 
653371d10453SEric Joyner 	/* Each port has its own config; calculate for our port */
653471d10453SEric Joyner 	tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
653571d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
653671d10453SEric Joyner 
653771d10453SEric Joyner 	/* link options first */
653871d10453SEric Joyner 	status = ice_read_sr_word(hw, tlv_start, &buf);
653971d10453SEric Joyner 	if (status) {
65407d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
654171d10453SEric Joyner 		return status;
654271d10453SEric Joyner 	}
654371d10453SEric Joyner 	ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
654471d10453SEric Joyner 	ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
654571d10453SEric Joyner 		ICE_LINK_OVERRIDE_PHY_CFG_S;
654671d10453SEric Joyner 
654771d10453SEric Joyner 	/* link PHY config */
654871d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
654971d10453SEric Joyner 	status = ice_read_sr_word(hw, offset, &buf);
655071d10453SEric Joyner 	if (status) {
65517d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n");
655271d10453SEric Joyner 		return status;
655371d10453SEric Joyner 	}
655471d10453SEric Joyner 	ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
655571d10453SEric Joyner 
655671d10453SEric Joyner 	/* PHY types low */
655771d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
655871d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
655971d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
656071d10453SEric Joyner 		if (status) {
65617d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
656271d10453SEric Joyner 			return status;
656371d10453SEric Joyner 		}
656471d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
656571d10453SEric Joyner 		ldo->phy_type_low |= ((u64)buf << (i * 16));
656671d10453SEric Joyner 	}
656771d10453SEric Joyner 
656871d10453SEric Joyner 	/* PHY types high */
656971d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
657071d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
657171d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
657271d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
657371d10453SEric Joyner 		if (status) {
65747d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
657571d10453SEric Joyner 			return status;
657671d10453SEric Joyner 		}
657771d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
657871d10453SEric Joyner 		ldo->phy_type_high |= ((u64)buf << (i * 16));
657971d10453SEric Joyner 	}
658071d10453SEric Joyner 
658171d10453SEric Joyner 	return status;
658271d10453SEric Joyner }
65837d7af7f8SEric Joyner 
65847d7af7f8SEric Joyner /**
65857d7af7f8SEric Joyner  * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
65867d7af7f8SEric Joyner  * @caps: get PHY capability data
65877d7af7f8SEric Joyner  */
65887d7af7f8SEric Joyner bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
65897d7af7f8SEric Joyner {
65907d7af7f8SEric Joyner 	if (caps->caps & ICE_AQC_PHY_AN_MODE ||
65917d7af7f8SEric Joyner 	    caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
65927d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE73 |
65937d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE37))
65947d7af7f8SEric Joyner 		return true;
65957d7af7f8SEric Joyner 
65967d7af7f8SEric Joyner 	return false;
65977d7af7f8SEric Joyner }
65987d7af7f8SEric Joyner 
65997d7af7f8SEric Joyner /**
66009cf1841cSEric Joyner  * ice_is_fw_health_report_supported
66019cf1841cSEric Joyner  * @hw: pointer to the hardware structure
66029cf1841cSEric Joyner  *
66039cf1841cSEric Joyner  * Return true if firmware supports health status reports,
66049cf1841cSEric Joyner  * false otherwise
66059cf1841cSEric Joyner  */
66069cf1841cSEric Joyner bool ice_is_fw_health_report_supported(struct ice_hw *hw)
66079cf1841cSEric Joyner {
66089cf1841cSEric Joyner 	if (hw->api_maj_ver > ICE_FW_API_HEALTH_REPORT_MAJ)
66099cf1841cSEric Joyner 		return true;
66109cf1841cSEric Joyner 
66119cf1841cSEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_HEALTH_REPORT_MAJ) {
66129cf1841cSEric Joyner 		if (hw->api_min_ver > ICE_FW_API_HEALTH_REPORT_MIN)
66139cf1841cSEric Joyner 			return true;
66149cf1841cSEric Joyner 		if (hw->api_min_ver == ICE_FW_API_HEALTH_REPORT_MIN &&
66159cf1841cSEric Joyner 		    hw->api_patch >= ICE_FW_API_HEALTH_REPORT_PATCH)
66169cf1841cSEric Joyner 			return true;
66179cf1841cSEric Joyner 	}
66189cf1841cSEric Joyner 
66199cf1841cSEric Joyner 	return false;
66209cf1841cSEric Joyner }
66219cf1841cSEric Joyner 
66229cf1841cSEric Joyner /**
66239cf1841cSEric Joyner  * ice_aq_set_health_status_config - Configure FW health events
66249cf1841cSEric Joyner  * @hw: pointer to the HW struct
66259cf1841cSEric Joyner  * @event_source: type of diagnostic events to enable
66269cf1841cSEric Joyner  * @cd: pointer to command details structure or NULL
66279cf1841cSEric Joyner  *
66289cf1841cSEric Joyner  * Configure the health status event types that the firmware will send to this
66299cf1841cSEric Joyner  * PF. The supported event types are: PF-specific, all PFs, and global
66309cf1841cSEric Joyner  */
6631*f2635e84SEric Joyner int
66329cf1841cSEric Joyner ice_aq_set_health_status_config(struct ice_hw *hw, u8 event_source,
66339cf1841cSEric Joyner 				struct ice_sq_cd *cd)
66349cf1841cSEric Joyner {
66359cf1841cSEric Joyner 	struct ice_aqc_set_health_status_config *cmd;
66369cf1841cSEric Joyner 	struct ice_aq_desc desc;
66379cf1841cSEric Joyner 
66389cf1841cSEric Joyner 	cmd = &desc.params.set_health_status_config;
66399cf1841cSEric Joyner 
66409cf1841cSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc,
66419cf1841cSEric Joyner 				      ice_aqc_opc_set_health_status_config);
66429cf1841cSEric Joyner 
66439cf1841cSEric Joyner 	cmd->event_source = event_source;
66449cf1841cSEric Joyner 
66459cf1841cSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
66469cf1841cSEric Joyner }
66479cf1841cSEric Joyner 
66489cf1841cSEric Joyner /**
66499cf1841cSEric Joyner  * ice_aq_get_port_options
66509cf1841cSEric Joyner  * @hw: pointer to the hw struct
66519cf1841cSEric Joyner  * @options: buffer for the resultant port options
66529cf1841cSEric Joyner  * @option_count: input - size of the buffer in port options structures,
66539cf1841cSEric Joyner  *                output - number of returned port options
66549cf1841cSEric Joyner  * @lport: logical port to call the command with (optional)
66559cf1841cSEric Joyner  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
66569cf1841cSEric Joyner  *               when PF owns more than 1 port it must be true
66579cf1841cSEric Joyner  * @active_option_idx: index of active port option in returned buffer
66589cf1841cSEric Joyner  * @active_option_valid: active option in returned buffer is valid
66599dc2f6e2SEric Joyner  * @pending_option_idx: index of pending port option in returned buffer
66609dc2f6e2SEric Joyner  * @pending_option_valid: pending option in returned buffer is valid
66619cf1841cSEric Joyner  *
66629cf1841cSEric Joyner  * Calls Get Port Options AQC (0x06ea) and verifies result.
66639cf1841cSEric Joyner  */
6664*f2635e84SEric Joyner int
66659cf1841cSEric Joyner ice_aq_get_port_options(struct ice_hw *hw,
66669cf1841cSEric Joyner 			struct ice_aqc_get_port_options_elem *options,
66679cf1841cSEric Joyner 			u8 *option_count, u8 lport, bool lport_valid,
66689dc2f6e2SEric Joyner 			u8 *active_option_idx, bool *active_option_valid,
66699dc2f6e2SEric Joyner 			u8 *pending_option_idx, bool *pending_option_valid)
66709cf1841cSEric Joyner {
66719cf1841cSEric Joyner 	struct ice_aqc_get_port_options *cmd;
66729cf1841cSEric Joyner 	struct ice_aq_desc desc;
6673*f2635e84SEric Joyner 	int status;
66749cf1841cSEric Joyner 	u8 i;
66759cf1841cSEric Joyner 
66769cf1841cSEric Joyner 	/* options buffer shall be able to hold max returned options */
66779cf1841cSEric Joyner 	if (*option_count < ICE_AQC_PORT_OPT_COUNT_M)
66789cf1841cSEric Joyner 		return ICE_ERR_PARAM;
66799cf1841cSEric Joyner 
66809cf1841cSEric Joyner 	cmd = &desc.params.get_port_options;
66819cf1841cSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options);
66829cf1841cSEric Joyner 
66839cf1841cSEric Joyner 	cmd->lport_num = lport;
66849cf1841cSEric Joyner 	cmd->lport_num_valid = lport_valid;
66859cf1841cSEric Joyner 
66869cf1841cSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, options,
66879cf1841cSEric Joyner 				 *option_count * sizeof(*options), NULL);
6688*f2635e84SEric Joyner 	if (status)
66899cf1841cSEric Joyner 		return status;
66909cf1841cSEric Joyner 
66919cf1841cSEric Joyner 	/* verify direct FW response & set output parameters */
66929cf1841cSEric Joyner 	*option_count = cmd->port_options_count & ICE_AQC_PORT_OPT_COUNT_M;
66939cf1841cSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count);
66949cf1841cSEric Joyner 	*active_option_valid = cmd->port_options & ICE_AQC_PORT_OPT_VALID;
66959cf1841cSEric Joyner 	if (*active_option_valid) {
66969cf1841cSEric Joyner 		*active_option_idx = cmd->port_options &
66979cf1841cSEric Joyner 				     ICE_AQC_PORT_OPT_ACTIVE_M;
66989cf1841cSEric Joyner 		if (*active_option_idx > (*option_count - 1))
66999cf1841cSEric Joyner 			return ICE_ERR_OUT_OF_RANGE;
67009cf1841cSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n",
67019cf1841cSEric Joyner 			  *active_option_idx);
67029cf1841cSEric Joyner 	}
67039cf1841cSEric Joyner 
67049dc2f6e2SEric Joyner 	*pending_option_valid = cmd->pending_port_option_status &
67059dc2f6e2SEric Joyner 				ICE_AQC_PENDING_PORT_OPT_VALID;
67069dc2f6e2SEric Joyner 	if (*pending_option_valid) {
67079dc2f6e2SEric Joyner 		*pending_option_idx = cmd->pending_port_option_status &
67089dc2f6e2SEric Joyner 				      ICE_AQC_PENDING_PORT_OPT_IDX_M;
67099dc2f6e2SEric Joyner 		if (*pending_option_idx > (*option_count - 1))
67109dc2f6e2SEric Joyner 			return ICE_ERR_OUT_OF_RANGE;
67119dc2f6e2SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n",
67129dc2f6e2SEric Joyner 			  *pending_option_idx);
67139dc2f6e2SEric Joyner 	}
67149dc2f6e2SEric Joyner 
67159dc2f6e2SEric Joyner 	/* mask output options fields */
67169cf1841cSEric Joyner 	for (i = 0; i < *option_count; i++) {
67179cf1841cSEric Joyner 		options[i].pmd &= ICE_AQC_PORT_OPT_PMD_COUNT_M;
67189cf1841cSEric Joyner 		options[i].max_lane_speed &= ICE_AQC_PORT_OPT_MAX_LANE_M;
67199cf1841cSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n",
67209dc2f6e2SEric Joyner 			  options[i].pmd, options[i].max_lane_speed);
67219cf1841cSEric Joyner 	}
67229cf1841cSEric Joyner 
6723*f2635e84SEric Joyner 	return 0;
67249cf1841cSEric Joyner }
67259cf1841cSEric Joyner 
67269cf1841cSEric Joyner /**
67279dc2f6e2SEric Joyner  * ice_aq_set_port_option
67289dc2f6e2SEric Joyner  * @hw: pointer to the hw struct
67299dc2f6e2SEric Joyner  * @lport: logical port to call the command with
67309dc2f6e2SEric Joyner  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
67319dc2f6e2SEric Joyner  *               when PF owns more than 1 port it must be true
67329dc2f6e2SEric Joyner  * @new_option: new port option to be written
67339dc2f6e2SEric Joyner  *
67349dc2f6e2SEric Joyner  * Calls Set Port Options AQC (0x06eb).
67359dc2f6e2SEric Joyner  */
6736*f2635e84SEric Joyner int
67379dc2f6e2SEric Joyner ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
67389dc2f6e2SEric Joyner 		       u8 new_option)
67399dc2f6e2SEric Joyner {
67409dc2f6e2SEric Joyner 	struct ice_aqc_set_port_option *cmd;
67419dc2f6e2SEric Joyner 	struct ice_aq_desc desc;
67429dc2f6e2SEric Joyner 
67439dc2f6e2SEric Joyner 	if (new_option >= ICE_AQC_PORT_OPT_COUNT_M)
67449dc2f6e2SEric Joyner 		return ICE_ERR_PARAM;
67459dc2f6e2SEric Joyner 
67469dc2f6e2SEric Joyner 	cmd = &desc.params.set_port_option;
67479dc2f6e2SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option);
67489dc2f6e2SEric Joyner 
67499dc2f6e2SEric Joyner 	cmd->lport_num = lport;
67509dc2f6e2SEric Joyner 
67519dc2f6e2SEric Joyner 	cmd->lport_num_valid = lport_valid;
67529dc2f6e2SEric Joyner 	cmd->selected_port_option = new_option;
67539dc2f6e2SEric Joyner 
67549dc2f6e2SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
67559dc2f6e2SEric Joyner }
67569dc2f6e2SEric Joyner 
67579dc2f6e2SEric Joyner /**
67587d7af7f8SEric Joyner  * ice_aq_set_lldp_mib - Set the LLDP MIB
67597d7af7f8SEric Joyner  * @hw: pointer to the HW struct
67607d7af7f8SEric Joyner  * @mib_type: Local, Remote or both Local and Remote MIBs
67617d7af7f8SEric Joyner  * @buf: pointer to the caller-supplied buffer to store the MIB block
67627d7af7f8SEric Joyner  * @buf_size: size of the buffer (in bytes)
67637d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
67647d7af7f8SEric Joyner  *
67657d7af7f8SEric Joyner  * Set the LLDP MIB. (0x0A08)
67667d7af7f8SEric Joyner  */
6767*f2635e84SEric Joyner int
67687d7af7f8SEric Joyner ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
67697d7af7f8SEric Joyner 		    struct ice_sq_cd *cd)
67707d7af7f8SEric Joyner {
67717d7af7f8SEric Joyner 	struct ice_aqc_lldp_set_local_mib *cmd;
67727d7af7f8SEric Joyner 	struct ice_aq_desc desc;
67737d7af7f8SEric Joyner 
67747d7af7f8SEric Joyner 	cmd = &desc.params.lldp_set_mib;
67757d7af7f8SEric Joyner 
67767d7af7f8SEric Joyner 	if (buf_size == 0 || !buf)
67777d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
67787d7af7f8SEric Joyner 
67797d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
67807d7af7f8SEric Joyner 
67817d7af7f8SEric Joyner 	desc.flags |= CPU_TO_LE16((u16)ICE_AQ_FLAG_RD);
67827d7af7f8SEric Joyner 	desc.datalen = CPU_TO_LE16(buf_size);
67837d7af7f8SEric Joyner 
67847d7af7f8SEric Joyner 	cmd->type = mib_type;
67857d7af7f8SEric Joyner 	cmd->length = CPU_TO_LE16(buf_size);
67867d7af7f8SEric Joyner 
67877d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
67887d7af7f8SEric Joyner }
67897d7af7f8SEric Joyner 
67907d7af7f8SEric Joyner /**
679156429daeSEric Joyner  * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
67927d7af7f8SEric Joyner  * @hw: pointer to HW struct
67937d7af7f8SEric Joyner  */
67947d7af7f8SEric Joyner bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
67957d7af7f8SEric Joyner {
67968923de59SPiotr Kubaj 	if (hw->mac_type != ICE_MAC_E810 && hw->mac_type != ICE_MAC_GENERIC)
67977d7af7f8SEric Joyner 		return false;
67987d7af7f8SEric Joyner 
67998923de59SPiotr Kubaj 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LLDP_FLTR_MAJ,
68008923de59SPiotr Kubaj 				     ICE_FW_API_LLDP_FLTR_MIN,
68018923de59SPiotr Kubaj 				     ICE_FW_API_LLDP_FLTR_PATCH);
68027d7af7f8SEric Joyner }
68037d7af7f8SEric Joyner 
68047d7af7f8SEric Joyner /**
68057d7af7f8SEric Joyner  * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
68067d7af7f8SEric Joyner  * @hw: pointer to HW struct
68077d7af7f8SEric Joyner  * @vsi_num: absolute HW index for VSI
68087d7af7f8SEric Joyner  * @add: boolean for if adding or removing a filter
68097d7af7f8SEric Joyner  */
6810*f2635e84SEric Joyner int
68117d7af7f8SEric Joyner ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
68127d7af7f8SEric Joyner {
68137d7af7f8SEric Joyner 	struct ice_aqc_lldp_filter_ctrl *cmd;
68147d7af7f8SEric Joyner 	struct ice_aq_desc desc;
68157d7af7f8SEric Joyner 
68167d7af7f8SEric Joyner 	cmd = &desc.params.lldp_filter_ctrl;
68177d7af7f8SEric Joyner 
68187d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
68197d7af7f8SEric Joyner 
68207d7af7f8SEric Joyner 	if (add)
68217d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
68227d7af7f8SEric Joyner 	else
68237d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
68247d7af7f8SEric Joyner 
68257d7af7f8SEric Joyner 	cmd->vsi_num = CPU_TO_LE16(vsi_num);
68267d7af7f8SEric Joyner 
68277d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
68287d7af7f8SEric Joyner }
68299cf1841cSEric Joyner 
68309cf1841cSEric Joyner /**
68318923de59SPiotr Kubaj  * ice_lldp_execute_pending_mib - execute LLDP pending MIB request
68328923de59SPiotr Kubaj  * @hw: pointer to HW struct
68338923de59SPiotr Kubaj  */
6834*f2635e84SEric Joyner int ice_lldp_execute_pending_mib(struct ice_hw *hw)
68358923de59SPiotr Kubaj {
68368923de59SPiotr Kubaj 	struct ice_aq_desc desc;
68378923de59SPiotr Kubaj 
68388923de59SPiotr Kubaj 	ice_fill_dflt_direct_cmd_desc(&desc, ice_execute_pending_lldp_mib);
68398923de59SPiotr Kubaj 
68408923de59SPiotr Kubaj 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
68418923de59SPiotr Kubaj }
68428923de59SPiotr Kubaj 
68438923de59SPiotr Kubaj /**
68449cf1841cSEric Joyner  * ice_fw_supports_report_dflt_cfg
68459cf1841cSEric Joyner  * @hw: pointer to the hardware structure
68469cf1841cSEric Joyner  *
68479cf1841cSEric Joyner  * Checks if the firmware supports report default configuration
68489cf1841cSEric Joyner  */
68499cf1841cSEric Joyner bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
68509cf1841cSEric Joyner {
68518923de59SPiotr Kubaj 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ,
68528923de59SPiotr Kubaj 				     ICE_FW_API_REPORT_DFLT_CFG_MIN,
68538923de59SPiotr Kubaj 				     ICE_FW_API_REPORT_DFLT_CFG_PATCH);
68549cf1841cSEric Joyner }
685556429daeSEric Joyner 
68569dc2f6e2SEric Joyner /* each of the indexes into the following array match the speed of a return
68579dc2f6e2SEric Joyner  * value from the list of AQ returned speeds like the range:
68589dc2f6e2SEric Joyner  * ICE_AQ_LINK_SPEED_10MB .. ICE_AQ_LINK_SPEED_100GB excluding
68599dc2f6e2SEric Joyner  * ICE_AQ_LINK_SPEED_UNKNOWN which is BIT(15) The array is defined as 15
68609dc2f6e2SEric Joyner  * elements long because the link_speed returned by the firmware is a 16 bit
68619dc2f6e2SEric Joyner  * value, but is indexed by [fls(speed) - 1]
68629dc2f6e2SEric Joyner  */
68639c30461dSEric Joyner static const u32 ice_aq_to_link_speed[] = {
68649dc2f6e2SEric Joyner 	ICE_LINK_SPEED_10MBPS,	/* BIT(0) */
68659dc2f6e2SEric Joyner 	ICE_LINK_SPEED_100MBPS,
68669dc2f6e2SEric Joyner 	ICE_LINK_SPEED_1000MBPS,
68679dc2f6e2SEric Joyner 	ICE_LINK_SPEED_2500MBPS,
68689dc2f6e2SEric Joyner 	ICE_LINK_SPEED_5000MBPS,
68699dc2f6e2SEric Joyner 	ICE_LINK_SPEED_10000MBPS,
68709dc2f6e2SEric Joyner 	ICE_LINK_SPEED_20000MBPS,
68719dc2f6e2SEric Joyner 	ICE_LINK_SPEED_25000MBPS,
68729dc2f6e2SEric Joyner 	ICE_LINK_SPEED_40000MBPS,
68739dc2f6e2SEric Joyner 	ICE_LINK_SPEED_50000MBPS,
68749dc2f6e2SEric Joyner 	ICE_LINK_SPEED_100000MBPS,	/* BIT(10) */
6875*f2635e84SEric Joyner 	ICE_LINK_SPEED_200000MBPS,
68769dc2f6e2SEric Joyner };
68779dc2f6e2SEric Joyner 
68789dc2f6e2SEric Joyner /**
68799dc2f6e2SEric Joyner  * ice_get_link_speed - get integer speed from table
68809dc2f6e2SEric Joyner  * @index: array index from fls(aq speed) - 1
68819dc2f6e2SEric Joyner  *
68829dc2f6e2SEric Joyner  * Returns: u32 value containing integer speed
68839dc2f6e2SEric Joyner  */
68849dc2f6e2SEric Joyner u32 ice_get_link_speed(u16 index)
68859dc2f6e2SEric Joyner {
68869c30461dSEric Joyner 	if (index >= ARRAY_SIZE(ice_aq_to_link_speed))
68879c30461dSEric Joyner 		return ICE_LINK_SPEED_UNKNOWN;
68889c30461dSEric Joyner 
68899dc2f6e2SEric Joyner 	return ice_aq_to_link_speed[index];
68909dc2f6e2SEric Joyner }
68919dc2f6e2SEric Joyner 
689256429daeSEric Joyner /**
68938923de59SPiotr Kubaj  * ice_fw_supports_fec_dis_auto
68948923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
68958923de59SPiotr Kubaj  *
68968923de59SPiotr Kubaj  * Checks if the firmware supports FEC disable in Auto FEC mode
68978923de59SPiotr Kubaj  */
68988923de59SPiotr Kubaj bool ice_fw_supports_fec_dis_auto(struct ice_hw *hw)
68998923de59SPiotr Kubaj {
6900*f2635e84SEric Joyner 	if (ice_is_e830(hw))
6901*f2635e84SEric Joyner 		return true;
69029e54973fSEric Joyner 	return ice_is_fw_min_ver(hw, ICE_FW_VER_BRANCH_E810,
69038923de59SPiotr Kubaj 				 ICE_FW_FEC_DIS_AUTO_MAJ,
69048923de59SPiotr Kubaj 				 ICE_FW_FEC_DIS_AUTO_MIN,
69059e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_PATCH) ||
69069e54973fSEric Joyner 	       ice_is_fw_min_ver(hw, ICE_FW_VER_BRANCH_E82X,
69079e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_MAJ_E82X,
69089e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_MIN_E82X,
69099e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_PATCH_E82X);
69108923de59SPiotr Kubaj }
69119c30461dSEric Joyner 
69128923de59SPiotr Kubaj /**
691356429daeSEric Joyner  * ice_is_fw_auto_drop_supported
691456429daeSEric Joyner  * @hw: pointer to the hardware structure
691556429daeSEric Joyner  *
691656429daeSEric Joyner  * Checks if the firmware supports auto drop feature
691756429daeSEric Joyner  */
691856429daeSEric Joyner bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)
691956429daeSEric Joyner {
692056429daeSEric Joyner 	if (hw->api_maj_ver >= ICE_FW_API_AUTO_DROP_MAJ &&
692156429daeSEric Joyner 	    hw->api_min_ver >= ICE_FW_API_AUTO_DROP_MIN)
692256429daeSEric Joyner 		return true;
692356429daeSEric Joyner 	return false;
692456429daeSEric Joyner }
69258923de59SPiotr Kubaj 
6926