xref: /freebsd/sys/dev/ice/ice_common.c (revision 9e54973fc33aa44b77d1c851cb36fcd82dc44cda)
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 
3671d10453SEric Joyner #include "ice_flow.h"
3771d10453SEric Joyner #include "ice_switch.h"
3871d10453SEric Joyner 
399dc2f6e2SEric Joyner #define ICE_PF_RESET_WAIT_COUNT	500
4071d10453SEric Joyner 
418923de59SPiotr Kubaj static const char * const ice_link_mode_str_low[] = {
429dc2f6e2SEric Joyner 	ice_arr_elem_idx(0, "100BASE_TX"),
439dc2f6e2SEric Joyner 	ice_arr_elem_idx(1, "100M_SGMII"),
449dc2f6e2SEric Joyner 	ice_arr_elem_idx(2, "1000BASE_T"),
459dc2f6e2SEric Joyner 	ice_arr_elem_idx(3, "1000BASE_SX"),
469dc2f6e2SEric Joyner 	ice_arr_elem_idx(4, "1000BASE_LX"),
479dc2f6e2SEric Joyner 	ice_arr_elem_idx(5, "1000BASE_KX"),
489dc2f6e2SEric Joyner 	ice_arr_elem_idx(6, "1G_SGMII"),
499dc2f6e2SEric Joyner 	ice_arr_elem_idx(7, "2500BASE_T"),
509dc2f6e2SEric Joyner 	ice_arr_elem_idx(8, "2500BASE_X"),
519dc2f6e2SEric Joyner 	ice_arr_elem_idx(9, "2500BASE_KX"),
529dc2f6e2SEric Joyner 	ice_arr_elem_idx(10, "5GBASE_T"),
539dc2f6e2SEric Joyner 	ice_arr_elem_idx(11, "5GBASE_KR"),
549dc2f6e2SEric Joyner 	ice_arr_elem_idx(12, "10GBASE_T"),
559dc2f6e2SEric Joyner 	ice_arr_elem_idx(13, "10G_SFI_DA"),
569dc2f6e2SEric Joyner 	ice_arr_elem_idx(14, "10GBASE_SR"),
579dc2f6e2SEric Joyner 	ice_arr_elem_idx(15, "10GBASE_LR"),
589dc2f6e2SEric Joyner 	ice_arr_elem_idx(16, "10GBASE_KR_CR1"),
599dc2f6e2SEric Joyner 	ice_arr_elem_idx(17, "10G_SFI_AOC_ACC"),
609dc2f6e2SEric Joyner 	ice_arr_elem_idx(18, "10G_SFI_C2C"),
619dc2f6e2SEric Joyner 	ice_arr_elem_idx(19, "25GBASE_T"),
629dc2f6e2SEric Joyner 	ice_arr_elem_idx(20, "25GBASE_CR"),
639dc2f6e2SEric Joyner 	ice_arr_elem_idx(21, "25GBASE_CR_S"),
649dc2f6e2SEric Joyner 	ice_arr_elem_idx(22, "25GBASE_CR1"),
659dc2f6e2SEric Joyner 	ice_arr_elem_idx(23, "25GBASE_SR"),
669dc2f6e2SEric Joyner 	ice_arr_elem_idx(24, "25GBASE_LR"),
679dc2f6e2SEric Joyner 	ice_arr_elem_idx(25, "25GBASE_KR"),
689dc2f6e2SEric Joyner 	ice_arr_elem_idx(26, "25GBASE_KR_S"),
699dc2f6e2SEric Joyner 	ice_arr_elem_idx(27, "25GBASE_KR1"),
709dc2f6e2SEric Joyner 	ice_arr_elem_idx(28, "25G_AUI_AOC_ACC"),
719dc2f6e2SEric Joyner 	ice_arr_elem_idx(29, "25G_AUI_C2C"),
729dc2f6e2SEric Joyner 	ice_arr_elem_idx(30, "40GBASE_CR4"),
739dc2f6e2SEric Joyner 	ice_arr_elem_idx(31, "40GBASE_SR4"),
749dc2f6e2SEric Joyner 	ice_arr_elem_idx(32, "40GBASE_LR4"),
759dc2f6e2SEric Joyner 	ice_arr_elem_idx(33, "40GBASE_KR4"),
769dc2f6e2SEric Joyner 	ice_arr_elem_idx(34, "40G_XLAUI_AOC_ACC"),
779dc2f6e2SEric Joyner 	ice_arr_elem_idx(35, "40G_XLAUI"),
789dc2f6e2SEric Joyner 	ice_arr_elem_idx(36, "50GBASE_CR2"),
799dc2f6e2SEric Joyner 	ice_arr_elem_idx(37, "50GBASE_SR2"),
809dc2f6e2SEric Joyner 	ice_arr_elem_idx(38, "50GBASE_LR2"),
819dc2f6e2SEric Joyner 	ice_arr_elem_idx(39, "50GBASE_KR2"),
829dc2f6e2SEric Joyner 	ice_arr_elem_idx(40, "50G_LAUI2_AOC_ACC"),
839dc2f6e2SEric Joyner 	ice_arr_elem_idx(41, "50G_LAUI2"),
849dc2f6e2SEric Joyner 	ice_arr_elem_idx(42, "50G_AUI2_AOC_ACC"),
859dc2f6e2SEric Joyner 	ice_arr_elem_idx(43, "50G_AUI2"),
869dc2f6e2SEric Joyner 	ice_arr_elem_idx(44, "50GBASE_CP"),
879dc2f6e2SEric Joyner 	ice_arr_elem_idx(45, "50GBASE_SR"),
889dc2f6e2SEric Joyner 	ice_arr_elem_idx(46, "50GBASE_FR"),
899dc2f6e2SEric Joyner 	ice_arr_elem_idx(47, "50GBASE_LR"),
909dc2f6e2SEric Joyner 	ice_arr_elem_idx(48, "50GBASE_KR_PAM4"),
919dc2f6e2SEric Joyner 	ice_arr_elem_idx(49, "50G_AUI1_AOC_ACC"),
929dc2f6e2SEric Joyner 	ice_arr_elem_idx(50, "50G_AUI1"),
939dc2f6e2SEric Joyner 	ice_arr_elem_idx(51, "100GBASE_CR4"),
949dc2f6e2SEric Joyner 	ice_arr_elem_idx(52, "100GBASE_SR4"),
959dc2f6e2SEric Joyner 	ice_arr_elem_idx(53, "100GBASE_LR4"),
969dc2f6e2SEric Joyner 	ice_arr_elem_idx(54, "100GBASE_KR4"),
979dc2f6e2SEric Joyner 	ice_arr_elem_idx(55, "100G_CAUI4_AOC_ACC"),
989dc2f6e2SEric Joyner 	ice_arr_elem_idx(56, "100G_CAUI4"),
999dc2f6e2SEric Joyner 	ice_arr_elem_idx(57, "100G_AUI4_AOC_ACC"),
1009dc2f6e2SEric Joyner 	ice_arr_elem_idx(58, "100G_AUI4"),
1019dc2f6e2SEric Joyner 	ice_arr_elem_idx(59, "100GBASE_CR_PAM4"),
1029dc2f6e2SEric Joyner 	ice_arr_elem_idx(60, "100GBASE_KR_PAM4"),
1039dc2f6e2SEric Joyner 	ice_arr_elem_idx(61, "100GBASE_CP2"),
1049dc2f6e2SEric Joyner 	ice_arr_elem_idx(62, "100GBASE_SR2"),
1059dc2f6e2SEric Joyner 	ice_arr_elem_idx(63, "100GBASE_DR"),
1068923de59SPiotr Kubaj };
1078923de59SPiotr Kubaj 
1088923de59SPiotr Kubaj static const char * const ice_link_mode_str_high[] = {
1099dc2f6e2SEric Joyner 	ice_arr_elem_idx(0, "100GBASE_KR2_PAM4"),
1109dc2f6e2SEric Joyner 	ice_arr_elem_idx(1, "100G_CAUI2_AOC_ACC"),
1119dc2f6e2SEric Joyner 	ice_arr_elem_idx(2, "100G_CAUI2"),
1129dc2f6e2SEric Joyner 	ice_arr_elem_idx(3, "100G_AUI2_AOC_ACC"),
1139dc2f6e2SEric Joyner 	ice_arr_elem_idx(4, "100G_AUI2"),
1148923de59SPiotr Kubaj };
11556429daeSEric Joyner 
11656429daeSEric Joyner /**
1178923de59SPiotr Kubaj  * ice_dump_phy_type - helper function to dump phy_type
11856429daeSEric Joyner  * @hw: pointer to the HW structure
11956429daeSEric Joyner  * @low: 64 bit value for phy_type_low
12056429daeSEric Joyner  * @high: 64 bit value for phy_type_high
12156429daeSEric Joyner  * @prefix: prefix string to differentiate multiple dumps
12256429daeSEric Joyner  */
12356429daeSEric Joyner static void
1248923de59SPiotr Kubaj ice_dump_phy_type(struct ice_hw *hw, u64 low, u64 high, const char *prefix)
12556429daeSEric Joyner {
1268923de59SPiotr Kubaj 	u32 i;
1278923de59SPiotr Kubaj 
1288923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix,
1298923de59SPiotr Kubaj 		  (unsigned long long)low);
1308923de59SPiotr Kubaj 
1318923de59SPiotr Kubaj 	for (i = 0; i < ARRAY_SIZE(ice_link_mode_str_low); i++) {
1328923de59SPiotr Kubaj 		if (low & BIT_ULL(i))
1338923de59SPiotr Kubaj 			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
1348923de59SPiotr Kubaj 				  prefix, i, ice_link_mode_str_low[i]);
1358923de59SPiotr Kubaj 	}
1368923de59SPiotr Kubaj 
13756429daeSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix,
13856429daeSEric Joyner 		  (unsigned long long)high);
13956429daeSEric Joyner 
1408923de59SPiotr Kubaj 	for (i = 0; i < ARRAY_SIZE(ice_link_mode_str_high); i++) {
1418923de59SPiotr Kubaj 		if (high & BIT_ULL(i))
1428923de59SPiotr Kubaj 			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
1438923de59SPiotr Kubaj 				  prefix, i, ice_link_mode_str_high[i]);
1448923de59SPiotr Kubaj 	}
14556429daeSEric Joyner }
14656429daeSEric Joyner 
14756429daeSEric Joyner /**
14871d10453SEric Joyner  * ice_set_mac_type - Sets MAC type
14971d10453SEric Joyner  * @hw: pointer to the HW structure
15071d10453SEric Joyner  *
15171d10453SEric Joyner  * This function sets the MAC type of the adapter based on the
15271d10453SEric Joyner  * vendor ID and device ID stored in the HW structure.
15371d10453SEric Joyner  */
15471d10453SEric Joyner enum ice_status ice_set_mac_type(struct ice_hw *hw)
15571d10453SEric Joyner {
15671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
15771d10453SEric Joyner 
15871d10453SEric Joyner 	if (hw->vendor_id != ICE_INTEL_VENDOR_ID)
15971d10453SEric Joyner 		return ICE_ERR_DEVICE_NOT_SUPPORTED;
16071d10453SEric Joyner 
16171d10453SEric Joyner 	switch (hw->device_id) {
16271d10453SEric Joyner 	case ICE_DEV_ID_E810C_BACKPLANE:
16371d10453SEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
16471d10453SEric Joyner 	case ICE_DEV_ID_E810C_SFP:
16571d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_BACKPLANE:
16671d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_QSFP:
16771d10453SEric Joyner 	case ICE_DEV_ID_E810_XXV_SFP:
16871d10453SEric Joyner 		hw->mac_type = ICE_MAC_E810;
16971d10453SEric Joyner 		break;
17071d10453SEric Joyner 	case ICE_DEV_ID_E822C_10G_BASE_T:
17171d10453SEric Joyner 	case ICE_DEV_ID_E822C_BACKPLANE:
17271d10453SEric Joyner 	case ICE_DEV_ID_E822C_QSFP:
17371d10453SEric Joyner 	case ICE_DEV_ID_E822C_SFP:
17471d10453SEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
17571d10453SEric Joyner 	case ICE_DEV_ID_E822L_10G_BASE_T:
17671d10453SEric Joyner 	case ICE_DEV_ID_E822L_BACKPLANE:
17771d10453SEric Joyner 	case ICE_DEV_ID_E822L_SFP:
17871d10453SEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
17971d10453SEric Joyner 	case ICE_DEV_ID_E823L_10G_BASE_T:
18071d10453SEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
18171d10453SEric Joyner 	case ICE_DEV_ID_E823L_BACKPLANE:
18271d10453SEric Joyner 	case ICE_DEV_ID_E823L_QSFP:
18371d10453SEric Joyner 	case ICE_DEV_ID_E823L_SFP:
18456429daeSEric Joyner 	case ICE_DEV_ID_E823C_10G_BASE_T:
18556429daeSEric Joyner 	case ICE_DEV_ID_E823C_BACKPLANE:
18656429daeSEric Joyner 	case ICE_DEV_ID_E823C_QSFP:
18756429daeSEric Joyner 	case ICE_DEV_ID_E823C_SFP:
18856429daeSEric Joyner 	case ICE_DEV_ID_E823C_SGMII:
18971d10453SEric Joyner 		hw->mac_type = ICE_MAC_GENERIC;
19071d10453SEric Joyner 		break;
19171d10453SEric Joyner 	default:
19271d10453SEric Joyner 		hw->mac_type = ICE_MAC_UNKNOWN;
19371d10453SEric Joyner 		break;
19471d10453SEric Joyner 	}
19571d10453SEric Joyner 
19671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
19771d10453SEric Joyner 	return ICE_SUCCESS;
19871d10453SEric Joyner }
19971d10453SEric Joyner 
20071d10453SEric Joyner /**
20156429daeSEric Joyner  * ice_is_e810
20256429daeSEric Joyner  * @hw: pointer to the hardware structure
20356429daeSEric Joyner  *
20456429daeSEric Joyner  * returns true if the device is E810 based, false if not.
20556429daeSEric Joyner  */
20656429daeSEric Joyner bool ice_is_e810(struct ice_hw *hw)
20756429daeSEric Joyner {
20856429daeSEric Joyner 	return hw->mac_type == ICE_MAC_E810;
20956429daeSEric Joyner }
21056429daeSEric Joyner 
21156429daeSEric Joyner /**
21256429daeSEric Joyner  * ice_is_e810t
21356429daeSEric Joyner  * @hw: pointer to the hardware structure
21456429daeSEric Joyner  *
21556429daeSEric Joyner  * returns true if the device is E810T based, false if not.
21656429daeSEric Joyner  */
21756429daeSEric Joyner bool ice_is_e810t(struct ice_hw *hw)
21856429daeSEric Joyner {
21956429daeSEric Joyner 	switch (hw->device_id) {
22056429daeSEric Joyner 	case ICE_DEV_ID_E810C_SFP:
2218923de59SPiotr Kubaj 		switch (hw->subsystem_device_id) {
2228923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T:
2238923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T2:
2248923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T3:
2258923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T4:
2268923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T5:
2278923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T7:
22856429daeSEric Joyner 			return true;
2298923de59SPiotr Kubaj 		}
23056429daeSEric Joyner 		break;
23156429daeSEric Joyner 	case ICE_DEV_ID_E810C_QSFP:
2328923de59SPiotr Kubaj 		switch (hw->subsystem_device_id) {
2338923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T2:
2348923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T5:
2358923de59SPiotr Kubaj 		case ICE_SUBDEV_ID_E810T6:
23656429daeSEric Joyner 			return true;
2378923de59SPiotr Kubaj 		}
23856429daeSEric Joyner 		break;
23956429daeSEric Joyner 	default:
24056429daeSEric Joyner 		break;
24156429daeSEric Joyner 	}
24256429daeSEric Joyner 
24356429daeSEric Joyner 	return false;
24456429daeSEric Joyner }
24556429daeSEric Joyner 
24656429daeSEric Joyner /**
2478923de59SPiotr Kubaj  * ice_is_e823
2488923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
2498923de59SPiotr Kubaj  *
2508923de59SPiotr Kubaj  * returns true if the device is E823-L or E823-C based, false if not.
2518923de59SPiotr Kubaj  */
2528923de59SPiotr Kubaj bool ice_is_e823(struct ice_hw *hw)
2538923de59SPiotr Kubaj {
2548923de59SPiotr Kubaj 	switch (hw->device_id) {
2558923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_BACKPLANE:
2568923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_SFP:
2578923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_10G_BASE_T:
2588923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_1GBE:
2598923de59SPiotr Kubaj 	case ICE_DEV_ID_E823L_QSFP:
2608923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_BACKPLANE:
2618923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_QSFP:
2628923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_SFP:
2638923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_10G_BASE_T:
2648923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_SGMII:
2658923de59SPiotr Kubaj 		return true;
2668923de59SPiotr Kubaj 	default:
2678923de59SPiotr Kubaj 		return false;
2688923de59SPiotr Kubaj 	}
2698923de59SPiotr Kubaj }
2708923de59SPiotr Kubaj 
2718923de59SPiotr Kubaj /**
27271d10453SEric Joyner  * ice_clear_pf_cfg - Clear PF configuration
27371d10453SEric Joyner  * @hw: pointer to the hardware structure
27471d10453SEric Joyner  *
27571d10453SEric Joyner  * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
27671d10453SEric Joyner  * configuration, flow director filters, etc.).
27771d10453SEric Joyner  */
27871d10453SEric Joyner enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
27971d10453SEric Joyner {
28071d10453SEric Joyner 	struct ice_aq_desc desc;
28171d10453SEric Joyner 
28271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
28371d10453SEric Joyner 
28471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
28571d10453SEric Joyner }
28671d10453SEric Joyner 
28771d10453SEric Joyner /**
28871d10453SEric Joyner  * ice_aq_manage_mac_read - manage MAC address read command
28971d10453SEric Joyner  * @hw: pointer to the HW struct
29071d10453SEric Joyner  * @buf: a virtual buffer to hold the manage MAC read response
29171d10453SEric Joyner  * @buf_size: Size of the virtual buffer
29271d10453SEric Joyner  * @cd: pointer to command details structure or NULL
29371d10453SEric Joyner  *
29471d10453SEric Joyner  * This function is used to return per PF station MAC address (0x0107).
29571d10453SEric Joyner  * NOTE: Upon successful completion of this command, MAC address information
29671d10453SEric Joyner  * is returned in user specified buffer. Please interpret user specified
29771d10453SEric Joyner  * buffer as "manage_mac_read" response.
29871d10453SEric Joyner  * Response such as various MAC addresses are stored in HW struct (port.mac)
2997d7af7f8SEric Joyner  * ice_discover_dev_caps is expected to be called before this function is
3007d7af7f8SEric Joyner  * called.
30171d10453SEric Joyner  */
30271d10453SEric Joyner enum ice_status
30371d10453SEric Joyner ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
30471d10453SEric Joyner 		       struct ice_sq_cd *cd)
30571d10453SEric Joyner {
30671d10453SEric Joyner 	struct ice_aqc_manage_mac_read_resp *resp;
30771d10453SEric Joyner 	struct ice_aqc_manage_mac_read *cmd;
30871d10453SEric Joyner 	struct ice_aq_desc desc;
30971d10453SEric Joyner 	enum ice_status status;
31071d10453SEric Joyner 	u16 flags;
31171d10453SEric Joyner 	u8 i;
31271d10453SEric Joyner 
31371d10453SEric Joyner 	cmd = &desc.params.mac_read;
31471d10453SEric Joyner 
31571d10453SEric Joyner 	if (buf_size < sizeof(*resp))
31671d10453SEric Joyner 		return ICE_ERR_BUF_TOO_SHORT;
31771d10453SEric Joyner 
31871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
31971d10453SEric Joyner 
32071d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
32171d10453SEric Joyner 	if (status)
32271d10453SEric Joyner 		return status;
32371d10453SEric Joyner 
32471d10453SEric Joyner 	resp = (struct ice_aqc_manage_mac_read_resp *)buf;
32571d10453SEric Joyner 	flags = LE16_TO_CPU(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
32671d10453SEric Joyner 
32771d10453SEric Joyner 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
32871d10453SEric Joyner 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
32971d10453SEric Joyner 		return ICE_ERR_CFG;
33071d10453SEric Joyner 	}
33171d10453SEric Joyner 
33271d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
33371d10453SEric Joyner 	for (i = 0; i < cmd->num_addr; i++)
33471d10453SEric Joyner 		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
33571d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.lan_addr,
33671d10453SEric Joyner 				   resp[i].mac_addr, ETH_ALEN,
3378923de59SPiotr Kubaj 				   ICE_NONDMA_TO_NONDMA);
33871d10453SEric Joyner 			ice_memcpy(hw->port_info->mac.perm_addr,
33971d10453SEric Joyner 				   resp[i].mac_addr,
3408923de59SPiotr Kubaj 				   ETH_ALEN, ICE_NONDMA_TO_NONDMA);
34171d10453SEric Joyner 			break;
34271d10453SEric Joyner 		}
34371d10453SEric Joyner 	return ICE_SUCCESS;
34471d10453SEric Joyner }
34571d10453SEric Joyner 
34671d10453SEric Joyner /**
3479c30461dSEric Joyner  * ice_phy_maps_to_media
3489c30461dSEric Joyner  * @phy_type_low: PHY type low bits
3499c30461dSEric Joyner  * @phy_type_high: PHY type high bits
3509c30461dSEric Joyner  * @media_mask_low: media type PHY type low bitmask
3519c30461dSEric Joyner  * @media_mask_high: media type PHY type high bitmask
3529c30461dSEric Joyner  *
3539c30461dSEric Joyner  * Return true if PHY type [low|high] bits are only of media type PHY types
3549c30461dSEric Joyner  * [low|high] bitmask.
3559c30461dSEric Joyner  */
3569c30461dSEric Joyner static bool
3579c30461dSEric Joyner ice_phy_maps_to_media(u64 phy_type_low, u64 phy_type_high,
3589c30461dSEric Joyner 		      u64 media_mask_low, u64 media_mask_high)
3599c30461dSEric Joyner {
3609c30461dSEric Joyner 	/* check if a PHY type exist for media type */
3619c30461dSEric Joyner 	if (!(phy_type_low & media_mask_low ||
3629c30461dSEric Joyner 	      phy_type_high & media_mask_high))
3639c30461dSEric Joyner 		return false;
3649c30461dSEric Joyner 
3659c30461dSEric Joyner 	/* check that PHY types are only of media type */
3669c30461dSEric Joyner 	if (!(phy_type_low & ~media_mask_low) &&
3679c30461dSEric Joyner 	    !(phy_type_high & ~media_mask_high))
3689c30461dSEric Joyner 		return true;
3699c30461dSEric Joyner 
3709c30461dSEric Joyner 	return false;
3719c30461dSEric Joyner }
3729c30461dSEric Joyner 
3739c30461dSEric Joyner /**
3749c30461dSEric Joyner  * ice_set_media_type - Sets media type
3759c30461dSEric Joyner  * @pi: port information structure
3769c30461dSEric Joyner  *
3779c30461dSEric Joyner  * Set ice_port_info PHY media type based on PHY type. This should be called
3789c30461dSEric Joyner  * from Get PHY caps with media.
3799c30461dSEric Joyner  */
3809c30461dSEric Joyner static void ice_set_media_type(struct ice_port_info *pi)
3819c30461dSEric Joyner {
3829c30461dSEric Joyner 	enum ice_media_type *media_type;
3839c30461dSEric Joyner 	u64 phy_type_high, phy_type_low;
3849c30461dSEric Joyner 
3859c30461dSEric Joyner 	phy_type_high = pi->phy.phy_type_high;
3869c30461dSEric Joyner 	phy_type_low = pi->phy.phy_type_low;
3879c30461dSEric Joyner 	media_type = &pi->phy.media_type;
3889c30461dSEric Joyner 
3899c30461dSEric Joyner 	/* if no media, then media type is NONE */
3909c30461dSEric Joyner 	if (!(pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE))
3919c30461dSEric Joyner 		*media_type = ICE_MEDIA_NONE;
3929c30461dSEric Joyner 	/* else if PHY types are only BASE-T, then media type is BASET */
3939c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
3949c30461dSEric Joyner 				       ICE_MEDIA_BASET_PHY_TYPE_LOW_M, 0))
3959c30461dSEric Joyner 		*media_type = ICE_MEDIA_BASET;
3969c30461dSEric Joyner 	/* else if any PHY type is BACKPLANE, then media type is BACKPLANE */
3979c30461dSEric Joyner 	else if (phy_type_low & ICE_MEDIA_BP_PHY_TYPE_LOW_M ||
3989c30461dSEric Joyner 		 phy_type_high & ICE_MEDIA_BP_PHY_TYPE_HIGH_M)
3999c30461dSEric Joyner 		*media_type = ICE_MEDIA_BACKPLANE;
4009c30461dSEric Joyner 	/* else if PHY types are only optical, or optical and C2M, then media
4019c30461dSEric Joyner 	 * type is FIBER
4029c30461dSEric Joyner 	 */
4039c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
4049c30461dSEric Joyner 				       ICE_MEDIA_OPT_PHY_TYPE_LOW_M, 0) ||
4059c30461dSEric Joyner 		 (phy_type_low & ICE_MEDIA_OPT_PHY_TYPE_LOW_M &&
4069c30461dSEric Joyner 		  phy_type_low & ICE_MEDIA_C2M_PHY_TYPE_LOW_M))
4079c30461dSEric Joyner 		*media_type = ICE_MEDIA_FIBER;
4089c30461dSEric Joyner 	/* else if PHY types are only DA, or DA and C2C, then media type DA */
4099c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
4109c30461dSEric Joyner 				       ICE_MEDIA_DAC_PHY_TYPE_LOW_M, 0) ||
4119c30461dSEric Joyner 		 (phy_type_low & ICE_MEDIA_DAC_PHY_TYPE_LOW_M &&
4129c30461dSEric Joyner 		 (phy_type_low & ICE_MEDIA_C2C_PHY_TYPE_LOW_M ||
4139c30461dSEric Joyner 		  phy_type_high & ICE_MEDIA_C2C_PHY_TYPE_HIGH_M)))
4149c30461dSEric Joyner 		*media_type = ICE_MEDIA_DA;
4159c30461dSEric Joyner 	/* else if PHY types are only C2M or only C2C, then media is AUI */
4169c30461dSEric Joyner 	else if (ice_phy_maps_to_media(phy_type_low, phy_type_high,
4179c30461dSEric Joyner 				       ICE_MEDIA_C2M_PHY_TYPE_LOW_M,
4189c30461dSEric Joyner 				       ICE_MEDIA_C2M_PHY_TYPE_HIGH_M) ||
4199c30461dSEric Joyner 		 ice_phy_maps_to_media(phy_type_low, phy_type_high,
4209c30461dSEric Joyner 				       ICE_MEDIA_C2C_PHY_TYPE_LOW_M,
4219c30461dSEric Joyner 				       ICE_MEDIA_C2C_PHY_TYPE_HIGH_M))
4229c30461dSEric Joyner 		*media_type = ICE_MEDIA_AUI;
4239c30461dSEric Joyner 
4249c30461dSEric Joyner 	else
4259c30461dSEric Joyner 		*media_type = ICE_MEDIA_UNKNOWN;
4269c30461dSEric Joyner }
4279c30461dSEric Joyner 
4289c30461dSEric Joyner /**
42971d10453SEric Joyner  * ice_aq_get_phy_caps - returns PHY capabilities
43071d10453SEric Joyner  * @pi: port information structure
43171d10453SEric Joyner  * @qual_mods: report qualified modules
43271d10453SEric Joyner  * @report_mode: report mode capabilities
43371d10453SEric Joyner  * @pcaps: structure for PHY capabilities to be filled
43471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
43571d10453SEric Joyner  *
43671d10453SEric Joyner  * Returns the various PHY capabilities supported on the Port (0x0600)
43771d10453SEric Joyner  */
43871d10453SEric Joyner enum ice_status
43971d10453SEric Joyner ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
44071d10453SEric Joyner 		    struct ice_aqc_get_phy_caps_data *pcaps,
44171d10453SEric Joyner 		    struct ice_sq_cd *cd)
44271d10453SEric Joyner {
44371d10453SEric Joyner 	struct ice_aqc_get_phy_caps *cmd;
44471d10453SEric Joyner 	u16 pcaps_size = sizeof(*pcaps);
44571d10453SEric Joyner 	struct ice_aq_desc desc;
44671d10453SEric Joyner 	enum ice_status status;
44756429daeSEric Joyner 	const char *prefix;
4487d7af7f8SEric Joyner 	struct ice_hw *hw;
44971d10453SEric Joyner 
45071d10453SEric Joyner 	cmd = &desc.params.get_phy;
45171d10453SEric Joyner 
45271d10453SEric Joyner 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
45371d10453SEric Joyner 		return ICE_ERR_PARAM;
4547d7af7f8SEric Joyner 	hw = pi->hw;
45571d10453SEric Joyner 
4569cf1841cSEric Joyner 	if (report_mode == ICE_AQC_REPORT_DFLT_CFG &&
4579cf1841cSEric Joyner 	    !ice_fw_supports_report_dflt_cfg(hw))
4589cf1841cSEric Joyner 		return ICE_ERR_PARAM;
4599cf1841cSEric Joyner 
46071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
46171d10453SEric Joyner 
46271d10453SEric Joyner 	if (qual_mods)
46371d10453SEric Joyner 		cmd->param0 |= CPU_TO_LE16(ICE_AQC_GET_PHY_RQM);
46471d10453SEric Joyner 
46571d10453SEric Joyner 	cmd->param0 |= CPU_TO_LE16(report_mode);
4668923de59SPiotr Kubaj 
4677d7af7f8SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
4687d7af7f8SEric Joyner 
46956429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
47056429daeSEric Joyner 
4718923de59SPiotr Kubaj 	switch (report_mode) {
4728923de59SPiotr Kubaj 	case ICE_AQC_REPORT_TOPO_CAP_MEDIA:
47356429daeSEric Joyner 		prefix = "phy_caps_media";
4748923de59SPiotr Kubaj 		break;
4758923de59SPiotr Kubaj 	case ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA:
47656429daeSEric Joyner 		prefix = "phy_caps_no_media";
4778923de59SPiotr Kubaj 		break;
4788923de59SPiotr Kubaj 	case ICE_AQC_REPORT_ACTIVE_CFG:
47956429daeSEric Joyner 		prefix = "phy_caps_active";
4808923de59SPiotr Kubaj 		break;
4818923de59SPiotr Kubaj 	case ICE_AQC_REPORT_DFLT_CFG:
48256429daeSEric Joyner 		prefix = "phy_caps_default";
4838923de59SPiotr Kubaj 		break;
4848923de59SPiotr Kubaj 	default:
48556429daeSEric Joyner 		prefix = "phy_caps_invalid";
4868923de59SPiotr Kubaj 	}
48756429daeSEric Joyner 
4888923de59SPiotr Kubaj 	ice_dump_phy_type(hw, LE64_TO_CPU(pcaps->phy_type_low),
4898923de59SPiotr Kubaj 			  LE64_TO_CPU(pcaps->phy_type_high), prefix);
49056429daeSEric Joyner 
49156429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
49256429daeSEric Joyner 		  prefix, report_mode);
49356429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
49456429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
4957d7af7f8SEric Joyner 		  pcaps->low_power_ctrl_an);
49656429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
49756429daeSEric Joyner 		  pcaps->eee_cap);
49856429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
4997d7af7f8SEric Joyner 		  pcaps->eeer_value);
50056429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
5017d7af7f8SEric Joyner 		  pcaps->link_fec_options);
50256429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
50356429daeSEric Joyner 		  prefix, pcaps->module_compliance_enforcement);
50456429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
50556429daeSEric Joyner 		  prefix, pcaps->extended_compliance_code);
50656429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
5077d7af7f8SEric Joyner 		  pcaps->module_type[0]);
50856429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
5097d7af7f8SEric Joyner 		  pcaps->module_type[1]);
51056429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
5117d7af7f8SEric Joyner 		  pcaps->module_type[2]);
51271d10453SEric Joyner 
5139cf1841cSEric Joyner 	if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
51471d10453SEric Joyner 		pi->phy.phy_type_low = LE64_TO_CPU(pcaps->phy_type_low);
51571d10453SEric Joyner 		pi->phy.phy_type_high = LE64_TO_CPU(pcaps->phy_type_high);
5167d7af7f8SEric Joyner 		ice_memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
5177d7af7f8SEric Joyner 			   sizeof(pi->phy.link_info.module_type),
5187d7af7f8SEric Joyner 			   ICE_NONDMA_TO_NONDMA);
5199c30461dSEric Joyner 		ice_set_media_type(pi);
5209c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_LINK, "%s: media_type = 0x%x\n", prefix,
5219c30461dSEric Joyner 			  pi->phy.media_type);
52271d10453SEric Joyner 	}
52371d10453SEric Joyner 
52471d10453SEric Joyner 	return status;
52571d10453SEric Joyner }
52671d10453SEric Joyner 
52771d10453SEric Joyner /**
52856429daeSEric Joyner  * ice_aq_get_netlist_node
52956429daeSEric Joyner  * @hw: pointer to the hw struct
53056429daeSEric Joyner  * @cmd: get_link_topo AQ structure
53156429daeSEric Joyner  * @node_part_number: output node part number if node found
53256429daeSEric Joyner  * @node_handle: output node handle parameter if node found
53371d10453SEric Joyner  */
53456429daeSEric Joyner enum ice_status
53556429daeSEric Joyner ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
53656429daeSEric Joyner 			u8 *node_part_number, u16 *node_handle)
53771d10453SEric Joyner {
53871d10453SEric Joyner 	struct ice_aq_desc desc;
53971d10453SEric Joyner 
54071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
54156429daeSEric Joyner 	desc.params.get_link_topo = *cmd;
54271d10453SEric Joyner 
54356429daeSEric Joyner 	if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL))
54456429daeSEric Joyner 		return ICE_ERR_NOT_SUPPORTED;
54571d10453SEric Joyner 
54656429daeSEric Joyner 	if (node_handle)
54756429daeSEric Joyner 		*node_handle =
54856429daeSEric Joyner 			LE16_TO_CPU(desc.params.get_link_topo.addr.handle);
54956429daeSEric Joyner 	if (node_part_number)
55056429daeSEric Joyner 		*node_part_number = desc.params.get_link_topo.node_part_num;
55171d10453SEric Joyner 
55256429daeSEric Joyner 	return ICE_SUCCESS;
55356429daeSEric Joyner }
55456429daeSEric Joyner 
55556429daeSEric Joyner #define MAX_NETLIST_SIZE 10
55656429daeSEric Joyner /**
55756429daeSEric Joyner  * ice_find_netlist_node
55856429daeSEric Joyner  * @hw: pointer to the hw struct
55956429daeSEric Joyner  * @node_type_ctx: type of netlist node to look for
56056429daeSEric Joyner  * @node_part_number: node part number to look for
56156429daeSEric Joyner  * @node_handle: output parameter if node found - optional
56256429daeSEric Joyner  *
56356429daeSEric Joyner  * Find and return the node handle for a given node type and part number in the
56456429daeSEric Joyner  * netlist. When found ICE_SUCCESS is returned, ICE_ERR_DOES_NOT_EXIST
5658923de59SPiotr Kubaj  * otherwise. If node_handle provided, it would be set to found node handle.
56656429daeSEric Joyner  */
56756429daeSEric Joyner enum ice_status
56856429daeSEric Joyner ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number,
56956429daeSEric Joyner 		      u16 *node_handle)
57056429daeSEric Joyner {
57156429daeSEric Joyner 	struct ice_aqc_get_link_topo cmd;
57256429daeSEric Joyner 	u8 rec_node_part_number;
57356429daeSEric Joyner 	u16 rec_node_handle;
57456429daeSEric Joyner 	u8 idx;
57556429daeSEric Joyner 
57656429daeSEric Joyner 	for (idx = 0; idx < MAX_NETLIST_SIZE; idx++) {
5778923de59SPiotr Kubaj 		enum ice_status status;
5788923de59SPiotr Kubaj 
57956429daeSEric Joyner 		memset(&cmd, 0, sizeof(cmd));
58056429daeSEric Joyner 
58156429daeSEric Joyner 		cmd.addr.topo_params.node_type_ctx =
58256429daeSEric Joyner 			(node_type_ctx << ICE_AQC_LINK_TOPO_NODE_TYPE_S);
58356429daeSEric Joyner 		cmd.addr.topo_params.index = idx;
58456429daeSEric Joyner 
58556429daeSEric Joyner 		status = ice_aq_get_netlist_node(hw, &cmd,
58656429daeSEric Joyner 						 &rec_node_part_number,
58756429daeSEric Joyner 						 &rec_node_handle);
58856429daeSEric Joyner 		if (status)
58956429daeSEric Joyner 			return status;
59056429daeSEric Joyner 
59156429daeSEric Joyner 		if (rec_node_part_number == node_part_number) {
59256429daeSEric Joyner 			if (node_handle)
59356429daeSEric Joyner 				*node_handle = rec_node_handle;
59456429daeSEric Joyner 			return ICE_SUCCESS;
59556429daeSEric Joyner 		}
59656429daeSEric Joyner 	}
59756429daeSEric Joyner 
59856429daeSEric Joyner 	return ICE_ERR_DOES_NOT_EXIST;
59971d10453SEric Joyner }
60071d10453SEric Joyner 
6018923de59SPiotr Kubaj #define ice_get_link_status_datalen(hw)	ICE_GET_LINK_STATUS_DATALEN_V1
6028923de59SPiotr Kubaj 
60371d10453SEric Joyner /**
60471d10453SEric Joyner  * ice_aq_get_link_info
60571d10453SEric Joyner  * @pi: port information structure
60671d10453SEric Joyner  * @ena_lse: enable/disable LinkStatusEvent reporting
60771d10453SEric Joyner  * @link: pointer to link status structure - optional
60871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
60971d10453SEric Joyner  *
61071d10453SEric Joyner  * Get Link Status (0x607). Returns the link status of the adapter.
61171d10453SEric Joyner  */
61271d10453SEric Joyner enum ice_status
61371d10453SEric Joyner ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
61471d10453SEric Joyner 		     struct ice_link_status *link, struct ice_sq_cd *cd)
61571d10453SEric Joyner {
61671d10453SEric Joyner 	struct ice_aqc_get_link_status_data link_data = { 0 };
61771d10453SEric Joyner 	struct ice_aqc_get_link_status *resp;
61871d10453SEric Joyner 	struct ice_link_status *li_old, *li;
61971d10453SEric Joyner 	struct ice_fc_info *hw_fc_info;
62071d10453SEric Joyner 	bool tx_pause, rx_pause;
62171d10453SEric Joyner 	struct ice_aq_desc desc;
62271d10453SEric Joyner 	enum ice_status status;
62371d10453SEric Joyner 	struct ice_hw *hw;
62471d10453SEric Joyner 	u16 cmd_flags;
62571d10453SEric Joyner 
62671d10453SEric Joyner 	if (!pi)
62771d10453SEric Joyner 		return ICE_ERR_PARAM;
62871d10453SEric Joyner 	hw = pi->hw;
62971d10453SEric Joyner 
63071d10453SEric Joyner 	li_old = &pi->phy.link_info_old;
63171d10453SEric Joyner 	li = &pi->phy.link_info;
63271d10453SEric Joyner 	hw_fc_info = &pi->fc;
63371d10453SEric Joyner 
63471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
63571d10453SEric Joyner 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
63671d10453SEric Joyner 	resp = &desc.params.get_link_status;
63771d10453SEric Joyner 	resp->cmd_flags = CPU_TO_LE16(cmd_flags);
63871d10453SEric Joyner 	resp->lport_num = pi->lport;
63971d10453SEric Joyner 
6408923de59SPiotr Kubaj 	status = ice_aq_send_cmd(hw, &desc, &link_data,
6418923de59SPiotr Kubaj 				 ice_get_link_status_datalen(hw), cd);
64271d10453SEric Joyner 	if (status != ICE_SUCCESS)
64371d10453SEric Joyner 		return status;
64471d10453SEric Joyner 
64571d10453SEric Joyner 	/* save off old link status information */
64671d10453SEric Joyner 	*li_old = *li;
64771d10453SEric Joyner 
64871d10453SEric Joyner 	/* update current link status information */
64971d10453SEric Joyner 	li->link_speed = LE16_TO_CPU(link_data.link_speed);
65071d10453SEric Joyner 	li->phy_type_low = LE64_TO_CPU(link_data.phy_type_low);
65171d10453SEric Joyner 	li->phy_type_high = LE64_TO_CPU(link_data.phy_type_high);
65271d10453SEric Joyner 	li->link_info = link_data.link_info;
6539cf1841cSEric Joyner 	li->link_cfg_err = link_data.link_cfg_err;
65471d10453SEric Joyner 	li->an_info = link_data.an_info;
65571d10453SEric Joyner 	li->ext_info = link_data.ext_info;
65671d10453SEric Joyner 	li->max_frame_size = LE16_TO_CPU(link_data.max_frame_size);
65771d10453SEric Joyner 	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
65871d10453SEric Joyner 	li->topo_media_conflict = link_data.topo_media_conflict;
65971d10453SEric Joyner 	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
66071d10453SEric Joyner 				      ICE_AQ_CFG_PACING_TYPE_M);
66171d10453SEric Joyner 
66271d10453SEric Joyner 	/* update fc info */
66371d10453SEric Joyner 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
66471d10453SEric Joyner 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
66571d10453SEric Joyner 	if (tx_pause && rx_pause)
66671d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_FULL;
66771d10453SEric Joyner 	else if (tx_pause)
66871d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
66971d10453SEric Joyner 	else if (rx_pause)
67071d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
67171d10453SEric Joyner 	else
67271d10453SEric Joyner 		hw_fc_info->current_mode = ICE_FC_NONE;
67371d10453SEric Joyner 
67471d10453SEric Joyner 	li->lse_ena = !!(resp->cmd_flags & CPU_TO_LE16(ICE_AQ_LSE_IS_ENABLED));
67571d10453SEric Joyner 
6767d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "get link info\n");
67771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_speed = 0x%x\n", li->link_speed);
67871d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
67971d10453SEric Joyner 		  (unsigned long long)li->phy_type_low);
68071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
68171d10453SEric Joyner 		  (unsigned long long)li->phy_type_high);
68271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_info = 0x%x\n", li->link_info);
68356429daeSEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_cfg_err = 0x%x\n", li->link_cfg_err);
68471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	an_info = 0x%x\n", li->an_info);
68571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	ext_info = 0x%x\n", li->ext_info);
6867d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	fec_info = 0x%x\n", li->fec_info);
68771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	lse_ena = 0x%x\n", li->lse_ena);
6887d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	max_frame = 0x%x\n",
6897d7af7f8SEric Joyner 		  li->max_frame_size);
69071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	pacing = 0x%x\n", li->pacing);
69171d10453SEric Joyner 
69271d10453SEric Joyner 	/* save link status information */
69371d10453SEric Joyner 	if (link)
69471d10453SEric Joyner 		*link = *li;
69571d10453SEric Joyner 
69671d10453SEric Joyner 	/* flag cleared so calling functions don't call AQ again */
69771d10453SEric Joyner 	pi->phy.get_link_info = false;
69871d10453SEric Joyner 
69971d10453SEric Joyner 	return ICE_SUCCESS;
70071d10453SEric Joyner }
70171d10453SEric Joyner 
70271d10453SEric Joyner /**
7037d7af7f8SEric Joyner  * ice_fill_tx_timer_and_fc_thresh
70471d10453SEric Joyner  * @hw: pointer to the HW struct
7057d7af7f8SEric Joyner  * @cmd: pointer to MAC cfg structure
70671d10453SEric Joyner  *
7077d7af7f8SEric Joyner  * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
7087d7af7f8SEric Joyner  * descriptor
70971d10453SEric Joyner  */
7107d7af7f8SEric Joyner static void
7117d7af7f8SEric Joyner ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
7127d7af7f8SEric Joyner 				struct ice_aqc_set_mac_cfg *cmd)
71371d10453SEric Joyner {
7147d7af7f8SEric Joyner 	u16 fc_thres_val, tx_timer_val;
7157d7af7f8SEric Joyner 	u32 val;
71671d10453SEric Joyner 
71771d10453SEric Joyner 	/* We read back the transmit timer and fc threshold value of
71871d10453SEric Joyner 	 * LFC. Thus, we will use index =
71971d10453SEric Joyner 	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
72071d10453SEric Joyner 	 *
72156429daeSEric Joyner 	 * Also, because we are operating on transmit timer and fc
72271d10453SEric Joyner 	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
72371d10453SEric Joyner 	 */
72471d10453SEric Joyner #define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
72571d10453SEric Joyner 
72671d10453SEric Joyner 	/* Retrieve the transmit timer */
7277d7af7f8SEric Joyner 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
7287d7af7f8SEric Joyner 	tx_timer_val = val &
72971d10453SEric Joyner 		PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
73071d10453SEric Joyner 	cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
73171d10453SEric Joyner 
73271d10453SEric Joyner 	/* Retrieve the fc threshold */
7337d7af7f8SEric Joyner 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
7347d7af7f8SEric Joyner 	fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
7357d7af7f8SEric Joyner 
7367d7af7f8SEric Joyner 	cmd->fc_refresh_threshold = CPU_TO_LE16(fc_thres_val);
7377d7af7f8SEric Joyner }
7387d7af7f8SEric Joyner 
7397d7af7f8SEric Joyner /**
7407d7af7f8SEric Joyner  * ice_aq_set_mac_cfg
7417d7af7f8SEric Joyner  * @hw: pointer to the HW struct
7427d7af7f8SEric Joyner  * @max_frame_size: Maximum Frame Size to be supported
74356429daeSEric Joyner  * @auto_drop: Tell HW to drop packets if TC queue is blocked
7447d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
7457d7af7f8SEric Joyner  *
7467d7af7f8SEric Joyner  * Set MAC configuration (0x0603)
7477d7af7f8SEric Joyner  */
7487d7af7f8SEric Joyner enum ice_status
74956429daeSEric Joyner ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,
75056429daeSEric Joyner 		   struct ice_sq_cd *cd)
7517d7af7f8SEric Joyner {
7527d7af7f8SEric Joyner 	struct ice_aqc_set_mac_cfg *cmd;
7537d7af7f8SEric Joyner 	struct ice_aq_desc desc;
7547d7af7f8SEric Joyner 
7557d7af7f8SEric Joyner 	cmd = &desc.params.set_mac_cfg;
7567d7af7f8SEric Joyner 
7577d7af7f8SEric Joyner 	if (max_frame_size == 0)
7587d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
7597d7af7f8SEric Joyner 
7607d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
7617d7af7f8SEric Joyner 
7627d7af7f8SEric Joyner 	cmd->max_frame_size = CPU_TO_LE16(max_frame_size);
7637d7af7f8SEric Joyner 
76456429daeSEric Joyner 	if (ice_is_fw_auto_drop_supported(hw) && auto_drop)
76556429daeSEric Joyner 		cmd->drop_opts |= ICE_AQ_SET_MAC_AUTO_DROP_BLOCKING_PKTS;
7667d7af7f8SEric Joyner 	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
76771d10453SEric Joyner 
76871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
76971d10453SEric Joyner }
77071d10453SEric Joyner 
77171d10453SEric Joyner /**
77271d10453SEric Joyner  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
77371d10453SEric Joyner  * @hw: pointer to the HW struct
77471d10453SEric Joyner  */
77571d10453SEric Joyner static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
77671d10453SEric Joyner {
77771d10453SEric Joyner 	struct ice_switch_info *sw;
7787d7af7f8SEric Joyner 	enum ice_status status;
77971d10453SEric Joyner 
78071d10453SEric Joyner 	hw->switch_info = (struct ice_switch_info *)
78171d10453SEric Joyner 			  ice_malloc(hw, sizeof(*hw->switch_info));
78271d10453SEric Joyner 
78371d10453SEric Joyner 	sw = hw->switch_info;
78471d10453SEric Joyner 
78571d10453SEric Joyner 	if (!sw)
78671d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
78771d10453SEric Joyner 
78871d10453SEric Joyner 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
7897d7af7f8SEric Joyner 	sw->prof_res_bm_init = 0;
79071d10453SEric Joyner 
7917d7af7f8SEric Joyner 	status = ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
7927d7af7f8SEric Joyner 	if (status) {
7937d7af7f8SEric Joyner 		ice_free(hw, hw->switch_info);
7947d7af7f8SEric Joyner 		return status;
7957d7af7f8SEric Joyner 	}
7967d7af7f8SEric Joyner 	return ICE_SUCCESS;
79771d10453SEric Joyner }
79871d10453SEric Joyner 
79971d10453SEric Joyner /**
8007d7af7f8SEric Joyner  * ice_cleanup_fltr_mgmt_single - clears single filter mngt struct
80171d10453SEric Joyner  * @hw: pointer to the HW struct
8027d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function clears filters
80371d10453SEric Joyner  */
8047d7af7f8SEric Joyner static void
8057d7af7f8SEric Joyner ice_cleanup_fltr_mgmt_single(struct ice_hw *hw, struct ice_switch_info *sw)
80671d10453SEric Joyner {
80771d10453SEric Joyner 	struct ice_vsi_list_map_info *v_pos_map;
80871d10453SEric Joyner 	struct ice_vsi_list_map_info *v_tmp_map;
80971d10453SEric Joyner 	struct ice_sw_recipe *recps;
81071d10453SEric Joyner 	u8 i;
81171d10453SEric Joyner 
8127d7af7f8SEric Joyner 	if (!sw)
8137d7af7f8SEric Joyner 		return;
8147d7af7f8SEric Joyner 
81571d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
81671d10453SEric Joyner 				 ice_vsi_list_map_info, list_entry) {
81771d10453SEric Joyner 		LIST_DEL(&v_pos_map->list_entry);
81871d10453SEric Joyner 		ice_free(hw, v_pos_map);
81971d10453SEric Joyner 	}
8207d7af7f8SEric Joyner 	recps = sw->recp_list;
82171d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
82271d10453SEric Joyner 		struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
82371d10453SEric Joyner 
82471d10453SEric Joyner 		recps[i].root_rid = i;
82571d10453SEric Joyner 		LIST_FOR_EACH_ENTRY_SAFE(rg_entry, tmprg_entry,
82671d10453SEric Joyner 					 &recps[i].rg_list, ice_recp_grp_entry,
82771d10453SEric Joyner 					 l_entry) {
82871d10453SEric Joyner 			LIST_DEL(&rg_entry->l_entry);
82971d10453SEric Joyner 			ice_free(hw, rg_entry);
83071d10453SEric Joyner 		}
83171d10453SEric Joyner 
83271d10453SEric Joyner 		if (recps[i].adv_rule) {
83371d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
83471d10453SEric Joyner 			struct ice_adv_fltr_mgmt_list_entry *lst_itr;
83571d10453SEric Joyner 
83671d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
83771d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
83871d10453SEric Joyner 						 &recps[i].filt_rules,
83971d10453SEric Joyner 						 ice_adv_fltr_mgmt_list_entry,
84071d10453SEric Joyner 						 list_entry) {
84171d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
84271d10453SEric Joyner 				ice_free(hw, lst_itr->lkups);
84371d10453SEric Joyner 				ice_free(hw, lst_itr);
84471d10453SEric Joyner 			}
84571d10453SEric Joyner 		} else {
84671d10453SEric Joyner 			struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
84771d10453SEric Joyner 
84871d10453SEric Joyner 			ice_destroy_lock(&recps[i].filt_rule_lock);
84971d10453SEric Joyner 			LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry,
85071d10453SEric Joyner 						 &recps[i].filt_rules,
85171d10453SEric Joyner 						 ice_fltr_mgmt_list_entry,
85271d10453SEric Joyner 						 list_entry) {
85371d10453SEric Joyner 				LIST_DEL(&lst_itr->list_entry);
85471d10453SEric Joyner 				ice_free(hw, lst_itr);
85571d10453SEric Joyner 			}
85671d10453SEric Joyner 		}
85771d10453SEric Joyner 		if (recps[i].root_buf)
85871d10453SEric Joyner 			ice_free(hw, recps[i].root_buf);
85971d10453SEric Joyner 	}
8607d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
86171d10453SEric Joyner 	ice_free(hw, sw->recp_list);
86271d10453SEric Joyner 	ice_free(hw, sw);
86371d10453SEric Joyner }
86471d10453SEric Joyner 
86571d10453SEric Joyner /**
86656429daeSEric Joyner  * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
8677d7af7f8SEric Joyner  * @hw: pointer to the HW struct
8687d7af7f8SEric Joyner  */
8697d7af7f8SEric Joyner static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
8707d7af7f8SEric Joyner {
8717d7af7f8SEric Joyner 	ice_cleanup_fltr_mgmt_single(hw, hw->switch_info);
8727d7af7f8SEric Joyner }
8737d7af7f8SEric Joyner 
8747d7af7f8SEric Joyner /**
87571d10453SEric Joyner  * ice_get_itr_intrl_gran
87671d10453SEric Joyner  * @hw: pointer to the HW struct
87771d10453SEric Joyner  *
87871d10453SEric Joyner  * Determines the ITR/INTRL granularities based on the maximum aggregate
87971d10453SEric Joyner  * bandwidth according to the device's configuration during power-on.
88071d10453SEric Joyner  */
88171d10453SEric Joyner static void ice_get_itr_intrl_gran(struct ice_hw *hw)
88271d10453SEric Joyner {
88371d10453SEric Joyner 	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
88471d10453SEric Joyner 			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
88571d10453SEric Joyner 			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
88671d10453SEric Joyner 
88771d10453SEric Joyner 	switch (max_agg_bw) {
88871d10453SEric Joyner 	case ICE_MAX_AGG_BW_200G:
88971d10453SEric Joyner 	case ICE_MAX_AGG_BW_100G:
89071d10453SEric Joyner 	case ICE_MAX_AGG_BW_50G:
89171d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
89271d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
89371d10453SEric Joyner 		break;
89471d10453SEric Joyner 	case ICE_MAX_AGG_BW_25G:
89571d10453SEric Joyner 		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
89671d10453SEric Joyner 		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
89771d10453SEric Joyner 		break;
89871d10453SEric Joyner 	}
89971d10453SEric Joyner }
90071d10453SEric Joyner 
90171d10453SEric Joyner /**
90271d10453SEric Joyner  * ice_print_rollback_msg - print FW rollback message
90371d10453SEric Joyner  * @hw: pointer to the hardware structure
90471d10453SEric Joyner  */
90571d10453SEric Joyner void ice_print_rollback_msg(struct ice_hw *hw)
90671d10453SEric Joyner {
90771d10453SEric Joyner 	char nvm_str[ICE_NVM_VER_LEN] = { 0 };
90871d10453SEric Joyner 	struct ice_orom_info *orom;
909d08b8680SEric Joyner 	struct ice_nvm_info *nvm;
91071d10453SEric Joyner 
911d08b8680SEric Joyner 	orom = &hw->flash.orom;
912d08b8680SEric Joyner 	nvm = &hw->flash.nvm;
91371d10453SEric Joyner 
91471d10453SEric Joyner 	SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d",
915d08b8680SEric Joyner 		 nvm->major, nvm->minor, nvm->eetrack, orom->major,
91671d10453SEric Joyner 		 orom->build, orom->patch);
91771d10453SEric Joyner 	ice_warn(hw,
91871d10453SEric 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",
91971d10453SEric Joyner 		 nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
92071d10453SEric Joyner }
92171d10453SEric Joyner 
92271d10453SEric Joyner /**
92356429daeSEric Joyner  * ice_set_umac_shared
92456429daeSEric Joyner  * @hw: pointer to the hw struct
92556429daeSEric Joyner  *
92656429daeSEric Joyner  * Set boolean flag to allow unicast MAC sharing
92756429daeSEric Joyner  */
92856429daeSEric Joyner void ice_set_umac_shared(struct ice_hw *hw)
92956429daeSEric Joyner {
93056429daeSEric Joyner 	hw->umac_shared = true;
93156429daeSEric Joyner }
93256429daeSEric Joyner 
93356429daeSEric Joyner /**
93471d10453SEric Joyner  * ice_init_hw - main hardware initialization routine
93571d10453SEric Joyner  * @hw: pointer to the hardware structure
93671d10453SEric Joyner  */
93771d10453SEric Joyner enum ice_status ice_init_hw(struct ice_hw *hw)
93871d10453SEric Joyner {
93971d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
94071d10453SEric Joyner 	enum ice_status status;
94171d10453SEric Joyner 	u16 mac_buf_len;
94271d10453SEric Joyner 	void *mac_buf;
94371d10453SEric Joyner 
94471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
94571d10453SEric Joyner 
94671d10453SEric Joyner 	/* Set MAC type based on DeviceID */
94771d10453SEric Joyner 	status = ice_set_mac_type(hw);
94871d10453SEric Joyner 	if (status)
94971d10453SEric Joyner 		return status;
95071d10453SEric Joyner 
95171d10453SEric Joyner 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
95271d10453SEric Joyner 			 PF_FUNC_RID_FUNCTION_NUMBER_M) >>
95371d10453SEric Joyner 		PF_FUNC_RID_FUNCTION_NUMBER_S;
95471d10453SEric Joyner 
95571d10453SEric Joyner 	status = ice_reset(hw, ICE_RESET_PFR);
95671d10453SEric Joyner 	if (status)
95771d10453SEric Joyner 		return status;
95871d10453SEric Joyner 	ice_get_itr_intrl_gran(hw);
95971d10453SEric Joyner 
96071d10453SEric Joyner 	status = ice_create_all_ctrlq(hw);
96171d10453SEric Joyner 	if (status)
96271d10453SEric Joyner 		goto err_unroll_cqinit;
96371d10453SEric Joyner 
96456429daeSEric Joyner 	ice_fwlog_set_support_ena(hw);
96556429daeSEric Joyner 	status = ice_fwlog_set(hw, &hw->fwlog_cfg);
96656429daeSEric Joyner 	if (status) {
96756429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging, status %d.\n",
96856429daeSEric Joyner 			  status);
96956429daeSEric Joyner 	} else {
97056429daeSEric Joyner 		if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_REGISTER_ON_INIT) {
97156429daeSEric Joyner 			status = ice_fwlog_register(hw);
97256429daeSEric Joyner 			if (status)
97356429daeSEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "Failed to register for FW logging events, status %d.\n",
97456429daeSEric Joyner 					  status);
97556429daeSEric Joyner 		} else {
97656429daeSEric Joyner 			status = ice_fwlog_unregister(hw);
97756429daeSEric Joyner 			if (status)
97856429daeSEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "Failed to unregister for FW logging events, status %d.\n",
97956429daeSEric Joyner 					  status);
98056429daeSEric Joyner 		}
98156429daeSEric Joyner 	}
98256429daeSEric Joyner 
98371d10453SEric Joyner 	status = ice_init_nvm(hw);
98471d10453SEric Joyner 	if (status)
98571d10453SEric Joyner 		goto err_unroll_cqinit;
98671d10453SEric Joyner 
98771d10453SEric Joyner 	if (ice_get_fw_mode(hw) == ICE_FW_MODE_ROLLBACK)
98871d10453SEric Joyner 		ice_print_rollback_msg(hw);
98971d10453SEric Joyner 
99071d10453SEric Joyner 	status = ice_clear_pf_cfg(hw);
99171d10453SEric Joyner 	if (status)
99271d10453SEric Joyner 		goto err_unroll_cqinit;
99371d10453SEric Joyner 
99471d10453SEric Joyner 	ice_clear_pxe_mode(hw);
99571d10453SEric Joyner 
99671d10453SEric Joyner 	status = ice_get_caps(hw);
99771d10453SEric Joyner 	if (status)
99871d10453SEric Joyner 		goto err_unroll_cqinit;
99971d10453SEric Joyner 
10009c30461dSEric Joyner 	if (!hw->port_info)
100171d10453SEric Joyner 		hw->port_info = (struct ice_port_info *)
100271d10453SEric Joyner 			ice_malloc(hw, sizeof(*hw->port_info));
100371d10453SEric Joyner 	if (!hw->port_info) {
100471d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
100571d10453SEric Joyner 		goto err_unroll_cqinit;
100671d10453SEric Joyner 	}
100771d10453SEric Joyner 
100871d10453SEric Joyner 	/* set the back pointer to HW */
100971d10453SEric Joyner 	hw->port_info->hw = hw;
101071d10453SEric Joyner 
101171d10453SEric Joyner 	/* Initialize port_info struct with switch configuration data */
101271d10453SEric Joyner 	status = ice_get_initial_sw_cfg(hw);
101371d10453SEric Joyner 	if (status)
101471d10453SEric Joyner 		goto err_unroll_alloc;
101571d10453SEric Joyner 
101671d10453SEric Joyner 	hw->evb_veb = true;
101771d10453SEric Joyner 	/* Query the allocated resources for Tx scheduler */
101871d10453SEric Joyner 	status = ice_sched_query_res_alloc(hw);
101971d10453SEric Joyner 	if (status) {
10207d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
102171d10453SEric Joyner 		goto err_unroll_alloc;
102271d10453SEric Joyner 	}
102371d10453SEric Joyner 	ice_sched_get_psm_clk_freq(hw);
102471d10453SEric Joyner 
102571d10453SEric Joyner 	/* Initialize port_info struct with scheduler data */
102671d10453SEric Joyner 	status = ice_sched_init_port(hw->port_info);
102771d10453SEric Joyner 	if (status)
102871d10453SEric Joyner 		goto err_unroll_sched;
102971d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
103071d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
103171d10453SEric Joyner 	if (!pcaps) {
103271d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
103371d10453SEric Joyner 		goto err_unroll_sched;
103471d10453SEric Joyner 	}
103571d10453SEric Joyner 
103671d10453SEric Joyner 	/* Initialize port_info struct with PHY capabilities */
103771d10453SEric Joyner 	status = ice_aq_get_phy_caps(hw->port_info, false,
10389cf1841cSEric Joyner 				     ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, NULL);
103971d10453SEric Joyner 	ice_free(hw, pcaps);
104071d10453SEric Joyner 	if (status)
10419cf1841cSEric Joyner 		ice_warn(hw, "Get PHY capabilities failed status = %d, continuing anyway\n",
10429cf1841cSEric Joyner 			 status);
104371d10453SEric Joyner 
104471d10453SEric Joyner 	/* Initialize port_info struct with link information */
104571d10453SEric Joyner 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
104671d10453SEric Joyner 	if (status)
104771d10453SEric Joyner 		goto err_unroll_sched;
104871d10453SEric Joyner 	/* need a valid SW entry point to build a Tx tree */
104971d10453SEric Joyner 	if (!hw->sw_entry_point_layer) {
105071d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
105171d10453SEric Joyner 		status = ICE_ERR_CFG;
105271d10453SEric Joyner 		goto err_unroll_sched;
105371d10453SEric Joyner 	}
105471d10453SEric Joyner 	INIT_LIST_HEAD(&hw->agg_list);
105571d10453SEric Joyner 	/* Initialize max burst size */
105671d10453SEric Joyner 	if (!hw->max_burst_size)
105771d10453SEric Joyner 		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
105871d10453SEric Joyner 	status = ice_init_fltr_mgmt_struct(hw);
105971d10453SEric Joyner 	if (status)
106071d10453SEric Joyner 		goto err_unroll_sched;
106171d10453SEric Joyner 
106271d10453SEric Joyner 	/* Get MAC information */
106356429daeSEric Joyner 
106471d10453SEric Joyner 	/* A single port can report up to two (LAN and WoL) addresses */
106571d10453SEric Joyner 	mac_buf = ice_calloc(hw, 2,
106671d10453SEric Joyner 			     sizeof(struct ice_aqc_manage_mac_read_resp));
106771d10453SEric Joyner 	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
106871d10453SEric Joyner 
106971d10453SEric Joyner 	if (!mac_buf) {
107071d10453SEric Joyner 		status = ICE_ERR_NO_MEMORY;
107171d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
107271d10453SEric Joyner 	}
107371d10453SEric Joyner 
107471d10453SEric Joyner 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
107571d10453SEric Joyner 	ice_free(hw, mac_buf);
107671d10453SEric Joyner 
107771d10453SEric Joyner 	if (status)
107871d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
107956429daeSEric Joyner 
10807d7af7f8SEric Joyner 	/* enable jumbo frame support at MAC level */
108156429daeSEric Joyner 	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, false,
108256429daeSEric Joyner 				    NULL);
10837d7af7f8SEric Joyner 	if (status)
10847d7af7f8SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
108556429daeSEric Joyner 
108671d10453SEric Joyner 	status = ice_init_hw_tbls(hw);
108771d10453SEric Joyner 	if (status)
108871d10453SEric Joyner 		goto err_unroll_fltr_mgmt_struct;
108971d10453SEric Joyner 	ice_init_lock(&hw->tnl_lock);
1090d08b8680SEric Joyner 
109171d10453SEric Joyner 	return ICE_SUCCESS;
109271d10453SEric Joyner 
109371d10453SEric Joyner err_unroll_fltr_mgmt_struct:
109471d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
109571d10453SEric Joyner err_unroll_sched:
109671d10453SEric Joyner 	ice_sched_cleanup_all(hw);
109771d10453SEric Joyner err_unroll_alloc:
109871d10453SEric Joyner 	ice_free(hw, hw->port_info);
109971d10453SEric Joyner 	hw->port_info = NULL;
110071d10453SEric Joyner err_unroll_cqinit:
110171d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
110271d10453SEric Joyner 	return status;
110371d10453SEric Joyner }
110471d10453SEric Joyner 
110571d10453SEric Joyner /**
110671d10453SEric Joyner  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
110771d10453SEric Joyner  * @hw: pointer to the hardware structure
110871d10453SEric Joyner  *
110971d10453SEric Joyner  * This should be called only during nominal operation, not as a result of
111071d10453SEric Joyner  * ice_init_hw() failing since ice_init_hw() will take care of unrolling
111171d10453SEric Joyner  * applicable initializations if it fails for any reason.
111271d10453SEric Joyner  */
111371d10453SEric Joyner void ice_deinit_hw(struct ice_hw *hw)
111471d10453SEric Joyner {
111571d10453SEric Joyner 	ice_cleanup_fltr_mgmt_struct(hw);
111671d10453SEric Joyner 
111771d10453SEric Joyner 	ice_sched_cleanup_all(hw);
111871d10453SEric Joyner 	ice_sched_clear_agg(hw);
111971d10453SEric Joyner 	ice_free_seg(hw);
112071d10453SEric Joyner 	ice_free_hw_tbls(hw);
112171d10453SEric Joyner 	ice_destroy_lock(&hw->tnl_lock);
112271d10453SEric Joyner 
112371d10453SEric Joyner 	if (hw->port_info) {
112471d10453SEric Joyner 		ice_free(hw, hw->port_info);
112571d10453SEric Joyner 		hw->port_info = NULL;
112671d10453SEric Joyner 	}
112771d10453SEric Joyner 
112871d10453SEric Joyner 	ice_destroy_all_ctrlq(hw);
112971d10453SEric Joyner 
113071d10453SEric Joyner 	/* Clear VSI contexts if not already cleared */
113171d10453SEric Joyner 	ice_clear_all_vsi_ctx(hw);
113271d10453SEric Joyner }
113371d10453SEric Joyner 
113471d10453SEric Joyner /**
113571d10453SEric Joyner  * ice_check_reset - Check to see if a global reset is complete
113671d10453SEric Joyner  * @hw: pointer to the hardware structure
113771d10453SEric Joyner  */
113871d10453SEric Joyner enum ice_status ice_check_reset(struct ice_hw *hw)
113971d10453SEric Joyner {
11409c30461dSEric Joyner 	u32 cnt, reg = 0, grst_timeout, uld_mask, reset_wait_cnt;
114171d10453SEric Joyner 
114271d10453SEric Joyner 	/* Poll for Device Active state in case a recent CORER, GLOBR,
114371d10453SEric Joyner 	 * or EMPR has occurred. The grst delay value is in 100ms units.
114471d10453SEric Joyner 	 * Add 1sec for outstanding AQ commands that can take a long time.
114571d10453SEric Joyner 	 */
11467d7af7f8SEric Joyner 	grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
114771d10453SEric Joyner 			GLGEN_RSTCTL_GRSTDEL_S) + 10;
114871d10453SEric Joyner 
11497d7af7f8SEric Joyner 	for (cnt = 0; cnt < grst_timeout; cnt++) {
115071d10453SEric Joyner 		ice_msec_delay(100, true);
115171d10453SEric Joyner 		reg = rd32(hw, GLGEN_RSTAT);
115271d10453SEric Joyner 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
115371d10453SEric Joyner 			break;
115471d10453SEric Joyner 	}
115571d10453SEric Joyner 
11567d7af7f8SEric Joyner 	if (cnt == grst_timeout) {
11577d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n");
115871d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
115971d10453SEric Joyner 	}
116071d10453SEric Joyner 
116171d10453SEric Joyner #define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
116271d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_1_M |\
116371d10453SEric Joyner 				 GLNVM_ULD_CORER_DONE_M |\
116471d10453SEric Joyner 				 GLNVM_ULD_GLOBR_DONE_M |\
116571d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_M |\
116671d10453SEric Joyner 				 GLNVM_ULD_POR_DONE_1_M |\
116771d10453SEric Joyner 				 GLNVM_ULD_PCIER_DONE_2_M)
116871d10453SEric Joyner 
11698a13362dSEric Joyner 	uld_mask = ICE_RESET_DONE_MASK | (hw->func_caps.common_cap.iwarp ?
11708a13362dSEric Joyner 					  GLNVM_ULD_PE_DONE_M : 0);
117171d10453SEric Joyner 
11729c30461dSEric Joyner 	reset_wait_cnt = ICE_PF_RESET_WAIT_COUNT;
11739c30461dSEric Joyner 
117471d10453SEric Joyner 	/* Device is Active; check Global Reset processes are done */
11759c30461dSEric Joyner 	for (cnt = 0; cnt < reset_wait_cnt; cnt++) {
117671d10453SEric Joyner 		reg = rd32(hw, GLNVM_ULD) & uld_mask;
117771d10453SEric Joyner 		if (reg == uld_mask) {
11787d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt);
117971d10453SEric Joyner 			break;
118071d10453SEric Joyner 		}
118171d10453SEric Joyner 		ice_msec_delay(10, true);
118271d10453SEric Joyner 	}
118371d10453SEric Joyner 
11849c30461dSEric Joyner 	if (cnt == reset_wait_cnt) {
11857d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
118671d10453SEric Joyner 			  reg);
118771d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
118871d10453SEric Joyner 	}
118971d10453SEric Joyner 
119071d10453SEric Joyner 	return ICE_SUCCESS;
119171d10453SEric Joyner }
119271d10453SEric Joyner 
119371d10453SEric Joyner /**
119471d10453SEric Joyner  * ice_pf_reset - Reset the PF
119571d10453SEric Joyner  * @hw: pointer to the hardware structure
119671d10453SEric Joyner  *
119771d10453SEric Joyner  * If a global reset has been triggered, this function checks
119871d10453SEric Joyner  * for its completion and then issues the PF reset
119971d10453SEric Joyner  */
120071d10453SEric Joyner static enum ice_status ice_pf_reset(struct ice_hw *hw)
120171d10453SEric Joyner {
12029c30461dSEric Joyner 	u32 cnt, reg, reset_wait_cnt, cfg_lock_timeout;
120371d10453SEric Joyner 
120471d10453SEric Joyner 	/* If at function entry a global reset was already in progress, i.e.
120571d10453SEric Joyner 	 * state is not 'device active' or any of the reset done bits are not
120671d10453SEric Joyner 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
120771d10453SEric Joyner 	 * global reset is done.
120871d10453SEric Joyner 	 */
120971d10453SEric Joyner 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
121071d10453SEric Joyner 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
121171d10453SEric Joyner 		/* poll on global reset currently in progress until done */
121271d10453SEric Joyner 		if (ice_check_reset(hw))
121371d10453SEric Joyner 			return ICE_ERR_RESET_FAILED;
121471d10453SEric Joyner 
121571d10453SEric Joyner 		return ICE_SUCCESS;
121671d10453SEric Joyner 	}
121771d10453SEric Joyner 
121871d10453SEric Joyner 	/* Reset the PF */
121971d10453SEric Joyner 	reg = rd32(hw, PFGEN_CTRL);
122071d10453SEric Joyner 
122171d10453SEric Joyner 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
122271d10453SEric Joyner 
12237d7af7f8SEric Joyner 	/* Wait for the PFR to complete. The wait time is the global config lock
12247d7af7f8SEric Joyner 	 * timeout plus the PFR timeout which will account for a possible reset
12257d7af7f8SEric Joyner 	 * that is occurring during a download package operation.
12267d7af7f8SEric Joyner 	 */
12279c30461dSEric Joyner 	reset_wait_cnt = ICE_PF_RESET_WAIT_COUNT;
12289c30461dSEric Joyner 	cfg_lock_timeout = ICE_GLOBAL_CFG_LOCK_TIMEOUT;
12299c30461dSEric Joyner 
12309c30461dSEric Joyner 	for (cnt = 0; cnt < cfg_lock_timeout + reset_wait_cnt; cnt++) {
123171d10453SEric Joyner 		reg = rd32(hw, PFGEN_CTRL);
123271d10453SEric Joyner 		if (!(reg & PFGEN_CTRL_PFSWR_M))
123371d10453SEric Joyner 			break;
123471d10453SEric Joyner 
123571d10453SEric Joyner 		ice_msec_delay(1, true);
123671d10453SEric Joyner 	}
123771d10453SEric Joyner 
12389c30461dSEric Joyner 	if (cnt == cfg_lock_timeout + reset_wait_cnt) {
12397d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n");
124071d10453SEric Joyner 		return ICE_ERR_RESET_FAILED;
124171d10453SEric Joyner 	}
124271d10453SEric Joyner 
124371d10453SEric Joyner 	return ICE_SUCCESS;
124471d10453SEric Joyner }
124571d10453SEric Joyner 
124671d10453SEric Joyner /**
124771d10453SEric Joyner  * ice_reset - Perform different types of reset
124871d10453SEric Joyner  * @hw: pointer to the hardware structure
124971d10453SEric Joyner  * @req: reset request
125071d10453SEric Joyner  *
125171d10453SEric Joyner  * This function triggers a reset as specified by the req parameter.
125271d10453SEric Joyner  *
125371d10453SEric Joyner  * Note:
125471d10453SEric Joyner  * If anything other than a PF reset is triggered, PXE mode is restored.
125571d10453SEric Joyner  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
125671d10453SEric Joyner  * interface has been restored in the rebuild flow.
125771d10453SEric Joyner  */
125871d10453SEric Joyner enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
125971d10453SEric Joyner {
126071d10453SEric Joyner 	u32 val = 0;
126171d10453SEric Joyner 
126271d10453SEric Joyner 	switch (req) {
126371d10453SEric Joyner 	case ICE_RESET_PFR:
126471d10453SEric Joyner 		return ice_pf_reset(hw);
126571d10453SEric Joyner 	case ICE_RESET_CORER:
126671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
126771d10453SEric Joyner 		val = GLGEN_RTRIG_CORER_M;
126871d10453SEric Joyner 		break;
126971d10453SEric Joyner 	case ICE_RESET_GLOBR:
127071d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
127171d10453SEric Joyner 		val = GLGEN_RTRIG_GLOBR_M;
127271d10453SEric Joyner 		break;
127371d10453SEric Joyner 	default:
127471d10453SEric Joyner 		return ICE_ERR_PARAM;
127571d10453SEric Joyner 	}
127671d10453SEric Joyner 
127771d10453SEric Joyner 	val |= rd32(hw, GLGEN_RTRIG);
127871d10453SEric Joyner 	wr32(hw, GLGEN_RTRIG, val);
127971d10453SEric Joyner 	ice_flush(hw);
128071d10453SEric Joyner 
128171d10453SEric Joyner 	/* wait for the FW to be ready */
128271d10453SEric Joyner 	return ice_check_reset(hw);
128371d10453SEric Joyner }
128471d10453SEric Joyner 
128571d10453SEric Joyner /**
128671d10453SEric Joyner  * ice_copy_rxq_ctx_to_hw
128771d10453SEric Joyner  * @hw: pointer to the hardware structure
128871d10453SEric Joyner  * @ice_rxq_ctx: pointer to the rxq context
128971d10453SEric Joyner  * @rxq_index: the index of the Rx queue
129071d10453SEric Joyner  *
129171d10453SEric Joyner  * Copies rxq context from dense structure to HW register space
129271d10453SEric Joyner  */
129371d10453SEric Joyner static enum ice_status
129471d10453SEric Joyner ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
129571d10453SEric Joyner {
129671d10453SEric Joyner 	u8 i;
129771d10453SEric Joyner 
129871d10453SEric Joyner 	if (!ice_rxq_ctx)
129971d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
130071d10453SEric Joyner 
130171d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
130271d10453SEric Joyner 		return ICE_ERR_PARAM;
130371d10453SEric Joyner 
130471d10453SEric Joyner 	/* Copy each dword separately to HW */
130571d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
130671d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index),
130771d10453SEric Joyner 		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
130871d10453SEric Joyner 
130971d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
131071d10453SEric Joyner 			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
131171d10453SEric Joyner 	}
131271d10453SEric Joyner 
131371d10453SEric Joyner 	return ICE_SUCCESS;
131471d10453SEric Joyner }
131571d10453SEric Joyner 
13169dc2f6e2SEric Joyner /**
13179dc2f6e2SEric Joyner  * ice_copy_rxq_ctx_from_hw - Copy rxq context register from HW
13189dc2f6e2SEric Joyner  * @hw: pointer to the hardware structure
13199dc2f6e2SEric Joyner  * @ice_rxq_ctx: pointer to the rxq context
13209dc2f6e2SEric Joyner  * @rxq_index: the index of the Rx queue
13219dc2f6e2SEric Joyner  *
13229dc2f6e2SEric Joyner  * Copies rxq context from HW register space to dense structure
13239dc2f6e2SEric Joyner  */
13249dc2f6e2SEric Joyner static enum ice_status
13259dc2f6e2SEric Joyner ice_copy_rxq_ctx_from_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
13269dc2f6e2SEric Joyner {
13279dc2f6e2SEric Joyner 	u8 i;
13289dc2f6e2SEric Joyner 
13299dc2f6e2SEric Joyner 	if (!ice_rxq_ctx)
13309dc2f6e2SEric Joyner 		return ICE_ERR_BAD_PTR;
13319dc2f6e2SEric Joyner 
13329dc2f6e2SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
13339dc2f6e2SEric Joyner 		return ICE_ERR_PARAM;
13349dc2f6e2SEric Joyner 
13359dc2f6e2SEric Joyner 	/* Copy each dword separately from HW */
13369dc2f6e2SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
13379dc2f6e2SEric Joyner 		u32 *ctx = (u32 *)(ice_rxq_ctx + (i * sizeof(u32)));
13389dc2f6e2SEric Joyner 
13399dc2f6e2SEric Joyner 		*ctx = rd32(hw, QRX_CONTEXT(i, rxq_index));
13409dc2f6e2SEric Joyner 
13419dc2f6e2SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, *ctx);
13429dc2f6e2SEric Joyner 	}
13439dc2f6e2SEric Joyner 
13449dc2f6e2SEric Joyner 	return ICE_SUCCESS;
13459dc2f6e2SEric Joyner }
13469dc2f6e2SEric Joyner 
134771d10453SEric Joyner /* LAN Rx Queue Context */
134871d10453SEric Joyner static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
134971d10453SEric Joyner 	/* Field		Width	LSB */
135071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
135171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
135271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
135371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
135471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
135571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
135671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
135771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
135871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
135971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
136071d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
136171d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
136271d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
136371d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
136471d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
136571d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
136671d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
136771d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
136871d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
136971d10453SEric Joyner 	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
137071d10453SEric Joyner 	{ 0 }
137171d10453SEric Joyner };
137271d10453SEric Joyner 
137371d10453SEric Joyner /**
137471d10453SEric Joyner  * ice_write_rxq_ctx
137571d10453SEric Joyner  * @hw: pointer to the hardware structure
137671d10453SEric Joyner  * @rlan_ctx: pointer to the rxq context
137771d10453SEric Joyner  * @rxq_index: the index of the Rx queue
137871d10453SEric Joyner  *
137971d10453SEric Joyner  * Converts rxq context from sparse to dense structure and then writes
138071d10453SEric Joyner  * it to HW register space and enables the hardware to prefetch descriptors
138171d10453SEric Joyner  * instead of only fetching them on demand
138271d10453SEric Joyner  */
138371d10453SEric Joyner enum ice_status
138471d10453SEric Joyner ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
138571d10453SEric Joyner 		  u32 rxq_index)
138671d10453SEric Joyner {
138771d10453SEric Joyner 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
138871d10453SEric Joyner 
138971d10453SEric Joyner 	if (!rlan_ctx)
139071d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
139171d10453SEric Joyner 
139271d10453SEric Joyner 	rlan_ctx->prefena = 1;
139371d10453SEric Joyner 
13947d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
139571d10453SEric Joyner 	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
139671d10453SEric Joyner }
139771d10453SEric Joyner 
139871d10453SEric Joyner /**
13999dc2f6e2SEric Joyner  * ice_read_rxq_ctx - Read rxq context from HW
14009dc2f6e2SEric Joyner  * @hw: pointer to the hardware structure
14019dc2f6e2SEric Joyner  * @rlan_ctx: pointer to the rxq context
14029dc2f6e2SEric Joyner  * @rxq_index: the index of the Rx queue
14039dc2f6e2SEric Joyner  *
14049dc2f6e2SEric Joyner  * Read rxq context from HW register space and then converts it from dense
14059dc2f6e2SEric Joyner  * structure to sparse
14069dc2f6e2SEric Joyner  */
14079dc2f6e2SEric Joyner enum ice_status
14089dc2f6e2SEric Joyner ice_read_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
14099dc2f6e2SEric Joyner 		 u32 rxq_index)
14109dc2f6e2SEric Joyner {
14119dc2f6e2SEric Joyner 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
14129dc2f6e2SEric Joyner 	enum ice_status status;
14139dc2f6e2SEric Joyner 
14149dc2f6e2SEric Joyner 	if (!rlan_ctx)
14159dc2f6e2SEric Joyner 		return ICE_ERR_BAD_PTR;
14169dc2f6e2SEric Joyner 
14179dc2f6e2SEric Joyner 	status = ice_copy_rxq_ctx_from_hw(hw, ctx_buf, rxq_index);
14189dc2f6e2SEric Joyner 	if (status)
14199dc2f6e2SEric Joyner 		return status;
14209dc2f6e2SEric Joyner 
14219dc2f6e2SEric Joyner 	return ice_get_ctx(ctx_buf, (u8 *)rlan_ctx, ice_rlan_ctx_info);
14229dc2f6e2SEric Joyner }
14239dc2f6e2SEric Joyner 
14249dc2f6e2SEric Joyner /**
142571d10453SEric Joyner  * ice_clear_rxq_ctx
142671d10453SEric Joyner  * @hw: pointer to the hardware structure
142771d10453SEric Joyner  * @rxq_index: the index of the Rx queue to clear
142871d10453SEric Joyner  *
142971d10453SEric Joyner  * Clears rxq context in HW register space
143071d10453SEric Joyner  */
143171d10453SEric Joyner enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index)
143271d10453SEric Joyner {
143371d10453SEric Joyner 	u8 i;
143471d10453SEric Joyner 
143571d10453SEric Joyner 	if (rxq_index > QRX_CTRL_MAX_INDEX)
143671d10453SEric Joyner 		return ICE_ERR_PARAM;
143771d10453SEric Joyner 
143871d10453SEric Joyner 	/* Clear each dword register separately */
143971d10453SEric Joyner 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++)
144071d10453SEric Joyner 		wr32(hw, QRX_CONTEXT(i, rxq_index), 0);
144171d10453SEric Joyner 
144271d10453SEric Joyner 	return ICE_SUCCESS;
144371d10453SEric Joyner }
144471d10453SEric Joyner 
14459dc2f6e2SEric Joyner /* LAN Tx Queue Context used for set Tx config by ice_aqc_opc_add_txqs,
14469dc2f6e2SEric Joyner  * Bit[0-175] is valid
14479dc2f6e2SEric Joyner  */
144871d10453SEric Joyner const struct ice_ctx_ele ice_tlan_ctx_info[] = {
144971d10453SEric Joyner 				    /* Field			Width	LSB */
145071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
145171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
145271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
145371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
145471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
145571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
145671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
145771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
145871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
145971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
146071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
146171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
146271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
146371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
146471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
146571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
146671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
146771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
146871d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
146971d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
147071d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
147171d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
147271d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
147371d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
147471d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
147571d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
147671d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
147771d10453SEric Joyner 	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
147871d10453SEric Joyner 	{ 0 }
147971d10453SEric Joyner };
148071d10453SEric Joyner 
148171d10453SEric Joyner /**
148271d10453SEric Joyner  * ice_copy_tx_cmpltnq_ctx_to_hw
148371d10453SEric Joyner  * @hw: pointer to the hardware structure
148471d10453SEric Joyner  * @ice_tx_cmpltnq_ctx: pointer to the Tx completion queue context
148571d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
148671d10453SEric Joyner  *
148771d10453SEric Joyner  * Copies Tx completion queue context from dense structure to HW register space
148871d10453SEric Joyner  */
148971d10453SEric Joyner static enum ice_status
149071d10453SEric Joyner ice_copy_tx_cmpltnq_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_cmpltnq_ctx,
149171d10453SEric Joyner 			      u32 tx_cmpltnq_index)
149271d10453SEric Joyner {
149371d10453SEric Joyner 	u8 i;
149471d10453SEric Joyner 
149571d10453SEric Joyner 	if (!ice_tx_cmpltnq_ctx)
149671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
149771d10453SEric Joyner 
149871d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
149971d10453SEric Joyner 		return ICE_ERR_PARAM;
150071d10453SEric Joyner 
150171d10453SEric Joyner 	/* Copy each dword separately to HW */
150271d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++) {
150371d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index),
150471d10453SEric Joyner 		     *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
150571d10453SEric Joyner 
150671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "cmpltnqdata[%d]: %08X\n", i,
150771d10453SEric Joyner 			  *((u32 *)(ice_tx_cmpltnq_ctx + (i * sizeof(u32)))));
150871d10453SEric Joyner 	}
150971d10453SEric Joyner 
151071d10453SEric Joyner 	return ICE_SUCCESS;
151171d10453SEric Joyner }
151271d10453SEric Joyner 
151371d10453SEric Joyner /* LAN Tx Completion Queue Context */
151471d10453SEric Joyner static const struct ice_ctx_ele ice_tx_cmpltnq_ctx_info[] = {
151571d10453SEric Joyner 				       /* Field			Width   LSB */
151671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, base,			57,	0),
151771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, q_len,		18,	64),
151871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, generation,		1,	96),
151971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, wrt_ptr,		22,	97),
152071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, pf_num,		3,	128),
152171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_num,		10,	131),
152271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, vmvf_type,		2,	141),
152371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, tph_desc_wr,		1,	160),
152471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cpuid,		8,	161),
152571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_cmpltnq_ctx, cmpltn_cache,		512,	192),
152671d10453SEric Joyner 	{ 0 }
152771d10453SEric Joyner };
152871d10453SEric Joyner 
152971d10453SEric Joyner /**
153071d10453SEric Joyner  * ice_write_tx_cmpltnq_ctx
153171d10453SEric Joyner  * @hw: pointer to the hardware structure
153271d10453SEric Joyner  * @tx_cmpltnq_ctx: pointer to the completion queue context
153371d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue
153471d10453SEric Joyner  *
153571d10453SEric Joyner  * Converts completion queue context from sparse to dense structure and then
153671d10453SEric Joyner  * writes it to HW register space
153771d10453SEric Joyner  */
153871d10453SEric Joyner enum ice_status
153971d10453SEric Joyner ice_write_tx_cmpltnq_ctx(struct ice_hw *hw,
154071d10453SEric Joyner 			 struct ice_tx_cmpltnq_ctx *tx_cmpltnq_ctx,
154171d10453SEric Joyner 			 u32 tx_cmpltnq_index)
154271d10453SEric Joyner {
154371d10453SEric Joyner 	u8 ctx_buf[ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
154471d10453SEric Joyner 
15457d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info);
154671d10453SEric Joyner 	return ice_copy_tx_cmpltnq_ctx_to_hw(hw, ctx_buf, tx_cmpltnq_index);
154771d10453SEric Joyner }
154871d10453SEric Joyner 
154971d10453SEric Joyner /**
155071d10453SEric Joyner  * ice_clear_tx_cmpltnq_ctx
155171d10453SEric Joyner  * @hw: pointer to the hardware structure
155271d10453SEric Joyner  * @tx_cmpltnq_index: the index of the completion queue to clear
155371d10453SEric Joyner  *
155471d10453SEric Joyner  * Clears Tx completion queue context in HW register space
155571d10453SEric Joyner  */
155671d10453SEric Joyner enum ice_status
155771d10453SEric Joyner ice_clear_tx_cmpltnq_ctx(struct ice_hw *hw, u32 tx_cmpltnq_index)
155871d10453SEric Joyner {
155971d10453SEric Joyner 	u8 i;
156071d10453SEric Joyner 
156171d10453SEric Joyner 	if (tx_cmpltnq_index > GLTCLAN_CQ_CNTX0_MAX_INDEX)
156271d10453SEric Joyner 		return ICE_ERR_PARAM;
156371d10453SEric Joyner 
156471d10453SEric Joyner 	/* Clear each dword register separately */
156571d10453SEric Joyner 	for (i = 0; i < ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS; i++)
156671d10453SEric Joyner 		wr32(hw, GLTCLAN_CQ_CNTX(i, tx_cmpltnq_index), 0);
156771d10453SEric Joyner 
156871d10453SEric Joyner 	return ICE_SUCCESS;
156971d10453SEric Joyner }
157071d10453SEric Joyner 
157171d10453SEric Joyner /**
157271d10453SEric Joyner  * ice_copy_tx_drbell_q_ctx_to_hw
157371d10453SEric Joyner  * @hw: pointer to the hardware structure
157471d10453SEric Joyner  * @ice_tx_drbell_q_ctx: pointer to the doorbell queue context
157571d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
157671d10453SEric Joyner  *
157771d10453SEric Joyner  * Copies doorbell queue context from dense structure to HW register space
157871d10453SEric Joyner  */
157971d10453SEric Joyner static enum ice_status
158071d10453SEric Joyner ice_copy_tx_drbell_q_ctx_to_hw(struct ice_hw *hw, u8 *ice_tx_drbell_q_ctx,
158171d10453SEric Joyner 			       u32 tx_drbell_q_index)
158271d10453SEric Joyner {
158371d10453SEric Joyner 	u8 i;
158471d10453SEric Joyner 
158571d10453SEric Joyner 	if (!ice_tx_drbell_q_ctx)
158671d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
158771d10453SEric Joyner 
158871d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
158971d10453SEric Joyner 		return ICE_ERR_PARAM;
159071d10453SEric Joyner 
159171d10453SEric Joyner 	/* Copy each dword separately to HW */
159271d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++) {
159371d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index),
159471d10453SEric Joyner 		     *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
159571d10453SEric Joyner 
159671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_QCTX, "tx_drbell_qdata[%d]: %08X\n", i,
159771d10453SEric Joyner 			  *((u32 *)(ice_tx_drbell_q_ctx + (i * sizeof(u32)))));
159871d10453SEric Joyner 	}
159971d10453SEric Joyner 
160071d10453SEric Joyner 	return ICE_SUCCESS;
160171d10453SEric Joyner }
160271d10453SEric Joyner 
160371d10453SEric Joyner /* LAN Tx Doorbell Queue Context info */
160471d10453SEric Joyner static const struct ice_ctx_ele ice_tx_drbell_q_ctx_info[] = {
160571d10453SEric Joyner 					/* Field		Width   LSB */
160671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, base,		57,	0),
160771d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, ring_len,		13,	64),
160871d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, pf_num,		3,	80),
160971d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vf_num,		8,	84),
161071d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, vmvf_type,		2,	94),
161171d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, cpuid,		8,	96),
161271d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_rd,		1,	104),
161371d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, tph_desc_wr,		1,	108),
161471d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, db_q_en,		1,	112),
161571d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_head,		13,	128),
161671d10453SEric Joyner 	ICE_CTX_STORE(ice_tx_drbell_q_ctx, rd_tail,		13,	144),
161771d10453SEric Joyner 	{ 0 }
161871d10453SEric Joyner };
161971d10453SEric Joyner 
162071d10453SEric Joyner /**
162171d10453SEric Joyner  * ice_write_tx_drbell_q_ctx
162271d10453SEric Joyner  * @hw: pointer to the hardware structure
162371d10453SEric Joyner  * @tx_drbell_q_ctx: pointer to the doorbell queue context
162471d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue
162571d10453SEric Joyner  *
162671d10453SEric Joyner  * Converts doorbell queue context from sparse to dense structure and then
162771d10453SEric Joyner  * writes it to HW register space
162871d10453SEric Joyner  */
162971d10453SEric Joyner enum ice_status
163071d10453SEric Joyner ice_write_tx_drbell_q_ctx(struct ice_hw *hw,
163171d10453SEric Joyner 			  struct ice_tx_drbell_q_ctx *tx_drbell_q_ctx,
163271d10453SEric Joyner 			  u32 tx_drbell_q_index)
163371d10453SEric Joyner {
163471d10453SEric Joyner 	u8 ctx_buf[ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
163571d10453SEric Joyner 
16367d7af7f8SEric Joyner 	ice_set_ctx(hw, (u8 *)tx_drbell_q_ctx, ctx_buf,
16377d7af7f8SEric Joyner 		    ice_tx_drbell_q_ctx_info);
163871d10453SEric Joyner 	return ice_copy_tx_drbell_q_ctx_to_hw(hw, ctx_buf, tx_drbell_q_index);
163971d10453SEric Joyner }
164071d10453SEric Joyner 
164171d10453SEric Joyner /**
164271d10453SEric Joyner  * ice_clear_tx_drbell_q_ctx
164371d10453SEric Joyner  * @hw: pointer to the hardware structure
164471d10453SEric Joyner  * @tx_drbell_q_index: the index of the doorbell queue to clear
164571d10453SEric Joyner  *
164671d10453SEric Joyner  * Clears doorbell queue context in HW register space
164771d10453SEric Joyner  */
164871d10453SEric Joyner enum ice_status
164971d10453SEric Joyner ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index)
165071d10453SEric Joyner {
165171d10453SEric Joyner 	u8 i;
165271d10453SEric Joyner 
165371d10453SEric Joyner 	if (tx_drbell_q_index > QTX_COMM_DBLQ_DBELL_MAX_INDEX)
165471d10453SEric Joyner 		return ICE_ERR_PARAM;
165571d10453SEric Joyner 
165671d10453SEric Joyner 	/* Clear each dword register separately */
165771d10453SEric Joyner 	for (i = 0; i < ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS; i++)
165871d10453SEric Joyner 		wr32(hw, QTX_COMM_DBLQ_CNTX(i, tx_drbell_q_index), 0);
165971d10453SEric Joyner 
166071d10453SEric Joyner 	return ICE_SUCCESS;
166171d10453SEric Joyner }
166271d10453SEric Joyner 
166371d10453SEric Joyner /* FW Admin Queue command wrappers */
166471d10453SEric Joyner 
166571d10453SEric Joyner /**
16669cf1841cSEric Joyner  * ice_should_retry_sq_send_cmd
16679cf1841cSEric Joyner  * @opcode: AQ opcode
16689cf1841cSEric Joyner  *
16699cf1841cSEric Joyner  * Decide if we should retry the send command routine for the ATQ, depending
16709cf1841cSEric Joyner  * on the opcode.
16719cf1841cSEric Joyner  */
16729cf1841cSEric Joyner static bool ice_should_retry_sq_send_cmd(u16 opcode)
16739cf1841cSEric Joyner {
16749cf1841cSEric Joyner 	switch (opcode) {
16759cf1841cSEric Joyner 	case ice_aqc_opc_dnl_get_status:
16769cf1841cSEric Joyner 	case ice_aqc_opc_dnl_run:
16779cf1841cSEric Joyner 	case ice_aqc_opc_dnl_call:
16789cf1841cSEric Joyner 	case ice_aqc_opc_dnl_read_sto:
16799cf1841cSEric Joyner 	case ice_aqc_opc_dnl_write_sto:
16809cf1841cSEric Joyner 	case ice_aqc_opc_dnl_set_breakpoints:
16819cf1841cSEric Joyner 	case ice_aqc_opc_dnl_read_log:
16829cf1841cSEric Joyner 	case ice_aqc_opc_get_link_topo:
16839cf1841cSEric Joyner 	case ice_aqc_opc_done_alt_write:
16849cf1841cSEric Joyner 	case ice_aqc_opc_lldp_stop:
16859cf1841cSEric Joyner 	case ice_aqc_opc_lldp_start:
16869cf1841cSEric Joyner 	case ice_aqc_opc_lldp_filter_ctrl:
16879cf1841cSEric Joyner 		return true;
16889cf1841cSEric Joyner 	}
16899cf1841cSEric Joyner 
16909cf1841cSEric Joyner 	return false;
16919cf1841cSEric Joyner }
16929cf1841cSEric Joyner 
16939cf1841cSEric Joyner /**
16949cf1841cSEric Joyner  * ice_sq_send_cmd_retry - send command to Control Queue (ATQ)
16959cf1841cSEric Joyner  * @hw: pointer to the HW struct
16969cf1841cSEric Joyner  * @cq: pointer to the specific Control queue
16979cf1841cSEric Joyner  * @desc: prefilled descriptor describing the command
16989cf1841cSEric Joyner  * @buf: buffer to use for indirect commands (or NULL for direct commands)
16999cf1841cSEric Joyner  * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
17009cf1841cSEric Joyner  * @cd: pointer to command details structure
17019cf1841cSEric Joyner  *
17029cf1841cSEric Joyner  * Retry sending the FW Admin Queue command, multiple times, to the FW Admin
17039cf1841cSEric Joyner  * Queue if the EBUSY AQ error is returned.
17049cf1841cSEric Joyner  */
17059cf1841cSEric Joyner static enum ice_status
17069cf1841cSEric Joyner ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
17079cf1841cSEric Joyner 		      struct ice_aq_desc *desc, void *buf, u16 buf_size,
17089cf1841cSEric Joyner 		      struct ice_sq_cd *cd)
17099cf1841cSEric Joyner {
17109cf1841cSEric Joyner 	struct ice_aq_desc desc_cpy;
17119cf1841cSEric Joyner 	enum ice_status status;
17129cf1841cSEric Joyner 	bool is_cmd_for_retry;
17139cf1841cSEric Joyner 	u8 *buf_cpy = NULL;
17149cf1841cSEric Joyner 	u8 idx = 0;
17159cf1841cSEric Joyner 	u16 opcode;
17169cf1841cSEric Joyner 
17179cf1841cSEric Joyner 	opcode = LE16_TO_CPU(desc->opcode);
17189cf1841cSEric Joyner 	is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode);
17199cf1841cSEric Joyner 	ice_memset(&desc_cpy, 0, sizeof(desc_cpy), ICE_NONDMA_MEM);
17209cf1841cSEric Joyner 
17219cf1841cSEric Joyner 	if (is_cmd_for_retry) {
17229cf1841cSEric Joyner 		if (buf) {
17239cf1841cSEric Joyner 			buf_cpy = (u8 *)ice_malloc(hw, buf_size);
17249cf1841cSEric Joyner 			if (!buf_cpy)
17259cf1841cSEric Joyner 				return ICE_ERR_NO_MEMORY;
17269cf1841cSEric Joyner 		}
17279cf1841cSEric Joyner 
17289cf1841cSEric Joyner 		ice_memcpy(&desc_cpy, desc, sizeof(desc_cpy),
17299cf1841cSEric Joyner 			   ICE_NONDMA_TO_NONDMA);
17309cf1841cSEric Joyner 	}
17319cf1841cSEric Joyner 
17329cf1841cSEric Joyner 	do {
17339cf1841cSEric Joyner 		status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd);
17349cf1841cSEric Joyner 
17359cf1841cSEric Joyner 		if (!is_cmd_for_retry || status == ICE_SUCCESS ||
17369cf1841cSEric Joyner 		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
17379cf1841cSEric Joyner 			break;
17389cf1841cSEric Joyner 
17399cf1841cSEric Joyner 		if (buf_cpy)
17409cf1841cSEric Joyner 			ice_memcpy(buf, buf_cpy, buf_size,
17419cf1841cSEric Joyner 				   ICE_NONDMA_TO_NONDMA);
17429cf1841cSEric Joyner 
17439cf1841cSEric Joyner 		ice_memcpy(desc, &desc_cpy, sizeof(desc_cpy),
17449cf1841cSEric Joyner 			   ICE_NONDMA_TO_NONDMA);
17459cf1841cSEric Joyner 
17469cf1841cSEric Joyner 		ice_msec_delay(ICE_SQ_SEND_DELAY_TIME_MS, false);
17479cf1841cSEric Joyner 
17489cf1841cSEric Joyner 	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
17499cf1841cSEric Joyner 
17509cf1841cSEric Joyner 	if (buf_cpy)
17519cf1841cSEric Joyner 		ice_free(hw, buf_cpy);
17529cf1841cSEric Joyner 
17539cf1841cSEric Joyner 	return status;
17549cf1841cSEric Joyner }
17559cf1841cSEric Joyner 
17569cf1841cSEric Joyner /**
175771d10453SEric Joyner  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
175871d10453SEric Joyner  * @hw: pointer to the HW struct
175971d10453SEric Joyner  * @desc: descriptor describing the command
176071d10453SEric Joyner  * @buf: buffer to use for indirect commands (NULL for direct commands)
176171d10453SEric Joyner  * @buf_size: size of buffer for indirect commands (0 for direct commands)
176271d10453SEric Joyner  * @cd: pointer to command details structure
176371d10453SEric Joyner  *
176471d10453SEric Joyner  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
176571d10453SEric Joyner  */
176671d10453SEric Joyner enum ice_status
176771d10453SEric Joyner ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
176871d10453SEric Joyner 		u16 buf_size, struct ice_sq_cd *cd)
176971d10453SEric Joyner {
17709cf1841cSEric Joyner 	return ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);
177171d10453SEric Joyner }
177271d10453SEric Joyner 
177371d10453SEric Joyner /**
177471d10453SEric Joyner  * ice_aq_get_fw_ver
177571d10453SEric Joyner  * @hw: pointer to the HW struct
177671d10453SEric Joyner  * @cd: pointer to command details structure or NULL
177771d10453SEric Joyner  *
177871d10453SEric Joyner  * Get the firmware version (0x0001) from the admin queue commands
177971d10453SEric Joyner  */
178071d10453SEric Joyner enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
178171d10453SEric Joyner {
178271d10453SEric Joyner 	struct ice_aqc_get_ver *resp;
178371d10453SEric Joyner 	struct ice_aq_desc desc;
178471d10453SEric Joyner 	enum ice_status status;
178571d10453SEric Joyner 
178671d10453SEric Joyner 	resp = &desc.params.get_ver;
178771d10453SEric Joyner 
178871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
178971d10453SEric Joyner 
179071d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
179171d10453SEric Joyner 
179271d10453SEric Joyner 	if (!status) {
179371d10453SEric Joyner 		hw->fw_branch = resp->fw_branch;
179471d10453SEric Joyner 		hw->fw_maj_ver = resp->fw_major;
179571d10453SEric Joyner 		hw->fw_min_ver = resp->fw_minor;
179671d10453SEric Joyner 		hw->fw_patch = resp->fw_patch;
179771d10453SEric Joyner 		hw->fw_build = LE32_TO_CPU(resp->fw_build);
179871d10453SEric Joyner 		hw->api_branch = resp->api_branch;
179971d10453SEric Joyner 		hw->api_maj_ver = resp->api_major;
180071d10453SEric Joyner 		hw->api_min_ver = resp->api_minor;
180171d10453SEric Joyner 		hw->api_patch = resp->api_patch;
180271d10453SEric Joyner 	}
180371d10453SEric Joyner 
180471d10453SEric Joyner 	return status;
180571d10453SEric Joyner }
180671d10453SEric Joyner 
180771d10453SEric Joyner /**
180871d10453SEric Joyner  * ice_aq_send_driver_ver
180971d10453SEric Joyner  * @hw: pointer to the HW struct
181071d10453SEric Joyner  * @dv: driver's major, minor version
181171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
181271d10453SEric Joyner  *
181371d10453SEric Joyner  * Send the driver version (0x0002) to the firmware
181471d10453SEric Joyner  */
181571d10453SEric Joyner enum ice_status
181671d10453SEric Joyner ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
181771d10453SEric Joyner 		       struct ice_sq_cd *cd)
181871d10453SEric Joyner {
181971d10453SEric Joyner 	struct ice_aqc_driver_ver *cmd;
182071d10453SEric Joyner 	struct ice_aq_desc desc;
182171d10453SEric Joyner 	u16 len;
182271d10453SEric Joyner 
182371d10453SEric Joyner 	cmd = &desc.params.driver_ver;
182471d10453SEric Joyner 
182571d10453SEric Joyner 	if (!dv)
182671d10453SEric Joyner 		return ICE_ERR_PARAM;
182771d10453SEric Joyner 
182871d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
182971d10453SEric Joyner 
183071d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
183171d10453SEric Joyner 	cmd->major_ver = dv->major_ver;
183271d10453SEric Joyner 	cmd->minor_ver = dv->minor_ver;
183371d10453SEric Joyner 	cmd->build_ver = dv->build_ver;
183471d10453SEric Joyner 	cmd->subbuild_ver = dv->subbuild_ver;
183571d10453SEric Joyner 
183671d10453SEric Joyner 	len = 0;
183771d10453SEric Joyner 	while (len < sizeof(dv->driver_string) &&
183871d10453SEric Joyner 	       IS_ASCII(dv->driver_string[len]) && dv->driver_string[len])
183971d10453SEric Joyner 		len++;
184071d10453SEric Joyner 
184171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
184271d10453SEric Joyner }
184371d10453SEric Joyner 
184471d10453SEric Joyner /**
184571d10453SEric Joyner  * ice_aq_q_shutdown
184671d10453SEric Joyner  * @hw: pointer to the HW struct
184771d10453SEric Joyner  * @unloading: is the driver unloading itself
184871d10453SEric Joyner  *
184971d10453SEric Joyner  * Tell the Firmware that we're shutting down the AdminQ and whether
185071d10453SEric Joyner  * or not the driver is unloading as well (0x0003).
185171d10453SEric Joyner  */
185271d10453SEric Joyner enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
185371d10453SEric Joyner {
185471d10453SEric Joyner 	struct ice_aqc_q_shutdown *cmd;
185571d10453SEric Joyner 	struct ice_aq_desc desc;
185671d10453SEric Joyner 
185771d10453SEric Joyner 	cmd = &desc.params.q_shutdown;
185871d10453SEric Joyner 
185971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
186071d10453SEric Joyner 
186171d10453SEric Joyner 	if (unloading)
186271d10453SEric Joyner 		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
186371d10453SEric Joyner 
186471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
186571d10453SEric Joyner }
186671d10453SEric Joyner 
186771d10453SEric Joyner /**
186871d10453SEric Joyner  * ice_aq_req_res
186971d10453SEric Joyner  * @hw: pointer to the HW struct
187071d10453SEric Joyner  * @res: resource ID
187171d10453SEric Joyner  * @access: access type
187271d10453SEric Joyner  * @sdp_number: resource number
187371d10453SEric Joyner  * @timeout: the maximum time in ms that the driver may hold the resource
187471d10453SEric Joyner  * @cd: pointer to command details structure or NULL
187571d10453SEric Joyner  *
187671d10453SEric Joyner  * Requests common resource using the admin queue commands (0x0008).
187771d10453SEric Joyner  * When attempting to acquire the Global Config Lock, the driver can
187871d10453SEric Joyner  * learn of three states:
187971d10453SEric Joyner  *  1) ICE_SUCCESS -        acquired lock, and can perform download package
188071d10453SEric Joyner  *  2) ICE_ERR_AQ_ERROR -   did not get lock, driver should fail to load
188171d10453SEric Joyner  *  3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
188271d10453SEric Joyner  *                          successfully downloaded the package; the driver does
188371d10453SEric Joyner  *                          not have to download the package and can continue
188471d10453SEric Joyner  *                          loading
188571d10453SEric Joyner  *
188671d10453SEric Joyner  * Note that if the caller is in an acquire lock, perform action, release lock
188771d10453SEric Joyner  * phase of operation, it is possible that the FW may detect a timeout and issue
188871d10453SEric Joyner  * a CORER. In this case, the driver will receive a CORER interrupt and will
188971d10453SEric Joyner  * have to determine its cause. The calling thread that is handling this flow
189071d10453SEric Joyner  * will likely get an error propagated back to it indicating the Download
189171d10453SEric Joyner  * Package, Update Package or the Release Resource AQ commands timed out.
189271d10453SEric Joyner  */
189371d10453SEric Joyner static enum ice_status
189471d10453SEric Joyner ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
189571d10453SEric Joyner 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
189671d10453SEric Joyner 	       struct ice_sq_cd *cd)
189771d10453SEric Joyner {
189871d10453SEric Joyner 	struct ice_aqc_req_res *cmd_resp;
189971d10453SEric Joyner 	struct ice_aq_desc desc;
190071d10453SEric Joyner 	enum ice_status status;
190171d10453SEric Joyner 
190271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
190371d10453SEric Joyner 
190471d10453SEric Joyner 	cmd_resp = &desc.params.res_owner;
190571d10453SEric Joyner 
190671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
190771d10453SEric Joyner 
190871d10453SEric Joyner 	cmd_resp->res_id = CPU_TO_LE16(res);
190971d10453SEric Joyner 	cmd_resp->access_type = CPU_TO_LE16(access);
191071d10453SEric Joyner 	cmd_resp->res_number = CPU_TO_LE32(sdp_number);
191171d10453SEric Joyner 	cmd_resp->timeout = CPU_TO_LE32(*timeout);
191271d10453SEric Joyner 	*timeout = 0;
191371d10453SEric Joyner 
191471d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
191571d10453SEric Joyner 
191671d10453SEric Joyner 	/* The completion specifies the maximum time in ms that the driver
191771d10453SEric Joyner 	 * may hold the resource in the Timeout field.
191871d10453SEric Joyner 	 */
191971d10453SEric Joyner 
192071d10453SEric Joyner 	/* Global config lock response utilizes an additional status field.
192171d10453SEric Joyner 	 *
192271d10453SEric Joyner 	 * If the Global config lock resource is held by some other driver, the
192371d10453SEric Joyner 	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
192471d10453SEric Joyner 	 * and the timeout field indicates the maximum time the current owner
192571d10453SEric Joyner 	 * of the resource has to free it.
192671d10453SEric Joyner 	 */
192771d10453SEric Joyner 	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
192871d10453SEric Joyner 		if (LE16_TO_CPU(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
192971d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
193071d10453SEric Joyner 			return ICE_SUCCESS;
193171d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
193271d10453SEric Joyner 			   ICE_AQ_RES_GLBL_IN_PROG) {
193371d10453SEric Joyner 			*timeout = LE32_TO_CPU(cmd_resp->timeout);
193471d10453SEric Joyner 			return ICE_ERR_AQ_ERROR;
193571d10453SEric Joyner 		} else if (LE16_TO_CPU(cmd_resp->status) ==
193671d10453SEric Joyner 			   ICE_AQ_RES_GLBL_DONE) {
193771d10453SEric Joyner 			return ICE_ERR_AQ_NO_WORK;
193871d10453SEric Joyner 		}
193971d10453SEric Joyner 
194071d10453SEric Joyner 		/* invalid FW response, force a timeout immediately */
194171d10453SEric Joyner 		*timeout = 0;
194271d10453SEric Joyner 		return ICE_ERR_AQ_ERROR;
194371d10453SEric Joyner 	}
194471d10453SEric Joyner 
194571d10453SEric Joyner 	/* If the resource is held by some other driver, the command completes
194671d10453SEric Joyner 	 * with a busy return value and the timeout field indicates the maximum
194771d10453SEric Joyner 	 * time the current owner of the resource has to free it.
194871d10453SEric Joyner 	 */
194971d10453SEric Joyner 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
195071d10453SEric Joyner 		*timeout = LE32_TO_CPU(cmd_resp->timeout);
195171d10453SEric Joyner 
195271d10453SEric Joyner 	return status;
195371d10453SEric Joyner }
195471d10453SEric Joyner 
195571d10453SEric Joyner /**
195671d10453SEric Joyner  * ice_aq_release_res
195771d10453SEric Joyner  * @hw: pointer to the HW struct
195871d10453SEric Joyner  * @res: resource ID
195971d10453SEric Joyner  * @sdp_number: resource number
196071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
196171d10453SEric Joyner  *
196271d10453SEric Joyner  * release common resource using the admin queue commands (0x0009)
196371d10453SEric Joyner  */
196471d10453SEric Joyner static enum ice_status
196571d10453SEric Joyner ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
196671d10453SEric Joyner 		   struct ice_sq_cd *cd)
196771d10453SEric Joyner {
196871d10453SEric Joyner 	struct ice_aqc_req_res *cmd;
196971d10453SEric Joyner 	struct ice_aq_desc desc;
197071d10453SEric Joyner 
197171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
197271d10453SEric Joyner 
197371d10453SEric Joyner 	cmd = &desc.params.res_owner;
197471d10453SEric Joyner 
197571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
197671d10453SEric Joyner 
197771d10453SEric Joyner 	cmd->res_id = CPU_TO_LE16(res);
197871d10453SEric Joyner 	cmd->res_number = CPU_TO_LE32(sdp_number);
197971d10453SEric Joyner 
198071d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
198171d10453SEric Joyner }
198271d10453SEric Joyner 
198371d10453SEric Joyner /**
198471d10453SEric Joyner  * ice_acquire_res
198571d10453SEric Joyner  * @hw: pointer to the HW structure
198671d10453SEric Joyner  * @res: resource ID
198771d10453SEric Joyner  * @access: access type (read or write)
198871d10453SEric Joyner  * @timeout: timeout in milliseconds
198971d10453SEric Joyner  *
199071d10453SEric Joyner  * This function will attempt to acquire the ownership of a resource.
199171d10453SEric Joyner  */
199271d10453SEric Joyner enum ice_status
199371d10453SEric Joyner ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
199471d10453SEric Joyner 		enum ice_aq_res_access_type access, u32 timeout)
199571d10453SEric Joyner {
199671d10453SEric Joyner #define ICE_RES_POLLING_DELAY_MS	10
199771d10453SEric Joyner 	u32 delay = ICE_RES_POLLING_DELAY_MS;
199871d10453SEric Joyner 	u32 time_left = timeout;
199971d10453SEric Joyner 	enum ice_status status;
200071d10453SEric Joyner 
200171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
200271d10453SEric Joyner 
200371d10453SEric Joyner 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
200471d10453SEric Joyner 
200571d10453SEric Joyner 	/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
200671d10453SEric Joyner 	 * previously acquired the resource and performed any necessary updates;
200771d10453SEric Joyner 	 * in this case the caller does not obtain the resource and has no
200871d10453SEric Joyner 	 * further work to do.
200971d10453SEric Joyner 	 */
201071d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK)
201171d10453SEric Joyner 		goto ice_acquire_res_exit;
201271d10453SEric Joyner 
201371d10453SEric Joyner 	if (status)
20147d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access);
201571d10453SEric Joyner 
201671d10453SEric Joyner 	/* If necessary, poll until the current lock owner timeouts */
201771d10453SEric Joyner 	timeout = time_left;
201871d10453SEric Joyner 	while (status && timeout && time_left) {
201971d10453SEric Joyner 		ice_msec_delay(delay, true);
202071d10453SEric Joyner 		timeout = (timeout > delay) ? timeout - delay : 0;
202171d10453SEric Joyner 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
202271d10453SEric Joyner 
202371d10453SEric Joyner 		if (status == ICE_ERR_AQ_NO_WORK)
202471d10453SEric Joyner 			/* lock free, but no work to do */
202571d10453SEric Joyner 			break;
202671d10453SEric Joyner 
202771d10453SEric Joyner 		if (!status)
202871d10453SEric Joyner 			/* lock acquired */
202971d10453SEric Joyner 			break;
203071d10453SEric Joyner 	}
203171d10453SEric Joyner 	if (status && status != ICE_ERR_AQ_NO_WORK)
203271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
203371d10453SEric Joyner 
203471d10453SEric Joyner ice_acquire_res_exit:
203571d10453SEric Joyner 	if (status == ICE_ERR_AQ_NO_WORK) {
203671d10453SEric Joyner 		if (access == ICE_RES_WRITE)
20377d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n");
203871d10453SEric Joyner 		else
20397d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_RES, "Warning: ICE_ERR_AQ_NO_WORK not expected\n");
204071d10453SEric Joyner 	}
204171d10453SEric Joyner 	return status;
204271d10453SEric Joyner }
204371d10453SEric Joyner 
204471d10453SEric Joyner /**
204571d10453SEric Joyner  * ice_release_res
204671d10453SEric Joyner  * @hw: pointer to the HW structure
204771d10453SEric Joyner  * @res: resource ID
204871d10453SEric Joyner  *
204971d10453SEric Joyner  * This function will release a resource using the proper Admin Command.
205071d10453SEric Joyner  */
205171d10453SEric Joyner void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
205271d10453SEric Joyner {
205371d10453SEric Joyner 	enum ice_status status;
205471d10453SEric Joyner 	u32 total_delay = 0;
205571d10453SEric Joyner 
205671d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
205771d10453SEric Joyner 
205871d10453SEric Joyner 	status = ice_aq_release_res(hw, res, 0, NULL);
205971d10453SEric Joyner 
206071d10453SEric Joyner 	/* there are some rare cases when trying to release the resource
206171d10453SEric Joyner 	 * results in an admin queue timeout, so handle them correctly
206271d10453SEric Joyner 	 */
206371d10453SEric Joyner 	while ((status == ICE_ERR_AQ_TIMEOUT) &&
206471d10453SEric Joyner 	       (total_delay < hw->adminq.sq_cmd_timeout)) {
206571d10453SEric Joyner 		ice_msec_delay(1, true);
206671d10453SEric Joyner 		status = ice_aq_release_res(hw, res, 0, NULL);
206771d10453SEric Joyner 		total_delay++;
206871d10453SEric Joyner 	}
206971d10453SEric Joyner }
207071d10453SEric Joyner 
207171d10453SEric Joyner /**
207271d10453SEric Joyner  * ice_aq_alloc_free_res - command to allocate/free resources
207371d10453SEric Joyner  * @hw: pointer to the HW struct
207471d10453SEric Joyner  * @num_entries: number of resource entries in buffer
207571d10453SEric Joyner  * @buf: Indirect buffer to hold data parameters and response
207671d10453SEric Joyner  * @buf_size: size of buffer for indirect commands
207771d10453SEric Joyner  * @opc: pass in the command opcode
207871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
207971d10453SEric Joyner  *
208071d10453SEric Joyner  * Helper function to allocate/free resources using the admin queue commands
208171d10453SEric Joyner  */
208271d10453SEric Joyner enum ice_status
208371d10453SEric Joyner ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
208471d10453SEric Joyner 		      struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
208571d10453SEric Joyner 		      enum ice_adminq_opc opc, struct ice_sq_cd *cd)
208671d10453SEric Joyner {
208771d10453SEric Joyner 	struct ice_aqc_alloc_free_res_cmd *cmd;
208871d10453SEric Joyner 	struct ice_aq_desc desc;
208971d10453SEric Joyner 
209071d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
209171d10453SEric Joyner 
209271d10453SEric Joyner 	cmd = &desc.params.sw_res_ctrl;
209371d10453SEric Joyner 
209471d10453SEric Joyner 	if (!buf)
209571d10453SEric Joyner 		return ICE_ERR_PARAM;
209671d10453SEric Joyner 
2097d08b8680SEric Joyner 	if (buf_size < FLEX_ARRAY_SIZE(buf, elem, num_entries))
209871d10453SEric Joyner 		return ICE_ERR_PARAM;
209971d10453SEric Joyner 
210071d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
210171d10453SEric Joyner 
210271d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
210371d10453SEric Joyner 
210471d10453SEric Joyner 	cmd->num_entries = CPU_TO_LE16(num_entries);
210571d10453SEric Joyner 
210671d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
210771d10453SEric Joyner }
210871d10453SEric Joyner 
210971d10453SEric Joyner /**
211071d10453SEric Joyner  * ice_alloc_hw_res - allocate resource
211171d10453SEric Joyner  * @hw: pointer to the HW struct
211271d10453SEric Joyner  * @type: type of resource
211371d10453SEric Joyner  * @num: number of resources to allocate
211471d10453SEric Joyner  * @btm: allocate from bottom
211571d10453SEric Joyner  * @res: pointer to array that will receive the resources
211671d10453SEric Joyner  */
211771d10453SEric Joyner enum ice_status
211871d10453SEric Joyner ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
211971d10453SEric Joyner {
212071d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
212171d10453SEric Joyner 	enum ice_status status;
212271d10453SEric Joyner 	u16 buf_len;
212371d10453SEric Joyner 
21247d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
21257d7af7f8SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
212671d10453SEric Joyner 	if (!buf)
212771d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
212871d10453SEric Joyner 
212971d10453SEric Joyner 	/* Prepare buffer to allocate resource. */
213071d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
213171d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
213271d10453SEric Joyner 				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
213371d10453SEric Joyner 	if (btm)
213471d10453SEric Joyner 		buf->res_type |= CPU_TO_LE16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
213571d10453SEric Joyner 
213671d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
213771d10453SEric Joyner 				       ice_aqc_opc_alloc_res, NULL);
213871d10453SEric Joyner 	if (status)
213971d10453SEric Joyner 		goto ice_alloc_res_exit;
214071d10453SEric Joyner 
21417d7af7f8SEric Joyner 	ice_memcpy(res, buf->elem, sizeof(*buf->elem) * num,
214271d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
214371d10453SEric Joyner 
214471d10453SEric Joyner ice_alloc_res_exit:
214571d10453SEric Joyner 	ice_free(hw, buf);
214671d10453SEric Joyner 	return status;
214771d10453SEric Joyner }
214871d10453SEric Joyner 
214971d10453SEric Joyner /**
215071d10453SEric Joyner  * ice_free_hw_res - free allocated HW resource
215171d10453SEric Joyner  * @hw: pointer to the HW struct
215271d10453SEric Joyner  * @type: type of resource to free
215371d10453SEric Joyner  * @num: number of resources
215471d10453SEric Joyner  * @res: pointer to array that contains the resources to free
215571d10453SEric Joyner  */
21567d7af7f8SEric Joyner enum ice_status ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
215771d10453SEric Joyner {
215871d10453SEric Joyner 	struct ice_aqc_alloc_free_res_elem *buf;
215971d10453SEric Joyner 	enum ice_status status;
216071d10453SEric Joyner 	u16 buf_len;
216171d10453SEric Joyner 
21627d7af7f8SEric Joyner 	buf_len = ice_struct_size(buf, elem, num);
216371d10453SEric Joyner 	buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
216471d10453SEric Joyner 	if (!buf)
216571d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
216671d10453SEric Joyner 
216771d10453SEric Joyner 	/* Prepare buffer to free resource. */
216871d10453SEric Joyner 	buf->num_elems = CPU_TO_LE16(num);
216971d10453SEric Joyner 	buf->res_type = CPU_TO_LE16(type);
21707d7af7f8SEric Joyner 	ice_memcpy(buf->elem, res, sizeof(*buf->elem) * num,
217171d10453SEric Joyner 		   ICE_NONDMA_TO_NONDMA);
217271d10453SEric Joyner 
217371d10453SEric Joyner 	status = ice_aq_alloc_free_res(hw, num, buf, buf_len,
217471d10453SEric Joyner 				       ice_aqc_opc_free_res, NULL);
217571d10453SEric Joyner 	if (status)
217671d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
217771d10453SEric Joyner 
217871d10453SEric Joyner 	ice_free(hw, buf);
217971d10453SEric Joyner 	return status;
218071d10453SEric Joyner }
218171d10453SEric Joyner 
218271d10453SEric Joyner /**
218371d10453SEric Joyner  * ice_get_num_per_func - determine number of resources per PF
218471d10453SEric Joyner  * @hw: pointer to the HW structure
218571d10453SEric Joyner  * @max: value to be evenly split between each PF
218671d10453SEric Joyner  *
218771d10453SEric Joyner  * Determine the number of valid functions by going through the bitmap returned
218871d10453SEric Joyner  * from parsing capabilities and use this to calculate the number of resources
218971d10453SEric Joyner  * per PF based on the max value passed in.
219071d10453SEric Joyner  */
219171d10453SEric Joyner static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
219271d10453SEric Joyner {
219371d10453SEric Joyner 	u8 funcs;
219471d10453SEric Joyner 
219571d10453SEric Joyner #define ICE_CAPS_VALID_FUNCS_M	0xFF
219671d10453SEric Joyner 	funcs = ice_hweight8(hw->dev_caps.common_cap.valid_functions &
219771d10453SEric Joyner 			     ICE_CAPS_VALID_FUNCS_M);
219871d10453SEric Joyner 
219971d10453SEric Joyner 	if (!funcs)
220071d10453SEric Joyner 		return 0;
220171d10453SEric Joyner 
220271d10453SEric Joyner 	return max / funcs;
220371d10453SEric Joyner }
220471d10453SEric Joyner 
220571d10453SEric Joyner /**
220671d10453SEric Joyner  * ice_print_led_caps - print LED capabilities
220771d10453SEric Joyner  * @hw: pointer to the ice_hw instance
220871d10453SEric Joyner  * @caps: pointer to common caps instance
220971d10453SEric Joyner  * @prefix: string to prefix when printing
22109cf1841cSEric Joyner  * @dbg: set to indicate debug print
221171d10453SEric Joyner  */
221271d10453SEric Joyner static void
221371d10453SEric Joyner ice_print_led_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
22149cf1841cSEric Joyner 		   char const *prefix, bool dbg)
221571d10453SEric Joyner {
221671d10453SEric Joyner 	u8 i;
221771d10453SEric Joyner 
22189cf1841cSEric Joyner 	if (dbg)
221971d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: led_pin_num = %d\n", prefix,
222071d10453SEric Joyner 			  caps->led_pin_num);
222171d10453SEric Joyner 	else
222271d10453SEric Joyner 		ice_info(hw, "%s: led_pin_num = %d\n", prefix,
222371d10453SEric Joyner 			 caps->led_pin_num);
222471d10453SEric Joyner 
222571d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_LED; i++) {
222671d10453SEric Joyner 		if (!caps->led[i])
222771d10453SEric Joyner 			continue;
222871d10453SEric Joyner 
22299cf1841cSEric Joyner 		if (dbg)
223071d10453SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = %d\n",
223171d10453SEric Joyner 				  prefix, i, caps->led[i]);
223271d10453SEric Joyner 		else
223371d10453SEric Joyner 			ice_info(hw, "%s: led[%d] = %d\n", prefix, i,
223471d10453SEric Joyner 				 caps->led[i]);
223571d10453SEric Joyner 	}
223671d10453SEric Joyner }
223771d10453SEric Joyner 
223871d10453SEric Joyner /**
223971d10453SEric Joyner  * ice_print_sdp_caps - print SDP capabilities
224071d10453SEric Joyner  * @hw: pointer to the ice_hw instance
224171d10453SEric Joyner  * @caps: pointer to common caps instance
224271d10453SEric Joyner  * @prefix: string to prefix when printing
22439cf1841cSEric Joyner  * @dbg: set to indicate debug print
224471d10453SEric Joyner  */
224571d10453SEric Joyner static void
224671d10453SEric Joyner ice_print_sdp_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
22479cf1841cSEric Joyner 		   char const *prefix, bool dbg)
224871d10453SEric Joyner {
224971d10453SEric Joyner 	u8 i;
225071d10453SEric Joyner 
22519cf1841cSEric Joyner 	if (dbg)
225271d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sdp_pin_num = %d\n", prefix,
225371d10453SEric Joyner 			  caps->sdp_pin_num);
225471d10453SEric Joyner 	else
225571d10453SEric Joyner 		ice_info(hw, "%s: sdp_pin_num = %d\n", prefix,
225671d10453SEric Joyner 			 caps->sdp_pin_num);
225771d10453SEric Joyner 
225871d10453SEric Joyner 	for (i = 0; i < ICE_MAX_SUPPORTED_GPIO_SDP; i++) {
225971d10453SEric Joyner 		if (!caps->sdp[i])
226071d10453SEric Joyner 			continue;
226171d10453SEric Joyner 
22629cf1841cSEric Joyner 		if (dbg)
226371d10453SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = %d\n",
226471d10453SEric Joyner 				  prefix, i, caps->sdp[i]);
226571d10453SEric Joyner 		else
226671d10453SEric Joyner 			ice_info(hw, "%s: sdp[%d] = %d\n", prefix,
226771d10453SEric Joyner 				 i, caps->sdp[i]);
226871d10453SEric Joyner 	}
226971d10453SEric Joyner }
227071d10453SEric Joyner 
227171d10453SEric Joyner /**
22727d7af7f8SEric Joyner  * ice_parse_common_caps - parse common device/function capabilities
227371d10453SEric Joyner  * @hw: pointer to the HW struct
22747d7af7f8SEric Joyner  * @caps: pointer to common capabilities structure
22757d7af7f8SEric Joyner  * @elem: the capability element to parse
22767d7af7f8SEric Joyner  * @prefix: message prefix for tracing capabilities
227771d10453SEric Joyner  *
22787d7af7f8SEric Joyner  * Given a capability element, extract relevant details into the common
22797d7af7f8SEric Joyner  * capability structure.
22807d7af7f8SEric Joyner  *
22817d7af7f8SEric Joyner  * Returns: true if the capability matches one of the common capability ids,
22827d7af7f8SEric Joyner  * false otherwise.
228371d10453SEric Joyner  */
22847d7af7f8SEric Joyner static bool
22857d7af7f8SEric Joyner ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
22867d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
228771d10453SEric Joyner {
22887d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(elem->logical_id);
22897d7af7f8SEric Joyner 	u32 phys_id = LE32_TO_CPU(elem->phys_id);
22907d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(elem->number);
22917d7af7f8SEric Joyner 	u16 cap = LE16_TO_CPU(elem->cap);
22927d7af7f8SEric Joyner 	bool found = true;
229371d10453SEric Joyner 
229471d10453SEric Joyner 	switch (cap) {
229571d10453SEric Joyner 	case ICE_AQC_CAPS_SWITCHING_MODE:
229671d10453SEric Joyner 		caps->switching_mode = number;
22977d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: switching_mode = %d\n", prefix,
229871d10453SEric Joyner 			  caps->switching_mode);
229971d10453SEric Joyner 		break;
230071d10453SEric Joyner 	case ICE_AQC_CAPS_MANAGEABILITY_MODE:
230171d10453SEric Joyner 		caps->mgmt_mode = number;
230271d10453SEric Joyner 		caps->mgmt_protocols_mctp = logical_id;
23037d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_mode = %d\n", prefix,
230471d10453SEric Joyner 			  caps->mgmt_mode);
23057d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_protocols_mctp = %d\n", prefix,
230671d10453SEric Joyner 			  caps->mgmt_protocols_mctp);
230771d10453SEric Joyner 		break;
230871d10453SEric Joyner 	case ICE_AQC_CAPS_OS2BMC:
230971d10453SEric Joyner 		caps->os2bmc = number;
23107d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: os2bmc = %d\n", prefix, caps->os2bmc);
231171d10453SEric Joyner 		break;
231271d10453SEric Joyner 	case ICE_AQC_CAPS_VALID_FUNCTIONS:
231371d10453SEric Joyner 		caps->valid_functions = number;
23147d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix,
231571d10453SEric Joyner 			  caps->valid_functions);
231671d10453SEric Joyner 		break;
231771d10453SEric Joyner 	case ICE_AQC_CAPS_SRIOV:
231871d10453SEric Joyner 		caps->sr_iov_1_1 = (number == 1);
23197d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix,
232071d10453SEric Joyner 			  caps->sr_iov_1_1);
232171d10453SEric Joyner 		break;
2322*9e54973fSEric Joyner 	case ICE_AQC_CAPS_VMDQ:
2323*9e54973fSEric Joyner 		caps->vmdq = (number == 1);
2324*9e54973fSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: vmdq = %d\n", prefix, caps->vmdq);
2325*9e54973fSEric Joyner 		break;
232671d10453SEric Joyner 	case ICE_AQC_CAPS_802_1QBG:
232771d10453SEric Joyner 		caps->evb_802_1_qbg = (number == 1);
23287d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbg = %d\n", prefix, number);
232971d10453SEric Joyner 		break;
233071d10453SEric Joyner 	case ICE_AQC_CAPS_802_1BR:
233171d10453SEric Joyner 		caps->evb_802_1_qbh = (number == 1);
23327d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: evb_802_1_qbh = %d\n", prefix, number);
233371d10453SEric Joyner 		break;
233471d10453SEric Joyner 	case ICE_AQC_CAPS_DCB:
233571d10453SEric Joyner 		caps->dcb = (number == 1);
233671d10453SEric Joyner 		caps->active_tc_bitmap = logical_id;
233771d10453SEric Joyner 		caps->maxtc = phys_id;
23387d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb);
23397d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix,
234071d10453SEric Joyner 			  caps->active_tc_bitmap);
23417d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc);
234271d10453SEric Joyner 		break;
234371d10453SEric Joyner 	case ICE_AQC_CAPS_ISCSI:
234471d10453SEric Joyner 		caps->iscsi = (number == 1);
23457d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: iscsi = %d\n", prefix, caps->iscsi);
234671d10453SEric Joyner 		break;
234771d10453SEric Joyner 	case ICE_AQC_CAPS_RSS:
234871d10453SEric Joyner 		caps->rss_table_size = number;
234971d10453SEric Joyner 		caps->rss_table_entry_width = logical_id;
23507d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix,
235171d10453SEric Joyner 			  caps->rss_table_size);
23527d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix,
235371d10453SEric Joyner 			  caps->rss_table_entry_width);
235471d10453SEric Joyner 		break;
235571d10453SEric Joyner 	case ICE_AQC_CAPS_RXQS:
235671d10453SEric Joyner 		caps->num_rxq = number;
235771d10453SEric Joyner 		caps->rxq_first_id = phys_id;
23587d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix,
235971d10453SEric Joyner 			  caps->num_rxq);
23607d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix,
236171d10453SEric Joyner 			  caps->rxq_first_id);
236271d10453SEric Joyner 		break;
236371d10453SEric Joyner 	case ICE_AQC_CAPS_TXQS:
236471d10453SEric Joyner 		caps->num_txq = number;
236571d10453SEric Joyner 		caps->txq_first_id = phys_id;
23667d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix,
236771d10453SEric Joyner 			  caps->num_txq);
23687d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix,
236971d10453SEric Joyner 			  caps->txq_first_id);
237071d10453SEric Joyner 		break;
237171d10453SEric Joyner 	case ICE_AQC_CAPS_MSIX:
237271d10453SEric Joyner 		caps->num_msix_vectors = number;
237371d10453SEric Joyner 		caps->msix_vector_first_id = phys_id;
23747d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix,
237571d10453SEric Joyner 			  caps->num_msix_vectors);
23767d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
237771d10453SEric Joyner 			  caps->msix_vector_first_id);
237871d10453SEric Joyner 		break;
237971d10453SEric Joyner 	case ICE_AQC_CAPS_NVM_MGMT:
2380d08b8680SEric Joyner 		caps->sec_rev_disabled =
2381d08b8680SEric Joyner 			(number & ICE_NVM_MGMT_SEC_REV_DISABLED) ?
2382d08b8680SEric Joyner 			true : false;
2383d08b8680SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: sec_rev_disabled = %d\n", prefix,
2384d08b8680SEric Joyner 			  caps->sec_rev_disabled);
2385d08b8680SEric Joyner 		caps->update_disabled =
2386d08b8680SEric Joyner 			(number & ICE_NVM_MGMT_UPDATE_DISABLED) ?
2387d08b8680SEric Joyner 			true : false;
2388d08b8680SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: update_disabled = %d\n", prefix,
2389d08b8680SEric Joyner 			  caps->update_disabled);
239071d10453SEric Joyner 		caps->nvm_unified_update =
239171d10453SEric Joyner 			(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
239271d10453SEric Joyner 			true : false;
23937d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
239471d10453SEric Joyner 			  caps->nvm_unified_update);
23959c30461dSEric Joyner 		caps->netlist_auth =
23969c30461dSEric Joyner 			(number & ICE_NVM_MGMT_NETLIST_AUTH_SUPPORT) ?
23979c30461dSEric Joyner 			true : false;
23989c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: netlist_auth = %d\n", prefix,
23999c30461dSEric Joyner 			  caps->netlist_auth);
240071d10453SEric Joyner 		break;
240171d10453SEric Joyner 	case ICE_AQC_CAPS_CEM:
240271d10453SEric Joyner 		caps->mgmt_cem = (number == 1);
24037d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: mgmt_cem = %d\n", prefix,
240471d10453SEric Joyner 			  caps->mgmt_cem);
240571d10453SEric Joyner 		break;
24068a13362dSEric Joyner 	case ICE_AQC_CAPS_IWARP:
24078a13362dSEric Joyner 		caps->iwarp = (number == 1);
24088a13362dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: iwarp = %d\n", prefix, caps->iwarp);
24098a13362dSEric Joyner 		break;
24108923de59SPiotr Kubaj 	case ICE_AQC_CAPS_ROCEV2_LAG:
2411*9e54973fSEric Joyner 		caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG);
24128923de59SPiotr Kubaj 		ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %d\n",
24138923de59SPiotr Kubaj 			  prefix, caps->roce_lag);
24148923de59SPiotr Kubaj 		break;
241571d10453SEric Joyner 	case ICE_AQC_CAPS_LED:
241671d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_LED) {
241771d10453SEric Joyner 			caps->led[phys_id] = true;
241871d10453SEric Joyner 			caps->led_pin_num++;
24197d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: led[%d] = 1\n", prefix, phys_id);
242071d10453SEric Joyner 		}
242171d10453SEric Joyner 		break;
242271d10453SEric Joyner 	case ICE_AQC_CAPS_SDP:
242371d10453SEric Joyner 		if (phys_id < ICE_MAX_SUPPORTED_GPIO_SDP) {
242471d10453SEric Joyner 			caps->sdp[phys_id] = true;
242571d10453SEric Joyner 			caps->sdp_pin_num++;
24267d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "%s: sdp[%d] = 1\n", prefix, phys_id);
242771d10453SEric Joyner 		}
242871d10453SEric Joyner 		break;
242971d10453SEric Joyner 	case ICE_AQC_CAPS_WR_CSR_PROT:
243071d10453SEric Joyner 		caps->wr_csr_prot = number;
243171d10453SEric Joyner 		caps->wr_csr_prot |= (u64)logical_id << 32;
24327d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wr_csr_prot = 0x%llX\n", prefix,
243371d10453SEric Joyner 			  (unsigned long long)caps->wr_csr_prot);
243471d10453SEric Joyner 		break;
243571d10453SEric Joyner 	case ICE_AQC_CAPS_WOL_PROXY:
243671d10453SEric Joyner 		caps->num_wol_proxy_fltr = number;
243771d10453SEric Joyner 		caps->wol_proxy_vsi_seid = logical_id;
243871d10453SEric Joyner 		caps->apm_wol_support = !!(phys_id & ICE_WOL_SUPPORT_M);
243971d10453SEric Joyner 		caps->acpi_prog_mthd = !!(phys_id &
244071d10453SEric Joyner 					  ICE_ACPI_PROG_MTHD_M);
244171d10453SEric Joyner 		caps->proxy_support = !!(phys_id & ICE_PROXY_SUPPORT_M);
24427d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: num_wol_proxy_fltr = %d\n", prefix,
244371d10453SEric Joyner 			  caps->num_wol_proxy_fltr);
24447d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: wol_proxy_vsi_seid = %d\n", prefix,
244571d10453SEric Joyner 			  caps->wol_proxy_vsi_seid);
244656429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: apm_wol_support = %d\n",
244756429daeSEric Joyner 			  prefix, caps->apm_wol_support);
244871d10453SEric Joyner 		break;
244971d10453SEric Joyner 	case ICE_AQC_CAPS_MAX_MTU:
245071d10453SEric Joyner 		caps->max_mtu = number;
245171d10453SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
245271d10453SEric Joyner 			  prefix, caps->max_mtu);
245371d10453SEric Joyner 		break;
245456429daeSEric Joyner 	case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
245556429daeSEric Joyner 		caps->pcie_reset_avoidance = (number > 0);
245656429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
245756429daeSEric Joyner 			  "%s: pcie_reset_avoidance = %d\n", prefix,
245856429daeSEric Joyner 			  caps->pcie_reset_avoidance);
245956429daeSEric Joyner 		break;
246056429daeSEric Joyner 	case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
246156429daeSEric Joyner 		caps->reset_restrict_support = (number == 1);
246256429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
246356429daeSEric Joyner 			  "%s: reset_restrict_support = %d\n", prefix,
246456429daeSEric Joyner 			  caps->reset_restrict_support);
246556429daeSEric Joyner 		break;
246656429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0:
246756429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1:
246856429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2:
246956429daeSEric Joyner 	case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3:
247056429daeSEric Joyner 	{
24718923de59SPiotr Kubaj 		u8 index = (u8)(cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0);
247256429daeSEric Joyner 
247356429daeSEric Joyner 		caps->ext_topo_dev_img_ver_high[index] = number;
247456429daeSEric Joyner 		caps->ext_topo_dev_img_ver_low[index] = logical_id;
247556429daeSEric Joyner 		caps->ext_topo_dev_img_part_num[index] =
247656429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
247756429daeSEric Joyner 			ICE_EXT_TOPO_DEV_IMG_PART_NUM_S;
247856429daeSEric Joyner 		caps->ext_topo_dev_img_load_en[index] =
247956429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
248056429daeSEric Joyner 		caps->ext_topo_dev_img_prog_en[index] =
248156429daeSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
24829c30461dSEric Joyner 		caps->ext_topo_dev_img_ver_schema[index] =
24839c30461dSEric Joyner 			(phys_id & ICE_EXT_TOPO_DEV_IMG_VER_SCHEMA) != 0;
248456429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
248556429daeSEric Joyner 			  "%s: ext_topo_dev_img_ver_high[%d] = %d\n",
248656429daeSEric Joyner 			  prefix, index,
248756429daeSEric Joyner 			  caps->ext_topo_dev_img_ver_high[index]);
248856429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
248956429daeSEric Joyner 			  "%s: ext_topo_dev_img_ver_low[%d] = %d\n",
249056429daeSEric Joyner 			  prefix, index,
249156429daeSEric Joyner 			  caps->ext_topo_dev_img_ver_low[index]);
249256429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
249356429daeSEric Joyner 			  "%s: ext_topo_dev_img_part_num[%d] = %d\n",
249456429daeSEric Joyner 			  prefix, index,
249556429daeSEric Joyner 			  caps->ext_topo_dev_img_part_num[index]);
249656429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
249756429daeSEric Joyner 			  "%s: ext_topo_dev_img_load_en[%d] = %d\n",
249856429daeSEric Joyner 			  prefix, index,
249956429daeSEric Joyner 			  caps->ext_topo_dev_img_load_en[index]);
250056429daeSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
250156429daeSEric Joyner 			  "%s: ext_topo_dev_img_prog_en[%d] = %d\n",
250256429daeSEric Joyner 			  prefix, index,
250356429daeSEric Joyner 			  caps->ext_topo_dev_img_prog_en[index]);
25049c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT,
25059c30461dSEric Joyner 			  "%s: ext_topo_dev_img_ver_schema[%d] = %d\n",
25069c30461dSEric Joyner 			  prefix, index,
25079c30461dSEric Joyner 			  caps->ext_topo_dev_img_ver_schema[index]);
250856429daeSEric Joyner 		break;
250956429daeSEric Joyner 	}
25108923de59SPiotr Kubaj 	case ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE:
25118923de59SPiotr Kubaj 		caps->tx_sched_topo_comp_mode_en = (number == 1);
25128923de59SPiotr Kubaj 		break;
25138923de59SPiotr Kubaj 	case ICE_AQC_CAPS_DYN_FLATTENING:
25148923de59SPiotr Kubaj 		caps->dyn_flattening_en = (number == 1);
25158923de59SPiotr Kubaj 		ice_debug(hw, ICE_DBG_INIT, "%s: dyn_flattening_en = %d\n",
25168923de59SPiotr Kubaj 			  prefix, caps->dyn_flattening_en);
25178923de59SPiotr Kubaj 		break;
25189c30461dSEric Joyner 	case ICE_AQC_CAPS_OROM_RECOVERY_UPDATE:
25199c30461dSEric Joyner 		caps->orom_recovery_update = (number == 1);
25209c30461dSEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "%s: orom_recovery_update = %d\n",
25219c30461dSEric Joyner 			  prefix, caps->orom_recovery_update);
25229c30461dSEric Joyner 		break;
252371d10453SEric Joyner 	default:
25247d7af7f8SEric Joyner 		/* Not one of the recognized common capabilities */
25257d7af7f8SEric Joyner 		found = false;
252671d10453SEric Joyner 	}
252771d10453SEric Joyner 
25287d7af7f8SEric Joyner 	return found;
25297d7af7f8SEric Joyner }
253071d10453SEric Joyner 
25317d7af7f8SEric Joyner /**
25327d7af7f8SEric Joyner  * ice_recalc_port_limited_caps - Recalculate port limited capabilities
25337d7af7f8SEric Joyner  * @hw: pointer to the HW structure
25347d7af7f8SEric Joyner  * @caps: pointer to capabilities structure to fix
25357d7af7f8SEric Joyner  *
25367d7af7f8SEric Joyner  * Re-calculate the capabilities that are dependent on the number of physical
25377d7af7f8SEric Joyner  * ports; i.e. some features are not supported or function differently on
25387d7af7f8SEric Joyner  * devices with more than 4 ports.
25397d7af7f8SEric Joyner  */
25407d7af7f8SEric Joyner static void
25417d7af7f8SEric Joyner ice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
25427d7af7f8SEric Joyner {
25437d7af7f8SEric Joyner 	/* This assumes device capabilities are always scanned before function
25447d7af7f8SEric Joyner 	 * capabilities during the initialization flow.
254571d10453SEric Joyner 	 */
254671d10453SEric Joyner 	if (hw->dev_caps.num_funcs > 4) {
254771d10453SEric Joyner 		/* Max 4 TCs per port */
254871d10453SEric Joyner 		caps->maxtc = 4;
25497d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %d (based on #ports)\n",
255071d10453SEric Joyner 			  caps->maxtc);
25518a13362dSEric Joyner 		if (caps->iwarp) {
25528a13362dSEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "forcing RDMA off\n");
25538a13362dSEric Joyner 			caps->iwarp = 0;
25548a13362dSEric Joyner 		}
25558a13362dSEric Joyner 
25568a13362dSEric Joyner 		/* print message only when processing device capabilities
25578a13362dSEric Joyner 		 * during initialization.
25588a13362dSEric Joyner 		 */
25598a13362dSEric Joyner 		if (caps == &hw->dev_caps.common_cap)
25608a13362dSEric Joyner 			ice_info(hw, "RDMA functionality is not available with the current device configuration.\n");
256171d10453SEric Joyner 	}
256271d10453SEric Joyner }
256371d10453SEric Joyner 
256471d10453SEric Joyner /**
25657d7af7f8SEric Joyner  * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
256671d10453SEric Joyner  * @hw: pointer to the HW struct
25677d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
25687d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
25697d7af7f8SEric Joyner  *
25707d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VF.
25717d7af7f8SEric Joyner  */
25727d7af7f8SEric Joyner static void
25737d7af7f8SEric Joyner ice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
25747d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
25757d7af7f8SEric Joyner {
25767d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
25777d7af7f8SEric Joyner 	u32 logical_id = LE32_TO_CPU(cap->logical_id);
25787d7af7f8SEric Joyner 
25797d7af7f8SEric Joyner 	func_p->num_allocd_vfs = number;
25807d7af7f8SEric Joyner 	func_p->vf_base_id = logical_id;
25817d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n",
25827d7af7f8SEric Joyner 		  func_p->num_allocd_vfs);
25837d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n",
25847d7af7f8SEric Joyner 		  func_p->vf_base_id);
25857d7af7f8SEric Joyner }
25867d7af7f8SEric Joyner 
25877d7af7f8SEric Joyner /**
25887d7af7f8SEric Joyner  * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
25897d7af7f8SEric Joyner  * @hw: pointer to the HW struct
25907d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
25917d7af7f8SEric Joyner  * @cap: pointer to the capability element to parse
25927d7af7f8SEric Joyner  *
25937d7af7f8SEric Joyner  * Extract function capabilities for ICE_AQC_CAPS_VSI.
25947d7af7f8SEric Joyner  */
25957d7af7f8SEric Joyner static void
25967d7af7f8SEric Joyner ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
25977d7af7f8SEric Joyner 			struct ice_aqc_list_caps_elem *cap)
25987d7af7f8SEric Joyner {
25997d7af7f8SEric Joyner 	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
26007d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n",
26017d7af7f8SEric Joyner 		  LE32_TO_CPU(cap->number));
26027d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n",
26037d7af7f8SEric Joyner 		  func_p->guar_num_vsi);
26047d7af7f8SEric Joyner }
26057d7af7f8SEric Joyner 
26067d7af7f8SEric Joyner /**
26077d7af7f8SEric Joyner  * ice_parse_func_caps - Parse function capabilities
26087d7af7f8SEric Joyner  * @hw: pointer to the HW struct
26097d7af7f8SEric Joyner  * @func_p: pointer to function capabilities structure
26107d7af7f8SEric Joyner  * @buf: buffer containing the function capability records
26117d7af7f8SEric Joyner  * @cap_count: the number of capabilities
26127d7af7f8SEric Joyner  *
26137d7af7f8SEric Joyner  * Helper function to parse function (0x000A) capabilities list. For
26147d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
26157d7af7f8SEric Joyner  * ice_parse_common_caps.
26167d7af7f8SEric Joyner  *
26177d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
26187d7af7f8SEric Joyner  * data into the function capabilities structured.
26197d7af7f8SEric Joyner  */
26207d7af7f8SEric Joyner static void
26217d7af7f8SEric Joyner ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
26227d7af7f8SEric Joyner 		    void *buf, u32 cap_count)
26237d7af7f8SEric Joyner {
26247d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
26257d7af7f8SEric Joyner 	u32 i;
26267d7af7f8SEric Joyner 
26277d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
26287d7af7f8SEric Joyner 
26297d7af7f8SEric Joyner 	ice_memset(func_p, 0, sizeof(*func_p), ICE_NONDMA_MEM);
26307d7af7f8SEric Joyner 
26317d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
26327d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
26337d7af7f8SEric Joyner 		bool found;
26347d7af7f8SEric Joyner 
26357d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &func_p->common_cap,
26367d7af7f8SEric Joyner 					      &cap_resp[i], "func caps");
26377d7af7f8SEric Joyner 
26387d7af7f8SEric Joyner 		switch (cap) {
26397d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
26407d7af7f8SEric Joyner 			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
26417d7af7f8SEric Joyner 			break;
26427d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
26437d7af7f8SEric Joyner 			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
26447d7af7f8SEric Joyner 			break;
26457d7af7f8SEric Joyner 		default:
26467d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
26477d7af7f8SEric Joyner 			if (!found)
26487d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n",
26497d7af7f8SEric Joyner 					  i, cap);
26507d7af7f8SEric Joyner 			break;
26517d7af7f8SEric Joyner 		}
26527d7af7f8SEric Joyner 	}
26537d7af7f8SEric Joyner 
26547d7af7f8SEric Joyner 	ice_print_led_caps(hw, &func_p->common_cap, "func caps", true);
26557d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &func_p->common_cap, "func caps", true);
26567d7af7f8SEric Joyner 
26577d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
26587d7af7f8SEric Joyner }
26597d7af7f8SEric Joyner 
26607d7af7f8SEric Joyner /**
26617d7af7f8SEric Joyner  * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
26627d7af7f8SEric Joyner  * @hw: pointer to the HW struct
26637d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
26647d7af7f8SEric Joyner  * @cap: capability element to parse
26657d7af7f8SEric Joyner  *
26667d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
26677d7af7f8SEric Joyner  */
26687d7af7f8SEric Joyner static void
26697d7af7f8SEric Joyner ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
26707d7af7f8SEric Joyner 			      struct ice_aqc_list_caps_elem *cap)
26717d7af7f8SEric Joyner {
26727d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
26737d7af7f8SEric Joyner 
26747d7af7f8SEric Joyner 	dev_p->num_funcs = ice_hweight32(number);
26757d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
26767d7af7f8SEric Joyner 		  dev_p->num_funcs);
267756429daeSEric Joyner 
26787d7af7f8SEric Joyner }
26797d7af7f8SEric Joyner 
26807d7af7f8SEric Joyner /**
26817d7af7f8SEric Joyner  * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
26827d7af7f8SEric Joyner  * @hw: pointer to the HW struct
26837d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
26847d7af7f8SEric Joyner  * @cap: capability element to parse
26857d7af7f8SEric Joyner  *
26867d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VF for device capabilities.
26877d7af7f8SEric Joyner  */
26887d7af7f8SEric Joyner static void
26897d7af7f8SEric Joyner ice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
26907d7af7f8SEric Joyner 		      struct ice_aqc_list_caps_elem *cap)
26917d7af7f8SEric Joyner {
26927d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
26937d7af7f8SEric Joyner 
26947d7af7f8SEric Joyner 	dev_p->num_vfs_exposed = number;
26957d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n",
26967d7af7f8SEric Joyner 		  dev_p->num_vfs_exposed);
26977d7af7f8SEric Joyner }
26987d7af7f8SEric Joyner 
26997d7af7f8SEric Joyner /**
27007d7af7f8SEric Joyner  * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
27017d7af7f8SEric Joyner  * @hw: pointer to the HW struct
27027d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
27037d7af7f8SEric Joyner  * @cap: capability element to parse
27047d7af7f8SEric Joyner  *
27057d7af7f8SEric Joyner  * Parse ICE_AQC_CAPS_VSI for device capabilities.
27067d7af7f8SEric Joyner  */
27077d7af7f8SEric Joyner static void
27087d7af7f8SEric Joyner ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
27097d7af7f8SEric Joyner 		       struct ice_aqc_list_caps_elem *cap)
27107d7af7f8SEric Joyner {
27117d7af7f8SEric Joyner 	u32 number = LE32_TO_CPU(cap->number);
27127d7af7f8SEric Joyner 
27137d7af7f8SEric Joyner 	dev_p->num_vsi_allocd_to_host = number;
27147d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n",
27157d7af7f8SEric Joyner 		  dev_p->num_vsi_allocd_to_host);
27167d7af7f8SEric Joyner }
27177d7af7f8SEric Joyner 
27187d7af7f8SEric Joyner /**
27198923de59SPiotr Kubaj  * ice_parse_nac_topo_dev_caps - Parse ICE_AQC_CAPS_NAC_TOPOLOGY cap
27208923de59SPiotr Kubaj  * @hw: pointer to the HW struct
27218923de59SPiotr Kubaj  * @dev_p: pointer to device capabilities structure
27228923de59SPiotr Kubaj  * @cap: capability element to parse
27238923de59SPiotr Kubaj  *
27248923de59SPiotr Kubaj  * Parse ICE_AQC_CAPS_NAC_TOPOLOGY for device capabilities.
27258923de59SPiotr Kubaj  */
27268923de59SPiotr Kubaj static void
27278923de59SPiotr Kubaj ice_parse_nac_topo_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
27288923de59SPiotr Kubaj 			    struct ice_aqc_list_caps_elem *cap)
27298923de59SPiotr Kubaj {
27308923de59SPiotr Kubaj 	dev_p->nac_topo.mode = LE32_TO_CPU(cap->number);
27318923de59SPiotr Kubaj 	dev_p->nac_topo.id = LE32_TO_CPU(cap->phys_id) & ICE_NAC_TOPO_ID_M;
27328923de59SPiotr Kubaj 
2733*9e54973fSEric Joyner 	ice_info(hw, "PF is configured in %s mode with IP instance ID %d\n",
2734*9e54973fSEric Joyner 		 (dev_p->nac_topo.mode == 0) ? "primary" : "secondary",
2735*9e54973fSEric Joyner 		 dev_p->nac_topo.id);
2736*9e54973fSEric Joyner 
27378923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology is_primary = %d\n",
27388923de59SPiotr Kubaj 		  !!(dev_p->nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M));
27398923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology is_dual = %d\n",
27408923de59SPiotr Kubaj 		  !!(dev_p->nac_topo.mode & ICE_NAC_TOPO_DUAL_M));
27418923de59SPiotr Kubaj 	ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology id = %d\n",
27428923de59SPiotr Kubaj 		  dev_p->nac_topo.id);
27438923de59SPiotr Kubaj }
27448923de59SPiotr Kubaj 
27458923de59SPiotr Kubaj /**
27469c30461dSEric Joyner  * ice_parse_sensor_reading_cap - Parse ICE_AQC_CAPS_SENSOR_READING cap
27479c30461dSEric Joyner  * @hw: pointer to the HW struct
27489c30461dSEric Joyner  * @dev_p: pointer to device capabilities structure
27499c30461dSEric Joyner  * @cap: capability element to parse
27509c30461dSEric Joyner  *
27519c30461dSEric Joyner  * Parse ICE_AQC_CAPS_SENSOR_READING for device capability for reading
27529c30461dSEric Joyner  * enabled sensors.
27539c30461dSEric Joyner  */
27549c30461dSEric Joyner static void
27559c30461dSEric Joyner ice_parse_sensor_reading_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
27569c30461dSEric Joyner 			     struct ice_aqc_list_caps_elem *cap)
27579c30461dSEric Joyner {
27589c30461dSEric Joyner 	dev_p->supported_sensors = LE32_TO_CPU(cap->number);
27599c30461dSEric Joyner 
27609c30461dSEric Joyner 	ice_debug(hw, ICE_DBG_INIT,
27619c30461dSEric Joyner 		  "dev caps: supported sensors (bitmap) = 0x%x\n",
27629c30461dSEric Joyner 		  dev_p->supported_sensors);
27639c30461dSEric Joyner }
27649c30461dSEric Joyner 
27659c30461dSEric Joyner /**
27667d7af7f8SEric Joyner  * ice_parse_dev_caps - Parse device capabilities
27677d7af7f8SEric Joyner  * @hw: pointer to the HW struct
27687d7af7f8SEric Joyner  * @dev_p: pointer to device capabilities structure
27697d7af7f8SEric Joyner  * @buf: buffer containing the device capability records
27707d7af7f8SEric Joyner  * @cap_count: the number of capabilities
27717d7af7f8SEric Joyner  *
27727d7af7f8SEric Joyner  * Helper device to parse device (0x000B) capabilities list. For
27737d7af7f8SEric Joyner  * capabilities shared between device and function, this relies on
27747d7af7f8SEric Joyner  * ice_parse_common_caps.
27757d7af7f8SEric Joyner  *
27767d7af7f8SEric Joyner  * Loop through the list of provided capabilities and extract the relevant
27777d7af7f8SEric Joyner  * data into the device capabilities structured.
27787d7af7f8SEric Joyner  */
27797d7af7f8SEric Joyner static void
27807d7af7f8SEric Joyner ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
27817d7af7f8SEric Joyner 		   void *buf, u32 cap_count)
27827d7af7f8SEric Joyner {
27837d7af7f8SEric Joyner 	struct ice_aqc_list_caps_elem *cap_resp;
27847d7af7f8SEric Joyner 	u32 i;
27857d7af7f8SEric Joyner 
27867d7af7f8SEric Joyner 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
27877d7af7f8SEric Joyner 
27887d7af7f8SEric Joyner 	ice_memset(dev_p, 0, sizeof(*dev_p), ICE_NONDMA_MEM);
27897d7af7f8SEric Joyner 
27907d7af7f8SEric Joyner 	for (i = 0; i < cap_count; i++) {
27917d7af7f8SEric Joyner 		u16 cap = LE16_TO_CPU(cap_resp[i].cap);
27927d7af7f8SEric Joyner 		bool found;
27937d7af7f8SEric Joyner 
27947d7af7f8SEric Joyner 		found = ice_parse_common_caps(hw, &dev_p->common_cap,
27957d7af7f8SEric Joyner 					      &cap_resp[i], "dev caps");
27967d7af7f8SEric Joyner 
27977d7af7f8SEric Joyner 		switch (cap) {
27987d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VALID_FUNCTIONS:
27997d7af7f8SEric Joyner 			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
28007d7af7f8SEric Joyner 			break;
28017d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VF:
28027d7af7f8SEric Joyner 			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
28037d7af7f8SEric Joyner 			break;
28047d7af7f8SEric Joyner 		case ICE_AQC_CAPS_VSI:
28057d7af7f8SEric Joyner 			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
28067d7af7f8SEric Joyner 			break;
28078923de59SPiotr Kubaj 		case ICE_AQC_CAPS_NAC_TOPOLOGY:
28088923de59SPiotr Kubaj 			ice_parse_nac_topo_dev_caps(hw, dev_p, &cap_resp[i]);
28098923de59SPiotr Kubaj 			break;
28109c30461dSEric Joyner 		case ICE_AQC_CAPS_SENSOR_READING:
28119c30461dSEric Joyner 			ice_parse_sensor_reading_cap(hw, dev_p, &cap_resp[i]);
28129c30461dSEric Joyner 			break;
28137d7af7f8SEric Joyner 		default:
28147d7af7f8SEric Joyner 			/* Don't list common capabilities as unknown */
28157d7af7f8SEric Joyner 			if (!found)
28167d7af7f8SEric Joyner 				ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%d]: 0x%x\n",
28177d7af7f8SEric Joyner 					  i, cap);
28187d7af7f8SEric Joyner 			break;
28197d7af7f8SEric Joyner 		}
28207d7af7f8SEric Joyner 	}
28217d7af7f8SEric Joyner 
28227d7af7f8SEric Joyner 	ice_print_led_caps(hw, &dev_p->common_cap, "dev caps", true);
28237d7af7f8SEric Joyner 	ice_print_sdp_caps(hw, &dev_p->common_cap, "dev caps", true);
28247d7af7f8SEric Joyner 
28257d7af7f8SEric Joyner 	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
28267d7af7f8SEric Joyner }
28277d7af7f8SEric Joyner 
28287d7af7f8SEric Joyner /**
28297d7af7f8SEric Joyner  * ice_aq_list_caps - query function/device capabilities
28307d7af7f8SEric Joyner  * @hw: pointer to the HW struct
28317d7af7f8SEric Joyner  * @buf: a buffer to hold the capabilities
28327d7af7f8SEric Joyner  * @buf_size: size of the buffer
28337d7af7f8SEric Joyner  * @cap_count: if not NULL, set to the number of capabilities reported
28347d7af7f8SEric Joyner  * @opc: capabilities type to discover, device or function
283571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
283671d10453SEric Joyner  *
28377d7af7f8SEric Joyner  * Get the function (0x000A) or device (0x000B) capabilities description from
28387d7af7f8SEric Joyner  * firmware and store it in the buffer.
28397d7af7f8SEric Joyner  *
28407d7af7f8SEric Joyner  * If the cap_count pointer is not NULL, then it is set to the number of
28417d7af7f8SEric Joyner  * capabilities firmware will report. Note that if the buffer size is too
28427d7af7f8SEric Joyner  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
28437d7af7f8SEric Joyner  * cap_count will still be updated in this case. It is recommended that the
28447d7af7f8SEric Joyner  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
28457d7af7f8SEric Joyner  * firmware could return) to avoid this.
284671d10453SEric Joyner  */
28477d7af7f8SEric Joyner static enum ice_status
28487d7af7f8SEric Joyner ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
284971d10453SEric Joyner 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
285071d10453SEric Joyner {
285171d10453SEric Joyner 	struct ice_aqc_list_caps *cmd;
285271d10453SEric Joyner 	struct ice_aq_desc desc;
285371d10453SEric Joyner 	enum ice_status status;
285471d10453SEric Joyner 
285571d10453SEric Joyner 	cmd = &desc.params.get_cap;
285671d10453SEric Joyner 
285771d10453SEric Joyner 	if (opc != ice_aqc_opc_list_func_caps &&
285871d10453SEric Joyner 	    opc != ice_aqc_opc_list_dev_caps)
285971d10453SEric Joyner 		return ICE_ERR_PARAM;
286071d10453SEric Joyner 
286171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
286271d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
28637d7af7f8SEric Joyner 
28647d7af7f8SEric Joyner 	if (cap_count)
286571d10453SEric Joyner 		*cap_count = LE32_TO_CPU(cmd->count);
28667d7af7f8SEric Joyner 
286771d10453SEric Joyner 	return status;
286871d10453SEric Joyner }
286971d10453SEric Joyner 
287071d10453SEric Joyner /**
28717d7af7f8SEric Joyner  * ice_discover_dev_caps - Read and extract device capabilities
287271d10453SEric Joyner  * @hw: pointer to the hardware structure
28737d7af7f8SEric Joyner  * @dev_caps: pointer to device capabilities structure
28747d7af7f8SEric Joyner  *
28757d7af7f8SEric Joyner  * Read the device capabilities and extract them into the dev_caps structure
28767d7af7f8SEric Joyner  * for later use.
287771d10453SEric Joyner  */
287871d10453SEric Joyner static enum ice_status
28797d7af7f8SEric Joyner ice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
288071d10453SEric Joyner {
288171d10453SEric Joyner 	enum ice_status status;
28827d7af7f8SEric Joyner 	u32 cap_count = 0;
288371d10453SEric Joyner 	void *cbuf;
288471d10453SEric Joyner 
28857d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
288671d10453SEric Joyner 	if (!cbuf)
288771d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
288871d10453SEric Joyner 
28897d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
28907d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
28917d7af7f8SEric Joyner 	 * possible size that firmware can return.
28927d7af7f8SEric Joyner 	 */
28937d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
28947d7af7f8SEric Joyner 
28957d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
28967d7af7f8SEric Joyner 				  ice_aqc_opc_list_dev_caps, NULL);
28977d7af7f8SEric Joyner 	if (!status)
28987d7af7f8SEric Joyner 		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
289971d10453SEric Joyner 	ice_free(hw, cbuf);
290071d10453SEric Joyner 
29017d7af7f8SEric Joyner 	return status;
29027d7af7f8SEric Joyner }
290371d10453SEric Joyner 
29047d7af7f8SEric Joyner /**
29057d7af7f8SEric Joyner  * ice_discover_func_caps - Read and extract function capabilities
29067d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
29077d7af7f8SEric Joyner  * @func_caps: pointer to function capabilities structure
29087d7af7f8SEric Joyner  *
29097d7af7f8SEric Joyner  * Read the function capabilities and extract them into the func_caps structure
29107d7af7f8SEric Joyner  * for later use.
29117d7af7f8SEric Joyner  */
29127d7af7f8SEric Joyner static enum ice_status
29137d7af7f8SEric Joyner ice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
29147d7af7f8SEric Joyner {
29157d7af7f8SEric Joyner 	enum ice_status status;
29167d7af7f8SEric Joyner 	u32 cap_count = 0;
29177d7af7f8SEric Joyner 	void *cbuf;
29187d7af7f8SEric Joyner 
29197d7af7f8SEric Joyner 	cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
29207d7af7f8SEric Joyner 	if (!cbuf)
29217d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
29227d7af7f8SEric Joyner 
29237d7af7f8SEric Joyner 	/* Although the driver doesn't know the number of capabilities the
29247d7af7f8SEric Joyner 	 * device will return, we can simply send a 4KB buffer, the maximum
29257d7af7f8SEric Joyner 	 * possible size that firmware can return.
29267d7af7f8SEric Joyner 	 */
29277d7af7f8SEric Joyner 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
29287d7af7f8SEric Joyner 
29297d7af7f8SEric Joyner 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
29307d7af7f8SEric Joyner 				  ice_aqc_opc_list_func_caps, NULL);
29317d7af7f8SEric Joyner 	if (!status)
29327d7af7f8SEric Joyner 		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
29337d7af7f8SEric Joyner 	ice_free(hw, cbuf);
293471d10453SEric Joyner 
293571d10453SEric Joyner 	return status;
293671d10453SEric Joyner }
293771d10453SEric Joyner 
293871d10453SEric Joyner /**
293971d10453SEric Joyner  * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
294071d10453SEric Joyner  * @hw: pointer to the hardware structure
294171d10453SEric Joyner  */
294271d10453SEric Joyner void ice_set_safe_mode_caps(struct ice_hw *hw)
294371d10453SEric Joyner {
294471d10453SEric Joyner 	struct ice_hw_func_caps *func_caps = &hw->func_caps;
294571d10453SEric Joyner 	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
2946d08b8680SEric Joyner 	struct ice_hw_common_caps cached_caps;
294771d10453SEric Joyner 	u32 num_funcs;
294871d10453SEric Joyner 
294971d10453SEric Joyner 	/* cache some func_caps values that should be restored after memset */
2950d08b8680SEric Joyner 	cached_caps = func_caps->common_cap;
295171d10453SEric Joyner 
295271d10453SEric Joyner 	/* unset func capabilities */
295371d10453SEric Joyner 	memset(func_caps, 0, sizeof(*func_caps));
295471d10453SEric Joyner 
2955d08b8680SEric Joyner #define ICE_RESTORE_FUNC_CAP(name) \
2956d08b8680SEric Joyner 	func_caps->common_cap.name = cached_caps.name
2957d08b8680SEric Joyner 
295871d10453SEric Joyner 	/* restore cached values */
2959d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(valid_functions);
2960d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(txq_first_id);
2961d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(rxq_first_id);
2962d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
2963d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(max_mtu);
2964d08b8680SEric Joyner 	ICE_RESTORE_FUNC_CAP(nvm_unified_update);
296571d10453SEric Joyner 
296671d10453SEric Joyner 	/* one Tx and one Rx queue in safe mode */
296771d10453SEric Joyner 	func_caps->common_cap.num_rxq = 1;
296871d10453SEric Joyner 	func_caps->common_cap.num_txq = 1;
296971d10453SEric Joyner 
297071d10453SEric Joyner 	/* two MSIX vectors, one for traffic and one for misc causes */
297171d10453SEric Joyner 	func_caps->common_cap.num_msix_vectors = 2;
297271d10453SEric Joyner 	func_caps->guar_num_vsi = 1;
297371d10453SEric Joyner 
297471d10453SEric Joyner 	/* cache some dev_caps values that should be restored after memset */
2975d08b8680SEric Joyner 	cached_caps = dev_caps->common_cap;
297671d10453SEric Joyner 	num_funcs = dev_caps->num_funcs;
297771d10453SEric Joyner 
297871d10453SEric Joyner 	/* unset dev capabilities */
297971d10453SEric Joyner 	memset(dev_caps, 0, sizeof(*dev_caps));
298071d10453SEric Joyner 
2981d08b8680SEric Joyner #define ICE_RESTORE_DEV_CAP(name) \
2982d08b8680SEric Joyner 	dev_caps->common_cap.name = cached_caps.name
2983d08b8680SEric Joyner 
298471d10453SEric Joyner 	/* restore cached values */
2985d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(valid_functions);
2986d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(txq_first_id);
2987d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(rxq_first_id);
2988d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(msix_vector_first_id);
2989d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(max_mtu);
2990d08b8680SEric Joyner 	ICE_RESTORE_DEV_CAP(nvm_unified_update);
299171d10453SEric Joyner 	dev_caps->num_funcs = num_funcs;
299271d10453SEric Joyner 
299371d10453SEric Joyner 	/* one Tx and one Rx queue per function in safe mode */
299471d10453SEric Joyner 	dev_caps->common_cap.num_rxq = num_funcs;
299571d10453SEric Joyner 	dev_caps->common_cap.num_txq = num_funcs;
299671d10453SEric Joyner 
299771d10453SEric Joyner 	/* two MSIX vectors per function */
299871d10453SEric Joyner 	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
299971d10453SEric Joyner }
300071d10453SEric Joyner 
300171d10453SEric Joyner /**
300271d10453SEric Joyner  * ice_get_caps - get info about the HW
300371d10453SEric Joyner  * @hw: pointer to the hardware structure
300471d10453SEric Joyner  */
300571d10453SEric Joyner enum ice_status ice_get_caps(struct ice_hw *hw)
300671d10453SEric Joyner {
300771d10453SEric Joyner 	enum ice_status status;
300871d10453SEric Joyner 
30097d7af7f8SEric Joyner 	status = ice_discover_dev_caps(hw, &hw->dev_caps);
30107d7af7f8SEric Joyner 	if (status)
301171d10453SEric Joyner 		return status;
30127d7af7f8SEric Joyner 
30137d7af7f8SEric Joyner 	return ice_discover_func_caps(hw, &hw->func_caps);
301471d10453SEric Joyner }
301571d10453SEric Joyner 
301671d10453SEric Joyner /**
301771d10453SEric Joyner  * ice_aq_manage_mac_write - manage MAC address write command
301871d10453SEric Joyner  * @hw: pointer to the HW struct
301971d10453SEric Joyner  * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
302071d10453SEric Joyner  * @flags: flags to control write behavior
302171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
302271d10453SEric Joyner  *
302371d10453SEric Joyner  * This function is used to write MAC address to the NVM (0x0108).
302471d10453SEric Joyner  */
302571d10453SEric Joyner enum ice_status
302671d10453SEric Joyner ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
302771d10453SEric Joyner 			struct ice_sq_cd *cd)
302871d10453SEric Joyner {
302971d10453SEric Joyner 	struct ice_aqc_manage_mac_write *cmd;
303071d10453SEric Joyner 	struct ice_aq_desc desc;
303171d10453SEric Joyner 
303271d10453SEric Joyner 	cmd = &desc.params.mac_write;
303371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
303471d10453SEric Joyner 
303571d10453SEric Joyner 	cmd->flags = flags;
3036d08b8680SEric Joyner 	ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_NONDMA);
303771d10453SEric Joyner 
303871d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
303971d10453SEric Joyner }
304071d10453SEric Joyner 
304171d10453SEric Joyner /**
304271d10453SEric Joyner  * ice_aq_clear_pxe_mode
304371d10453SEric Joyner  * @hw: pointer to the HW struct
304471d10453SEric Joyner  *
304571d10453SEric Joyner  * Tell the firmware that the driver is taking over from PXE (0x0110).
304671d10453SEric Joyner  */
304771d10453SEric Joyner static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw)
304871d10453SEric Joyner {
304971d10453SEric Joyner 	struct ice_aq_desc desc;
305071d10453SEric Joyner 
305171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
305271d10453SEric Joyner 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
305371d10453SEric Joyner 
305471d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
305571d10453SEric Joyner }
305671d10453SEric Joyner 
305771d10453SEric Joyner /**
305871d10453SEric Joyner  * ice_clear_pxe_mode - clear pxe operations mode
305971d10453SEric Joyner  * @hw: pointer to the HW struct
306071d10453SEric Joyner  *
306171d10453SEric Joyner  * Make sure all PXE mode settings are cleared, including things
306271d10453SEric Joyner  * like descriptor fetch/write-back mode.
306371d10453SEric Joyner  */
306471d10453SEric Joyner void ice_clear_pxe_mode(struct ice_hw *hw)
306571d10453SEric Joyner {
306671d10453SEric Joyner 	if (ice_check_sq_alive(hw, &hw->adminq))
306771d10453SEric Joyner 		ice_aq_clear_pxe_mode(hw);
306871d10453SEric Joyner }
306971d10453SEric Joyner 
307071d10453SEric Joyner /**
3071*9e54973fSEric Joyner  * ice_aq_set_port_params - set physical port parameters
307271d10453SEric Joyner  * @pi: pointer to the port info struct
307371d10453SEric Joyner  * @bad_frame_vsi: defines the VSI to which bad frames are forwarded
307471d10453SEric Joyner  * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI
307571d10453SEric Joyner  * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded
307671d10453SEric Joyner  * @double_vlan: if set double VLAN is enabled
307771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
307871d10453SEric Joyner  *
307971d10453SEric Joyner  * Set Physical port parameters (0x0203)
308071d10453SEric Joyner  */
308171d10453SEric Joyner enum ice_status
308271d10453SEric Joyner ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
308371d10453SEric Joyner 		       bool save_bad_pac, bool pad_short_pac, bool double_vlan,
308471d10453SEric Joyner 		       struct ice_sq_cd *cd)
308571d10453SEric Joyner {
308671d10453SEric Joyner 	struct ice_aqc_set_port_params *cmd;
308771d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
308871d10453SEric Joyner 	struct ice_aq_desc desc;
308971d10453SEric Joyner 	u16 cmd_flags = 0;
309071d10453SEric Joyner 
309171d10453SEric Joyner 	cmd = &desc.params.set_port_params;
309271d10453SEric Joyner 
309371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
309471d10453SEric Joyner 	cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi);
309571d10453SEric Joyner 	if (save_bad_pac)
309671d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS;
309771d10453SEric Joyner 	if (pad_short_pac)
309871d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS;
309971d10453SEric Joyner 	if (double_vlan)
310071d10453SEric Joyner 		cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
310171d10453SEric Joyner 	cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
310271d10453SEric Joyner 
310371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
310471d10453SEric Joyner }
310571d10453SEric Joyner 
310671d10453SEric Joyner /**
310756429daeSEric Joyner  * ice_is_100m_speed_supported
310856429daeSEric Joyner  * @hw: pointer to the HW struct
310956429daeSEric Joyner  *
311056429daeSEric Joyner  * returns true if 100M speeds are supported by the device,
311156429daeSEric Joyner  * false otherwise.
311256429daeSEric Joyner  */
311356429daeSEric Joyner bool ice_is_100m_speed_supported(struct ice_hw *hw)
311456429daeSEric Joyner {
311556429daeSEric Joyner 	switch (hw->device_id) {
311656429daeSEric Joyner 	case ICE_DEV_ID_E822C_SGMII:
311756429daeSEric Joyner 	case ICE_DEV_ID_E822L_SGMII:
311856429daeSEric Joyner 	case ICE_DEV_ID_E823L_1GBE:
31198923de59SPiotr Kubaj 	case ICE_DEV_ID_E823C_SGMII:
312056429daeSEric Joyner 		return true;
312156429daeSEric Joyner 	default:
312256429daeSEric Joyner 		return false;
312356429daeSEric Joyner 	}
312456429daeSEric Joyner }
312556429daeSEric Joyner 
312656429daeSEric Joyner /**
312771d10453SEric Joyner  * ice_get_link_speed_based_on_phy_type - returns link speed
312871d10453SEric Joyner  * @phy_type_low: lower part of phy_type
312971d10453SEric Joyner  * @phy_type_high: higher part of phy_type
313071d10453SEric Joyner  *
313171d10453SEric Joyner  * This helper function will convert an entry in PHY type structure
313271d10453SEric Joyner  * [phy_type_low, phy_type_high] to its corresponding link speed.
313371d10453SEric Joyner  * Note: In the structure of [phy_type_low, phy_type_high], there should
313471d10453SEric Joyner  * be one bit set, as this function will convert one PHY type to its
313571d10453SEric Joyner  * speed.
31369dc2f6e2SEric Joyner  * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
31379dc2f6e2SEric Joyner  * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
313871d10453SEric Joyner  */
313971d10453SEric Joyner static u16
314071d10453SEric Joyner ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
314171d10453SEric Joyner {
314271d10453SEric Joyner 	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
314371d10453SEric Joyner 	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
314471d10453SEric Joyner 
314571d10453SEric Joyner 	switch (phy_type_low) {
314671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100BASE_TX:
314771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100M_SGMII:
314871d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
314971d10453SEric Joyner 		break;
315071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_T:
315171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_SX:
315271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_LX:
315371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1000BASE_KX:
315471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_1G_SGMII:
315571d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
315671d10453SEric Joyner 		break;
315771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_T:
315871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_X:
315971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_2500BASE_KX:
316071d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
316171d10453SEric Joyner 		break;
316271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_T:
316371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_5GBASE_KR:
316471d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
316571d10453SEric Joyner 		break;
316671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_T:
316771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
316871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_SR:
316971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_LR:
317071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
317171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
317271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
317371d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
317471d10453SEric Joyner 		break;
317571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_T:
317671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR:
317771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
317871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
317971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_SR:
318071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_LR:
318171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR:
318271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
318371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
318471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
318571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
318671d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
318771d10453SEric Joyner 		break;
318871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
318971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
319071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
319171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
319271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
319371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_40G_XLAUI:
319471d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
319571d10453SEric Joyner 		break;
319671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
319771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
319871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
319971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
320071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
320171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_LAUI2:
320271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
320371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI2:
320471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_CP:
320571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_SR:
320671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_FR:
320771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_LR:
320871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
320971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
321071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_50G_AUI1:
321171d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
321271d10453SEric Joyner 		break;
321371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
321471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
321571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
321671d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
321771d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
321871d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_CAUI4:
321971d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
322071d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100G_AUI4:
322171d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
322271d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
322371d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
322471d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
322571d10453SEric Joyner 	case ICE_PHY_TYPE_LOW_100GBASE_DR:
322671d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
322771d10453SEric Joyner 		break;
322871d10453SEric Joyner 	default:
322971d10453SEric Joyner 		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
323071d10453SEric Joyner 		break;
323171d10453SEric Joyner 	}
323271d10453SEric Joyner 
323371d10453SEric Joyner 	switch (phy_type_high) {
323471d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
323571d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
323671d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
323771d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
323871d10453SEric Joyner 	case ICE_PHY_TYPE_HIGH_100G_AUI2:
323971d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
324071d10453SEric Joyner 		break;
324171d10453SEric Joyner 	default:
324271d10453SEric Joyner 		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
324371d10453SEric Joyner 		break;
324471d10453SEric Joyner 	}
324571d10453SEric Joyner 
324671d10453SEric Joyner 	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
324771d10453SEric Joyner 	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
324871d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
324971d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
325071d10453SEric Joyner 		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
325171d10453SEric Joyner 		return ICE_AQ_LINK_SPEED_UNKNOWN;
325271d10453SEric Joyner 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
325371d10453SEric Joyner 		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
325471d10453SEric Joyner 		return speed_phy_type_low;
325571d10453SEric Joyner 	else
325671d10453SEric Joyner 		return speed_phy_type_high;
325771d10453SEric Joyner }
325871d10453SEric Joyner 
325971d10453SEric Joyner /**
326071d10453SEric Joyner  * ice_update_phy_type
326171d10453SEric Joyner  * @phy_type_low: pointer to the lower part of phy_type
326271d10453SEric Joyner  * @phy_type_high: pointer to the higher part of phy_type
326371d10453SEric Joyner  * @link_speeds_bitmap: targeted link speeds bitmap
326471d10453SEric Joyner  *
326571d10453SEric Joyner  * Note: For the link_speeds_bitmap structure, you can check it at
326671d10453SEric Joyner  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
326771d10453SEric Joyner  * link_speeds_bitmap include multiple speeds.
326871d10453SEric Joyner  *
326971d10453SEric Joyner  * Each entry in this [phy_type_low, phy_type_high] structure will
327071d10453SEric Joyner  * present a certain link speed. This helper function will turn on bits
327171d10453SEric Joyner  * in [phy_type_low, phy_type_high] structure based on the value of
327271d10453SEric Joyner  * link_speeds_bitmap input parameter.
327371d10453SEric Joyner  */
327471d10453SEric Joyner void
327571d10453SEric Joyner ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
327671d10453SEric Joyner 		    u16 link_speeds_bitmap)
327771d10453SEric Joyner {
327871d10453SEric Joyner 	u64 pt_high;
327971d10453SEric Joyner 	u64 pt_low;
328071d10453SEric Joyner 	int index;
328171d10453SEric Joyner 	u16 speed;
328271d10453SEric Joyner 
328371d10453SEric Joyner 	/* We first check with low part of phy_type */
328471d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
328571d10453SEric Joyner 		pt_low = BIT_ULL(index);
328671d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
328771d10453SEric Joyner 
328871d10453SEric Joyner 		if (link_speeds_bitmap & speed)
328971d10453SEric Joyner 			*phy_type_low |= BIT_ULL(index);
329071d10453SEric Joyner 	}
329171d10453SEric Joyner 
329271d10453SEric Joyner 	/* We then check with high part of phy_type */
329371d10453SEric Joyner 	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
329471d10453SEric Joyner 		pt_high = BIT_ULL(index);
329571d10453SEric Joyner 		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
329671d10453SEric Joyner 
329771d10453SEric Joyner 		if (link_speeds_bitmap & speed)
329871d10453SEric Joyner 			*phy_type_high |= BIT_ULL(index);
329971d10453SEric Joyner 	}
330071d10453SEric Joyner }
330171d10453SEric Joyner 
330271d10453SEric Joyner /**
330371d10453SEric Joyner  * ice_aq_set_phy_cfg
330471d10453SEric Joyner  * @hw: pointer to the HW struct
330571d10453SEric Joyner  * @pi: port info structure of the interested logical port
330671d10453SEric Joyner  * @cfg: structure with PHY configuration data to be set
330771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
330871d10453SEric Joyner  *
330971d10453SEric Joyner  * Set the various PHY configuration parameters supported on the Port.
331071d10453SEric Joyner  * One or more of the Set PHY config parameters may be ignored in an MFP
331171d10453SEric Joyner  * mode as the PF may not have the privilege to set some of the PHY Config
331271d10453SEric Joyner  * parameters. This status will be indicated by the command response (0x0601).
331371d10453SEric Joyner  */
331471d10453SEric Joyner enum ice_status
331571d10453SEric Joyner ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
331671d10453SEric Joyner 		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
331771d10453SEric Joyner {
331871d10453SEric Joyner 	struct ice_aq_desc desc;
331971d10453SEric Joyner 	enum ice_status status;
332071d10453SEric Joyner 
332171d10453SEric Joyner 	if (!cfg)
332271d10453SEric Joyner 		return ICE_ERR_PARAM;
332371d10453SEric Joyner 
332471d10453SEric Joyner 	/* Ensure that only valid bits of cfg->caps can be turned on. */
332571d10453SEric Joyner 	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
33267d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
332771d10453SEric Joyner 			  cfg->caps);
332871d10453SEric Joyner 
332971d10453SEric Joyner 		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
333071d10453SEric Joyner 	}
333171d10453SEric Joyner 
333271d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
333371d10453SEric Joyner 	desc.params.set_phy.lport_num = pi->lport;
333471d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
333571d10453SEric Joyner 
33367d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
333771d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
333871d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_low));
333971d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
334071d10453SEric Joyner 		  (unsigned long long)LE64_TO_CPU(cfg->phy_type_high));
334171d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", cfg->caps);
334271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
334371d10453SEric Joyner 		  cfg->low_power_ctrl_an);
334471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", cfg->eee_cap);
334571d10453SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n", cfg->eeer_value);
33467d7af7f8SEric Joyner 	ice_debug(hw, ICE_DBG_LINK, "	link_fec_opt = 0x%x\n",
33477d7af7f8SEric Joyner 		  cfg->link_fec_opt);
334871d10453SEric Joyner 
334971d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
335071d10453SEric Joyner 
33517d7af7f8SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
33527d7af7f8SEric Joyner 		status = ICE_SUCCESS;
33537d7af7f8SEric Joyner 
335471d10453SEric Joyner 	if (!status)
335571d10453SEric Joyner 		pi->phy.curr_user_phy_cfg = *cfg;
335671d10453SEric Joyner 
335771d10453SEric Joyner 	return status;
335871d10453SEric Joyner }
335971d10453SEric Joyner 
336071d10453SEric Joyner /**
336171d10453SEric Joyner  * ice_update_link_info - update status of the HW network link
336271d10453SEric Joyner  * @pi: port info structure of the interested logical port
336371d10453SEric Joyner  */
336471d10453SEric Joyner enum ice_status ice_update_link_info(struct ice_port_info *pi)
336571d10453SEric Joyner {
336671d10453SEric Joyner 	struct ice_link_status *li;
336771d10453SEric Joyner 	enum ice_status status;
336871d10453SEric Joyner 
336971d10453SEric Joyner 	if (!pi)
337071d10453SEric Joyner 		return ICE_ERR_PARAM;
337171d10453SEric Joyner 
337271d10453SEric Joyner 	li = &pi->phy.link_info;
337371d10453SEric Joyner 
337471d10453SEric Joyner 	status = ice_aq_get_link_info(pi, true, NULL, NULL);
337571d10453SEric Joyner 	if (status)
337671d10453SEric Joyner 		return status;
337771d10453SEric Joyner 
337871d10453SEric Joyner 	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
337971d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
338071d10453SEric Joyner 		struct ice_hw *hw;
338171d10453SEric Joyner 
338271d10453SEric Joyner 		hw = pi->hw;
338371d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
338471d10453SEric Joyner 			ice_malloc(hw, sizeof(*pcaps));
338571d10453SEric Joyner 		if (!pcaps)
338671d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
338771d10453SEric Joyner 
33889cf1841cSEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
338971d10453SEric Joyner 					     pcaps, NULL);
339071d10453SEric Joyner 
3391d08b8680SEric Joyner 		if (status == ICE_SUCCESS)
3392d08b8680SEric Joyner 			ice_memcpy(li->module_type, &pcaps->module_type,
3393d08b8680SEric Joyner 				   sizeof(li->module_type),
3394d08b8680SEric Joyner 				   ICE_NONDMA_TO_NONDMA);
3395d08b8680SEric Joyner 
339671d10453SEric Joyner 		ice_free(hw, pcaps);
339771d10453SEric Joyner 	}
339871d10453SEric Joyner 
339971d10453SEric Joyner 	return status;
340071d10453SEric Joyner }
340171d10453SEric Joyner 
340271d10453SEric Joyner /**
340371d10453SEric Joyner  * ice_cache_phy_user_req
340471d10453SEric Joyner  * @pi: port information structure
340571d10453SEric Joyner  * @cache_data: PHY logging data
340671d10453SEric Joyner  * @cache_mode: PHY logging mode
340771d10453SEric Joyner  *
340871d10453SEric Joyner  * Log the user request on (FC, FEC, SPEED) for later user.
340971d10453SEric Joyner  */
341071d10453SEric Joyner static void
341171d10453SEric Joyner ice_cache_phy_user_req(struct ice_port_info *pi,
341271d10453SEric Joyner 		       struct ice_phy_cache_mode_data cache_data,
341371d10453SEric Joyner 		       enum ice_phy_cache_mode cache_mode)
341471d10453SEric Joyner {
341571d10453SEric Joyner 	if (!pi)
341671d10453SEric Joyner 		return;
341771d10453SEric Joyner 
341871d10453SEric Joyner 	switch (cache_mode) {
341971d10453SEric Joyner 	case ICE_FC_MODE:
342071d10453SEric Joyner 		pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
342171d10453SEric Joyner 		break;
342271d10453SEric Joyner 	case ICE_SPEED_MODE:
342371d10453SEric Joyner 		pi->phy.curr_user_speed_req =
342471d10453SEric Joyner 			cache_data.data.curr_user_speed_req;
342571d10453SEric Joyner 		break;
342671d10453SEric Joyner 	case ICE_FEC_MODE:
342771d10453SEric Joyner 		pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
342871d10453SEric Joyner 		break;
342971d10453SEric Joyner 	default:
343071d10453SEric Joyner 		break;
343171d10453SEric Joyner 	}
343271d10453SEric Joyner }
343371d10453SEric Joyner 
343471d10453SEric Joyner /**
343571d10453SEric Joyner  * ice_caps_to_fc_mode
343671d10453SEric Joyner  * @caps: PHY capabilities
343771d10453SEric Joyner  *
343871d10453SEric Joyner  * Convert PHY FC capabilities to ice FC mode
343971d10453SEric Joyner  */
344071d10453SEric Joyner enum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
344171d10453SEric Joyner {
344271d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
344371d10453SEric Joyner 	    caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
344471d10453SEric Joyner 		return ICE_FC_FULL;
344571d10453SEric Joyner 
344671d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
344771d10453SEric Joyner 		return ICE_FC_TX_PAUSE;
344871d10453SEric Joyner 
344971d10453SEric Joyner 	if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
345071d10453SEric Joyner 		return ICE_FC_RX_PAUSE;
345171d10453SEric Joyner 
345271d10453SEric Joyner 	return ICE_FC_NONE;
345371d10453SEric Joyner }
345471d10453SEric Joyner 
345571d10453SEric Joyner /**
345671d10453SEric Joyner  * ice_caps_to_fec_mode
345771d10453SEric Joyner  * @caps: PHY capabilities
345871d10453SEric Joyner  * @fec_options: Link FEC options
345971d10453SEric Joyner  *
346071d10453SEric Joyner  * Convert PHY FEC capabilities to ice FEC mode
346171d10453SEric Joyner  */
346271d10453SEric Joyner enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
346371d10453SEric Joyner {
34648923de59SPiotr Kubaj 	if (caps & ICE_AQC_PHY_EN_AUTO_FEC) {
34658923de59SPiotr Kubaj 		if (fec_options & ICE_AQC_PHY_FEC_DIS)
34668923de59SPiotr Kubaj 			return ICE_FEC_DIS_AUTO;
34678923de59SPiotr Kubaj 		else
346871d10453SEric Joyner 			return ICE_FEC_AUTO;
34698923de59SPiotr Kubaj 	}
347071d10453SEric Joyner 
347171d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
347271d10453SEric Joyner 			   ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
347371d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
347471d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_KR_REQ))
347571d10453SEric Joyner 		return ICE_FEC_BASER;
347671d10453SEric Joyner 
347771d10453SEric Joyner 	if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
347871d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_544_REQ |
347971d10453SEric Joyner 			   ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
348071d10453SEric Joyner 		return ICE_FEC_RS;
348171d10453SEric Joyner 
348271d10453SEric Joyner 	return ICE_FEC_NONE;
348371d10453SEric Joyner }
348471d10453SEric Joyner 
348571d10453SEric Joyner /**
34867d7af7f8SEric Joyner  * ice_cfg_phy_fc - Configure PHY FC data based on FC mode
348771d10453SEric Joyner  * @pi: port information structure
34887d7af7f8SEric Joyner  * @cfg: PHY configuration data to set FC mode
34897d7af7f8SEric Joyner  * @req_mode: FC mode to configure
349071d10453SEric Joyner  */
34917d7af7f8SEric Joyner static enum ice_status
34927d7af7f8SEric Joyner ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
34937d7af7f8SEric Joyner 	       enum ice_fc_mode req_mode)
349471d10453SEric Joyner {
349571d10453SEric Joyner 	struct ice_phy_cache_mode_data cache_data;
34967d7af7f8SEric Joyner 	u8 pause_mask = 0x0;
34977d7af7f8SEric Joyner 
34987d7af7f8SEric Joyner 	if (!pi || !cfg)
34997d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
35007d7af7f8SEric Joyner 	switch (req_mode) {
35017d7af7f8SEric Joyner 	case ICE_FC_AUTO:
35027d7af7f8SEric Joyner 	{
350371d10453SEric Joyner 		struct ice_aqc_get_phy_caps_data *pcaps;
350471d10453SEric Joyner 		enum ice_status status;
350571d10453SEric Joyner 
350671d10453SEric Joyner 		pcaps = (struct ice_aqc_get_phy_caps_data *)
35077d7af7f8SEric Joyner 			ice_malloc(pi->hw, sizeof(*pcaps));
350871d10453SEric Joyner 		if (!pcaps)
350971d10453SEric Joyner 			return ICE_ERR_NO_MEMORY;
351071d10453SEric Joyner 		/* Query the value of FC that both the NIC and attached media
351171d10453SEric Joyner 		 * can do.
351271d10453SEric Joyner 		 */
35139cf1841cSEric Joyner 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
351471d10453SEric Joyner 					     pcaps, NULL);
351571d10453SEric Joyner 		if (status) {
35167d7af7f8SEric Joyner 			ice_free(pi->hw, pcaps);
35177d7af7f8SEric Joyner 			return status;
351871d10453SEric Joyner 		}
351971d10453SEric Joyner 
352071d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE;
352171d10453SEric Joyner 		pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE;
35227d7af7f8SEric Joyner 
35237d7af7f8SEric Joyner 		ice_free(pi->hw, pcaps);
352471d10453SEric Joyner 		break;
35257d7af7f8SEric Joyner 	}
352671d10453SEric Joyner 	case ICE_FC_FULL:
352771d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
352871d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
352971d10453SEric Joyner 		break;
353071d10453SEric Joyner 	case ICE_FC_RX_PAUSE:
353171d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
353271d10453SEric Joyner 		break;
353371d10453SEric Joyner 	case ICE_FC_TX_PAUSE:
353471d10453SEric Joyner 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
353571d10453SEric Joyner 		break;
353671d10453SEric Joyner 	default:
353771d10453SEric Joyner 		break;
353871d10453SEric Joyner 	}
353971d10453SEric Joyner 
35407d7af7f8SEric Joyner 	/* clear the old pause settings */
35417d7af7f8SEric Joyner 	cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
35427d7af7f8SEric Joyner 		ICE_AQC_PHY_EN_RX_LINK_PAUSE);
35437d7af7f8SEric Joyner 
35447d7af7f8SEric Joyner 	/* set the new capabilities */
35457d7af7f8SEric Joyner 	cfg->caps |= pause_mask;
35467d7af7f8SEric Joyner 
35477d7af7f8SEric Joyner 	/* Cache user FC request */
35487d7af7f8SEric Joyner 	cache_data.data.curr_user_fc_req = req_mode;
35497d7af7f8SEric Joyner 	ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
35507d7af7f8SEric Joyner 
35517d7af7f8SEric Joyner 	return ICE_SUCCESS;
35527d7af7f8SEric Joyner }
35537d7af7f8SEric Joyner 
35547d7af7f8SEric Joyner /**
35557d7af7f8SEric Joyner  * ice_set_fc
35567d7af7f8SEric Joyner  * @pi: port information structure
35577d7af7f8SEric Joyner  * @aq_failures: pointer to status code, specific to ice_set_fc routine
35587d7af7f8SEric Joyner  * @ena_auto_link_update: enable automatic link update
35597d7af7f8SEric Joyner  *
35607d7af7f8SEric Joyner  * Set the requested flow control mode.
35617d7af7f8SEric Joyner  */
35627d7af7f8SEric Joyner enum ice_status
35637d7af7f8SEric Joyner ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
35647d7af7f8SEric Joyner {
35657d7af7f8SEric Joyner 	struct ice_aqc_set_phy_cfg_data  cfg = { 0 };
35667d7af7f8SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
35677d7af7f8SEric Joyner 	enum ice_status status;
35687d7af7f8SEric Joyner 	struct ice_hw *hw;
35697d7af7f8SEric Joyner 
35707d7af7f8SEric Joyner 	if (!pi || !aq_failures)
35717d7af7f8SEric Joyner 		return ICE_ERR_BAD_PTR;
35727d7af7f8SEric Joyner 
35737d7af7f8SEric Joyner 	*aq_failures = 0;
35747d7af7f8SEric Joyner 	hw = pi->hw;
35757d7af7f8SEric Joyner 
35767d7af7f8SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
35777d7af7f8SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
35787d7af7f8SEric Joyner 	if (!pcaps)
35797d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
35807d7af7f8SEric Joyner 
358171d10453SEric Joyner 	/* Get the current PHY config */
35829cf1841cSEric Joyner 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG,
35839cf1841cSEric Joyner 				     pcaps, NULL);
35849cf1841cSEric Joyner 
358571d10453SEric Joyner 	if (status) {
358671d10453SEric Joyner 		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
358771d10453SEric Joyner 		goto out;
358871d10453SEric Joyner 	}
358971d10453SEric Joyner 
359071d10453SEric Joyner 	ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
359171d10453SEric Joyner 
35927d7af7f8SEric Joyner 	/* Configure the set PHY data */
35937d7af7f8SEric Joyner 	status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
35947d7af7f8SEric Joyner 	if (status) {
35957d7af7f8SEric Joyner 		if (status != ICE_ERR_BAD_PTR)
35967d7af7f8SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
359771d10453SEric Joyner 
35987d7af7f8SEric Joyner 		goto out;
35997d7af7f8SEric Joyner 	}
360071d10453SEric Joyner 
360171d10453SEric Joyner 	/* If the capabilities have changed, then set the new config */
360271d10453SEric Joyner 	if (cfg.caps != pcaps->caps) {
360371d10453SEric Joyner 		int retry_count, retry_max = 10;
360471d10453SEric Joyner 
360571d10453SEric Joyner 		/* Auto restart link so settings take effect */
360671d10453SEric Joyner 		if (ena_auto_link_update)
360771d10453SEric Joyner 			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
360871d10453SEric Joyner 
360971d10453SEric Joyner 		status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
361071d10453SEric Joyner 		if (status) {
361171d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
361271d10453SEric Joyner 			goto out;
361371d10453SEric Joyner 		}
361471d10453SEric Joyner 
361571d10453SEric Joyner 		/* Update the link info
361671d10453SEric Joyner 		 * It sometimes takes a really long time for link to
361771d10453SEric Joyner 		 * come back from the atomic reset. Thus, we wait a
361871d10453SEric Joyner 		 * little bit.
361971d10453SEric Joyner 		 */
362071d10453SEric Joyner 		for (retry_count = 0; retry_count < retry_max; retry_count++) {
362171d10453SEric Joyner 			status = ice_update_link_info(pi);
362271d10453SEric Joyner 
362371d10453SEric Joyner 			if (status == ICE_SUCCESS)
362471d10453SEric Joyner 				break;
362571d10453SEric Joyner 
362671d10453SEric Joyner 			ice_msec_delay(100, true);
362771d10453SEric Joyner 		}
362871d10453SEric Joyner 
362971d10453SEric Joyner 		if (status)
363071d10453SEric Joyner 			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
363171d10453SEric Joyner 	}
363271d10453SEric Joyner 
363371d10453SEric Joyner out:
363471d10453SEric Joyner 	ice_free(hw, pcaps);
363571d10453SEric Joyner 	return status;
363671d10453SEric Joyner }
363771d10453SEric Joyner 
363871d10453SEric Joyner /**
363971d10453SEric Joyner  * ice_phy_caps_equals_cfg
364071d10453SEric Joyner  * @phy_caps: PHY capabilities
364171d10453SEric Joyner  * @phy_cfg: PHY configuration
364271d10453SEric Joyner  *
364371d10453SEric Joyner  * Helper function to determine if PHY capabilities matches PHY
364471d10453SEric Joyner  * configuration
364571d10453SEric Joyner  */
364671d10453SEric Joyner bool
364771d10453SEric Joyner ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
364871d10453SEric Joyner 			struct ice_aqc_set_phy_cfg_data *phy_cfg)
364971d10453SEric Joyner {
365071d10453SEric Joyner 	u8 caps_mask, cfg_mask;
365171d10453SEric Joyner 
365271d10453SEric Joyner 	if (!phy_caps || !phy_cfg)
365371d10453SEric Joyner 		return false;
365471d10453SEric Joyner 
365571d10453SEric Joyner 	/* These bits are not common between capabilities and configuration.
365671d10453SEric Joyner 	 * Do not use them to determine equality.
365771d10453SEric Joyner 	 */
365871d10453SEric Joyner 	caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
365971d10453SEric Joyner 					      ICE_AQC_PHY_EN_MOD_QUAL);
366071d10453SEric Joyner 	cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
366171d10453SEric Joyner 
366271d10453SEric Joyner 	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
366371d10453SEric Joyner 	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
366471d10453SEric Joyner 	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
366571d10453SEric Joyner 	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
366671d10453SEric Joyner 	    phy_caps->eee_cap != phy_cfg->eee_cap ||
366771d10453SEric Joyner 	    phy_caps->eeer_value != phy_cfg->eeer_value ||
366871d10453SEric Joyner 	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
366971d10453SEric Joyner 		return false;
367071d10453SEric Joyner 
367171d10453SEric Joyner 	return true;
367271d10453SEric Joyner }
367371d10453SEric Joyner 
367471d10453SEric Joyner /**
367571d10453SEric Joyner  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
367671d10453SEric Joyner  * @pi: port information structure
367756429daeSEric Joyner  * @caps: PHY ability structure to copy data from
367871d10453SEric Joyner  * @cfg: PHY configuration structure to copy data to
367971d10453SEric Joyner  *
368071d10453SEric Joyner  * Helper function to copy AQC PHY get ability data to PHY set configuration
368171d10453SEric Joyner  * data structure
368271d10453SEric Joyner  */
368371d10453SEric Joyner void
368471d10453SEric Joyner ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
368571d10453SEric Joyner 			 struct ice_aqc_get_phy_caps_data *caps,
368671d10453SEric Joyner 			 struct ice_aqc_set_phy_cfg_data *cfg)
368771d10453SEric Joyner {
368871d10453SEric Joyner 	if (!pi || !caps || !cfg)
368971d10453SEric Joyner 		return;
369071d10453SEric Joyner 
369171d10453SEric Joyner 	ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
369271d10453SEric Joyner 	cfg->phy_type_low = caps->phy_type_low;
369371d10453SEric Joyner 	cfg->phy_type_high = caps->phy_type_high;
369471d10453SEric Joyner 	cfg->caps = caps->caps;
369571d10453SEric Joyner 	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
369671d10453SEric Joyner 	cfg->eee_cap = caps->eee_cap;
369771d10453SEric Joyner 	cfg->eeer_value = caps->eeer_value;
369871d10453SEric Joyner 	cfg->link_fec_opt = caps->link_fec_options;
369971d10453SEric Joyner 	cfg->module_compliance_enforcement =
370071d10453SEric Joyner 		caps->module_compliance_enforcement;
370171d10453SEric Joyner }
370271d10453SEric Joyner 
370371d10453SEric Joyner /**
370471d10453SEric Joyner  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
370571d10453SEric Joyner  * @pi: port information structure
370671d10453SEric Joyner  * @cfg: PHY configuration data to set FEC mode
370771d10453SEric Joyner  * @fec: FEC mode to configure
370871d10453SEric Joyner  */
370971d10453SEric Joyner enum ice_status
371071d10453SEric Joyner ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
371171d10453SEric Joyner 		enum ice_fec_mode fec)
371271d10453SEric Joyner {
371371d10453SEric Joyner 	struct ice_aqc_get_phy_caps_data *pcaps;
371471d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
371571d10453SEric Joyner 	struct ice_hw *hw;
371671d10453SEric Joyner 
371771d10453SEric Joyner 	if (!pi || !cfg)
371871d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
371971d10453SEric Joyner 
372071d10453SEric Joyner 	hw = pi->hw;
372171d10453SEric Joyner 
372271d10453SEric Joyner 	pcaps = (struct ice_aqc_get_phy_caps_data *)
372371d10453SEric Joyner 		ice_malloc(hw, sizeof(*pcaps));
372471d10453SEric Joyner 	if (!pcaps)
372571d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
372671d10453SEric Joyner 
37279cf1841cSEric Joyner 	status = ice_aq_get_phy_caps(pi, false,
37289cf1841cSEric Joyner 				     (ice_fw_supports_report_dflt_cfg(hw) ?
37299cf1841cSEric Joyner 				      ICE_AQC_REPORT_DFLT_CFG :
37309cf1841cSEric Joyner 				      ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);
37319cf1841cSEric Joyner 
373271d10453SEric Joyner 	if (status)
373371d10453SEric Joyner 		goto out;
373471d10453SEric Joyner 
37357d7af7f8SEric Joyner 	cfg->caps |= (pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC);
37367d7af7f8SEric Joyner 	cfg->link_fec_opt = pcaps->link_fec_options;
37377d7af7f8SEric Joyner 
373871d10453SEric Joyner 	switch (fec) {
373971d10453SEric Joyner 	case ICE_FEC_BASER:
374071d10453SEric Joyner 		/* Clear RS bits, and AND BASE-R ability
374171d10453SEric Joyner 		 * bits and OR request bits.
374271d10453SEric Joyner 		 */
374371d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
374471d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
374571d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
374671d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_KR_REQ;
374771d10453SEric Joyner 		break;
374871d10453SEric Joyner 	case ICE_FEC_RS:
374971d10453SEric Joyner 		/* Clear BASE-R bits, and AND RS ability
375071d10453SEric Joyner 		 * bits and OR request bits.
375171d10453SEric Joyner 		 */
375271d10453SEric Joyner 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
375371d10453SEric Joyner 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
375471d10453SEric Joyner 			ICE_AQC_PHY_FEC_25G_RS_544_REQ;
375571d10453SEric Joyner 		break;
375671d10453SEric Joyner 	case ICE_FEC_NONE:
375771d10453SEric Joyner 		/* Clear all FEC option bits. */
375871d10453SEric Joyner 		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
375971d10453SEric Joyner 		break;
37608923de59SPiotr Kubaj 	case ICE_FEC_DIS_AUTO:
37618923de59SPiotr Kubaj 		/* Set No FEC and auto FEC */
37629c30461dSEric Joyner 		if (!ice_fw_supports_fec_dis_auto(hw)) {
37639c30461dSEric Joyner 			status = ICE_ERR_NOT_SUPPORTED;
37649c30461dSEric Joyner 			goto out;
37659c30461dSEric Joyner 		}
37668923de59SPiotr Kubaj 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_DIS;
37678923de59SPiotr Kubaj 		/* fall-through */
376871d10453SEric Joyner 	case ICE_FEC_AUTO:
376971d10453SEric Joyner 		/* AND auto FEC bit, and all caps bits. */
377071d10453SEric Joyner 		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
377171d10453SEric Joyner 		cfg->link_fec_opt |= pcaps->link_fec_options;
377271d10453SEric Joyner 		break;
377371d10453SEric Joyner 	default:
377471d10453SEric Joyner 		status = ICE_ERR_PARAM;
377571d10453SEric Joyner 		break;
377671d10453SEric Joyner 	}
377771d10453SEric Joyner 
37789cf1841cSEric Joyner 	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw) &&
37799cf1841cSEric Joyner 	    !ice_fw_supports_report_dflt_cfg(pi->hw)) {
378071d10453SEric Joyner 		struct ice_link_default_override_tlv tlv;
378171d10453SEric Joyner 
378271d10453SEric Joyner 		if (ice_get_link_default_override(&tlv, pi))
378371d10453SEric Joyner 			goto out;
378471d10453SEric Joyner 
378571d10453SEric Joyner 		if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
378671d10453SEric Joyner 		    (tlv.options & ICE_LINK_OVERRIDE_EN))
378771d10453SEric Joyner 			cfg->link_fec_opt = tlv.fec_options;
378871d10453SEric Joyner 	}
378971d10453SEric Joyner 
379071d10453SEric Joyner out:
379171d10453SEric Joyner 	ice_free(hw, pcaps);
379271d10453SEric Joyner 
379371d10453SEric Joyner 	return status;
379471d10453SEric Joyner }
379571d10453SEric Joyner 
379671d10453SEric Joyner /**
379771d10453SEric Joyner  * ice_get_link_status - get status of the HW network link
379871d10453SEric Joyner  * @pi: port information structure
379971d10453SEric Joyner  * @link_up: pointer to bool (true/false = linkup/linkdown)
380071d10453SEric Joyner  *
380171d10453SEric Joyner  * Variable link_up is true if link is up, false if link is down.
380271d10453SEric Joyner  * The variable link_up is invalid if status is non zero. As a
380371d10453SEric Joyner  * result of this call, link status reporting becomes enabled
380471d10453SEric Joyner  */
380571d10453SEric Joyner enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up)
380671d10453SEric Joyner {
380771d10453SEric Joyner 	struct ice_phy_info *phy_info;
380871d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
380971d10453SEric Joyner 
381071d10453SEric Joyner 	if (!pi || !link_up)
381171d10453SEric Joyner 		return ICE_ERR_PARAM;
381271d10453SEric Joyner 
381371d10453SEric Joyner 	phy_info = &pi->phy;
381471d10453SEric Joyner 
381571d10453SEric Joyner 	if (phy_info->get_link_info) {
381671d10453SEric Joyner 		status = ice_update_link_info(pi);
381771d10453SEric Joyner 
381871d10453SEric Joyner 		if (status)
38197d7af7f8SEric Joyner 			ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n",
382071d10453SEric Joyner 				  status);
382171d10453SEric Joyner 	}
382271d10453SEric Joyner 
382371d10453SEric Joyner 	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
382471d10453SEric Joyner 
382571d10453SEric Joyner 	return status;
382671d10453SEric Joyner }
382771d10453SEric Joyner 
382871d10453SEric Joyner /**
382971d10453SEric Joyner  * ice_aq_set_link_restart_an
383071d10453SEric Joyner  * @pi: pointer to the port information structure
383171d10453SEric Joyner  * @ena_link: if true: enable link, if false: disable link
383271d10453SEric Joyner  * @cd: pointer to command details structure or NULL
383371d10453SEric Joyner  *
383471d10453SEric Joyner  * Sets up the link and restarts the Auto-Negotiation over the link.
383571d10453SEric Joyner  */
383671d10453SEric Joyner enum ice_status
383771d10453SEric Joyner ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
383871d10453SEric Joyner 			   struct ice_sq_cd *cd)
383971d10453SEric Joyner {
38409c30461dSEric Joyner 	enum ice_status status = ICE_ERR_AQ_ERROR;
384171d10453SEric Joyner 	struct ice_aqc_restart_an *cmd;
384271d10453SEric Joyner 	struct ice_aq_desc desc;
384371d10453SEric Joyner 
384471d10453SEric Joyner 	cmd = &desc.params.restart_an;
384571d10453SEric Joyner 
384671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
384771d10453SEric Joyner 
384871d10453SEric Joyner 	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
384971d10453SEric Joyner 	cmd->lport_num = pi->lport;
385071d10453SEric Joyner 	if (ena_link)
385171d10453SEric Joyner 		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
385271d10453SEric Joyner 	else
385371d10453SEric Joyner 		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
385471d10453SEric Joyner 
38559c30461dSEric Joyner 	status = ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
38569c30461dSEric Joyner 	if (status)
38579c30461dSEric Joyner 		return status;
38589c30461dSEric Joyner 
38599c30461dSEric Joyner 	if (ena_link)
38609c30461dSEric Joyner 		pi->phy.curr_user_phy_cfg.caps |= ICE_AQC_PHY_EN_LINK;
38619c30461dSEric Joyner 	else
38629c30461dSEric Joyner 		pi->phy.curr_user_phy_cfg.caps &= ~ICE_AQC_PHY_EN_LINK;
38639c30461dSEric Joyner 
38649c30461dSEric Joyner 	return ICE_SUCCESS;
386571d10453SEric Joyner }
386671d10453SEric Joyner 
386771d10453SEric Joyner /**
386871d10453SEric Joyner  * ice_aq_set_event_mask
386971d10453SEric Joyner  * @hw: pointer to the HW struct
387071d10453SEric Joyner  * @port_num: port number of the physical function
387171d10453SEric Joyner  * @mask: event mask to be set
387271d10453SEric Joyner  * @cd: pointer to command details structure or NULL
387371d10453SEric Joyner  *
387471d10453SEric Joyner  * Set event mask (0x0613)
387571d10453SEric Joyner  */
387671d10453SEric Joyner enum ice_status
387771d10453SEric Joyner ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
387871d10453SEric Joyner 		      struct ice_sq_cd *cd)
387971d10453SEric Joyner {
388071d10453SEric Joyner 	struct ice_aqc_set_event_mask *cmd;
388171d10453SEric Joyner 	struct ice_aq_desc desc;
388271d10453SEric Joyner 
388371d10453SEric Joyner 	cmd = &desc.params.set_event_mask;
388471d10453SEric Joyner 
388571d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
388671d10453SEric Joyner 
388771d10453SEric Joyner 	cmd->lport_num = port_num;
388871d10453SEric Joyner 
388971d10453SEric Joyner 	cmd->event_mask = CPU_TO_LE16(mask);
389071d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
389171d10453SEric Joyner }
389271d10453SEric Joyner 
389371d10453SEric Joyner /**
389471d10453SEric Joyner  * ice_aq_set_mac_loopback
389571d10453SEric Joyner  * @hw: pointer to the HW struct
389671d10453SEric Joyner  * @ena_lpbk: Enable or Disable loopback
389771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
389871d10453SEric Joyner  *
389971d10453SEric Joyner  * Enable/disable loopback on a given port
390071d10453SEric Joyner  */
390171d10453SEric Joyner enum ice_status
390271d10453SEric Joyner ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
390371d10453SEric Joyner {
390471d10453SEric Joyner 	struct ice_aqc_set_mac_lb *cmd;
390571d10453SEric Joyner 	struct ice_aq_desc desc;
390671d10453SEric Joyner 
390771d10453SEric Joyner 	cmd = &desc.params.set_mac_lb;
390871d10453SEric Joyner 
390971d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
391071d10453SEric Joyner 	if (ena_lpbk)
391171d10453SEric Joyner 		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
391271d10453SEric Joyner 
391371d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
391471d10453SEric Joyner }
391571d10453SEric Joyner 
391671d10453SEric Joyner /**
391771d10453SEric Joyner  * ice_aq_set_port_id_led
391871d10453SEric Joyner  * @pi: pointer to the port information
391971d10453SEric Joyner  * @is_orig_mode: is this LED set to original mode (by the net-list)
392071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
392171d10453SEric Joyner  *
392271d10453SEric Joyner  * Set LED value for the given port (0x06e9)
392371d10453SEric Joyner  */
392471d10453SEric Joyner enum ice_status
392571d10453SEric Joyner ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
392671d10453SEric Joyner 		       struct ice_sq_cd *cd)
392771d10453SEric Joyner {
392871d10453SEric Joyner 	struct ice_aqc_set_port_id_led *cmd;
392971d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
393071d10453SEric Joyner 	struct ice_aq_desc desc;
393171d10453SEric Joyner 
393271d10453SEric Joyner 	cmd = &desc.params.set_port_id_led;
393371d10453SEric Joyner 
393471d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
393571d10453SEric Joyner 
393671d10453SEric Joyner 	if (is_orig_mode)
393771d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
393871d10453SEric Joyner 	else
393971d10453SEric Joyner 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
394071d10453SEric Joyner 
394171d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
394271d10453SEric Joyner }
394371d10453SEric Joyner 
394471d10453SEric Joyner /**
394571d10453SEric Joyner  * ice_aq_sff_eeprom
394671d10453SEric Joyner  * @hw: pointer to the HW struct
394771d10453SEric Joyner  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
394871d10453SEric Joyner  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
394971d10453SEric Joyner  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
395071d10453SEric Joyner  * @page: QSFP page
395171d10453SEric Joyner  * @set_page: set or ignore the page
395271d10453SEric Joyner  * @data: pointer to data buffer to be read/written to the I2C device.
395371d10453SEric Joyner  * @length: 1-16 for read, 1 for write.
395471d10453SEric Joyner  * @write: 0 read, 1 for write.
395571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
395671d10453SEric Joyner  *
395771d10453SEric Joyner  * Read/Write SFF EEPROM (0x06EE)
395871d10453SEric Joyner  */
395971d10453SEric Joyner enum ice_status
396071d10453SEric Joyner ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
396171d10453SEric Joyner 		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
396271d10453SEric Joyner 		  bool write, struct ice_sq_cd *cd)
396371d10453SEric Joyner {
396471d10453SEric Joyner 	struct ice_aqc_sff_eeprom *cmd;
396571d10453SEric Joyner 	struct ice_aq_desc desc;
396671d10453SEric Joyner 	enum ice_status status;
396771d10453SEric Joyner 
396871d10453SEric Joyner 	if (!data || (mem_addr & 0xff00))
396971d10453SEric Joyner 		return ICE_ERR_PARAM;
397071d10453SEric Joyner 
397171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
397271d10453SEric Joyner 	cmd = &desc.params.read_write_sff_param;
3973d08b8680SEric Joyner 	desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD);
397471d10453SEric Joyner 	cmd->lport_num = (u8)(lport & 0xff);
397571d10453SEric Joyner 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
397671d10453SEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(((bus_addr >> 1) &
397771d10453SEric Joyner 					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
397871d10453SEric Joyner 					((set_page <<
397971d10453SEric Joyner 					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
398071d10453SEric Joyner 					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
398171d10453SEric Joyner 	cmd->i2c_mem_addr = CPU_TO_LE16(mem_addr & 0xff);
398271d10453SEric Joyner 	cmd->eeprom_page = CPU_TO_LE16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
398371d10453SEric Joyner 	if (write)
398471d10453SEric Joyner 		cmd->i2c_bus_addr |= CPU_TO_LE16(ICE_AQC_SFF_IS_WRITE);
398571d10453SEric Joyner 
398671d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
398771d10453SEric Joyner 	return status;
398871d10453SEric Joyner }
398971d10453SEric Joyner 
399071d10453SEric Joyner /**
399156429daeSEric Joyner  * ice_aq_prog_topo_dev_nvm
399256429daeSEric Joyner  * @hw: pointer to the hardware structure
399356429daeSEric Joyner  * @topo_params: pointer to structure storing topology parameters for a device
399456429daeSEric Joyner  * @cd: pointer to command details structure or NULL
399556429daeSEric Joyner  *
399656429daeSEric Joyner  * Program Topology Device NVM (0x06F2)
399756429daeSEric Joyner  *
399856429daeSEric Joyner  */
399956429daeSEric Joyner enum ice_status
400056429daeSEric Joyner ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
400156429daeSEric Joyner 			 struct ice_aqc_link_topo_params *topo_params,
400256429daeSEric Joyner 			 struct ice_sq_cd *cd)
400356429daeSEric Joyner {
400456429daeSEric Joyner 	struct ice_aqc_prog_topo_dev_nvm *cmd;
400556429daeSEric Joyner 	struct ice_aq_desc desc;
400656429daeSEric Joyner 
400756429daeSEric Joyner 	cmd = &desc.params.prog_topo_dev_nvm;
400856429daeSEric Joyner 
400956429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm);
401056429daeSEric Joyner 
401156429daeSEric Joyner 	ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
401256429daeSEric Joyner 		   ICE_NONDMA_TO_NONDMA);
401356429daeSEric Joyner 
401456429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
401556429daeSEric Joyner }
401656429daeSEric Joyner 
401756429daeSEric Joyner /**
401856429daeSEric Joyner  * ice_aq_read_topo_dev_nvm
401956429daeSEric Joyner  * @hw: pointer to the hardware structure
402056429daeSEric Joyner  * @topo_params: pointer to structure storing topology parameters for a device
402156429daeSEric Joyner  * @start_address: byte offset in the topology device NVM
402256429daeSEric Joyner  * @data: pointer to data buffer
402356429daeSEric Joyner  * @data_size: number of bytes to be read from the topology device NVM
402456429daeSEric Joyner  * @cd: pointer to command details structure or NULL
402556429daeSEric Joyner  * Read Topology Device NVM (0x06F3)
402656429daeSEric Joyner  *
402756429daeSEric Joyner  */
402856429daeSEric Joyner enum ice_status
402956429daeSEric Joyner ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
403056429daeSEric Joyner 			 struct ice_aqc_link_topo_params *topo_params,
403156429daeSEric Joyner 			 u32 start_address, u8 *data, u8 data_size,
403256429daeSEric Joyner 			 struct ice_sq_cd *cd)
403356429daeSEric Joyner {
403456429daeSEric Joyner 	struct ice_aqc_read_topo_dev_nvm *cmd;
403556429daeSEric Joyner 	struct ice_aq_desc desc;
403656429daeSEric Joyner 	enum ice_status status;
403756429daeSEric Joyner 
403856429daeSEric Joyner 	if (!data || data_size == 0 ||
403956429daeSEric Joyner 	    data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
404056429daeSEric Joyner 		return ICE_ERR_PARAM;
404156429daeSEric Joyner 
404256429daeSEric Joyner 	cmd = &desc.params.read_topo_dev_nvm;
404356429daeSEric Joyner 
404456429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm);
404556429daeSEric Joyner 
40468923de59SPiotr Kubaj 	desc.datalen = CPU_TO_LE16(data_size);
404756429daeSEric Joyner 	ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
404856429daeSEric Joyner 		   ICE_NONDMA_TO_NONDMA);
404956429daeSEric Joyner 	cmd->start_address = CPU_TO_LE32(start_address);
405056429daeSEric Joyner 
405156429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
405256429daeSEric Joyner 	if (status)
405356429daeSEric Joyner 		return status;
405456429daeSEric Joyner 
405556429daeSEric Joyner 	ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA);
405656429daeSEric Joyner 
405756429daeSEric Joyner 	return ICE_SUCCESS;
405856429daeSEric Joyner }
405956429daeSEric Joyner 
40609c30461dSEric Joyner static u16 ice_lut_type_to_size(u16 lut_type)
40619c30461dSEric Joyner {
40629c30461dSEric Joyner 	switch (lut_type) {
40639c30461dSEric Joyner 	case ICE_LUT_VSI:
40649c30461dSEric Joyner 		return ICE_LUT_VSI_SIZE;
40659c30461dSEric Joyner 	case ICE_LUT_GLOBAL:
40669c30461dSEric Joyner 		return ICE_LUT_GLOBAL_SIZE;
40679c30461dSEric Joyner 	case ICE_LUT_PF:
40689c30461dSEric Joyner 		return ICE_LUT_PF_SIZE;
4069*9e54973fSEric Joyner 	case ICE_LUT_PF_SMALL:
4070*9e54973fSEric Joyner 		return ICE_LUT_PF_SMALL_SIZE;
40719c30461dSEric Joyner 	default:
40729c30461dSEric Joyner 		return 0;
40739c30461dSEric Joyner 	}
40749c30461dSEric Joyner }
40759c30461dSEric Joyner 
40769c30461dSEric Joyner static u16 ice_lut_size_to_flag(u16 lut_size)
40779c30461dSEric Joyner {
40789c30461dSEric Joyner 	u16 f = 0;
40799c30461dSEric Joyner 
40809c30461dSEric Joyner 	switch (lut_size) {
40819c30461dSEric Joyner 	case ICE_LUT_GLOBAL_SIZE:
40829c30461dSEric Joyner 		f = ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG;
40839c30461dSEric Joyner 		break;
40849c30461dSEric Joyner 	case ICE_LUT_PF_SIZE:
40859c30461dSEric Joyner 		f = ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG;
40869c30461dSEric Joyner 		break;
40879c30461dSEric Joyner 	default:
40889c30461dSEric Joyner 		break;
40899c30461dSEric Joyner 	}
40909c30461dSEric Joyner 	return f << ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S;
40919c30461dSEric Joyner }
40929c30461dSEric Joyner 
40939c30461dSEric Joyner int ice_lut_size_to_type(int lut_size)
40949c30461dSEric Joyner {
40959c30461dSEric Joyner 	switch (lut_size) {
40969c30461dSEric Joyner 	case ICE_LUT_VSI_SIZE:
40979c30461dSEric Joyner 		return ICE_LUT_VSI;
40989c30461dSEric Joyner 	case ICE_LUT_GLOBAL_SIZE:
40999c30461dSEric Joyner 		return ICE_LUT_GLOBAL;
41009c30461dSEric Joyner 	case ICE_LUT_PF_SIZE:
41019c30461dSEric Joyner 		return ICE_LUT_PF;
4102*9e54973fSEric Joyner 	case ICE_LUT_PF_SMALL_SIZE:
4103*9e54973fSEric Joyner 		return ICE_LUT_PF_SMALL;
41049c30461dSEric Joyner 	default:
41059c30461dSEric Joyner 		return -1;
41069c30461dSEric Joyner 	}
41079c30461dSEric Joyner }
41089c30461dSEric Joyner 
410956429daeSEric Joyner /**
411071d10453SEric Joyner  * __ice_aq_get_set_rss_lut
411171d10453SEric Joyner  * @hw: pointer to the hardware structure
4112d08b8680SEric Joyner  * @params: RSS LUT parameters
411371d10453SEric Joyner  * @set: set true to set the table, false to get the table
411471d10453SEric Joyner  *
411571d10453SEric Joyner  * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
411671d10453SEric Joyner  */
411771d10453SEric Joyner static enum ice_status
4118d08b8680SEric Joyner __ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, bool set)
411971d10453SEric Joyner {
41209c30461dSEric Joyner 	u16 flags, vsi_id, lut_type, lut_size, glob_lut_idx = 0, vsi_handle;
412171d10453SEric Joyner 	struct ice_aqc_get_set_rss_lut *cmd_resp;
412271d10453SEric Joyner 	struct ice_aq_desc desc;
412371d10453SEric Joyner 	enum ice_status status;
4124d08b8680SEric Joyner 	u8 *lut;
4125d08b8680SEric Joyner 
4126d08b8680SEric Joyner 	if (!params)
4127d08b8680SEric Joyner 		return ICE_ERR_PARAM;
4128d08b8680SEric Joyner 
4129d08b8680SEric Joyner 	vsi_handle = params->vsi_handle;
4130d08b8680SEric Joyner 	lut = params->lut;
4131*9e54973fSEric Joyner 	lut_size = ice_lut_type_to_size(params->lut_type);
4132*9e54973fSEric Joyner 	lut_type = params->lut_type & ICE_LUT_TYPE_MASK;
41339c30461dSEric Joyner 	cmd_resp = &desc.params.get_set_rss_lut;
41349c30461dSEric Joyner 	if (lut_type == ICE_LUT_GLOBAL)
41359c30461dSEric Joyner 		glob_lut_idx = params->global_lut_id;
4136d08b8680SEric Joyner 
41379c30461dSEric Joyner 	if (!lut || !lut_size || !ice_is_vsi_valid(hw, vsi_handle))
4138d08b8680SEric Joyner 		return ICE_ERR_PARAM;
4139d08b8680SEric Joyner 
41409c30461dSEric Joyner 	if (lut_size > params->lut_size)
41419c30461dSEric Joyner 		return ICE_ERR_INVAL_SIZE;
414271d10453SEric Joyner 
41439c30461dSEric Joyner 	if (set && lut_size != params->lut_size)
41449c30461dSEric Joyner 		return ICE_ERR_PARAM;
41459c30461dSEric Joyner 
41469c30461dSEric Joyner 	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
414771d10453SEric Joyner 
414871d10453SEric Joyner 	if (set) {
414971d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut);
415071d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
415171d10453SEric Joyner 	} else {
415271d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut);
415371d10453SEric Joyner 	}
415471d10453SEric Joyner 
415571d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
415671d10453SEric Joyner 					 ICE_AQC_GSET_RSS_LUT_VSI_ID_S) &
415771d10453SEric Joyner 					ICE_AQC_GSET_RSS_LUT_VSI_ID_M) |
415871d10453SEric Joyner 				       ICE_AQC_GSET_RSS_LUT_VSI_VALID);
415971d10453SEric Joyner 
41609c30461dSEric Joyner 	flags = ice_lut_size_to_flag(lut_size) |
41619c30461dSEric Joyner 		 ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) &
41629c30461dSEric Joyner 		  ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M) |
41639c30461dSEric Joyner 		 ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) &
416471d10453SEric Joyner 		  ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M);
416571d10453SEric Joyner 
416671d10453SEric Joyner 	cmd_resp->flags = CPU_TO_LE16(flags);
416771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
41689c30461dSEric Joyner 	params->lut_size = LE16_TO_CPU(desc.datalen);
416971d10453SEric Joyner 	return status;
417071d10453SEric Joyner }
417171d10453SEric Joyner 
417271d10453SEric Joyner /**
417371d10453SEric Joyner  * ice_aq_get_rss_lut
417471d10453SEric Joyner  * @hw: pointer to the hardware structure
4175d08b8680SEric Joyner  * @get_params: RSS LUT parameters used to specify which RSS LUT to get
417671d10453SEric Joyner  *
417771d10453SEric Joyner  * get the RSS lookup table, PF or VSI type
417871d10453SEric Joyner  */
417971d10453SEric Joyner enum ice_status
4180d08b8680SEric Joyner ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)
418171d10453SEric Joyner {
4182d08b8680SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, get_params, false);
418371d10453SEric Joyner }
418471d10453SEric Joyner 
418571d10453SEric Joyner /**
418671d10453SEric Joyner  * ice_aq_set_rss_lut
418771d10453SEric Joyner  * @hw: pointer to the hardware structure
4188d08b8680SEric Joyner  * @set_params: RSS LUT parameters used to specify how to set the RSS LUT
418971d10453SEric Joyner  *
419071d10453SEric Joyner  * set the RSS lookup table, PF or VSI type
419171d10453SEric Joyner  */
419271d10453SEric Joyner enum ice_status
4193d08b8680SEric Joyner ice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)
419471d10453SEric Joyner {
4195d08b8680SEric Joyner 	return __ice_aq_get_set_rss_lut(hw, set_params, true);
419671d10453SEric Joyner }
419771d10453SEric Joyner 
419871d10453SEric Joyner /**
419971d10453SEric Joyner  * __ice_aq_get_set_rss_key
420071d10453SEric Joyner  * @hw: pointer to the HW struct
420171d10453SEric Joyner  * @vsi_id: VSI FW index
420271d10453SEric Joyner  * @key: pointer to key info struct
420371d10453SEric Joyner  * @set: set true to set the key, false to get the key
420471d10453SEric Joyner  *
420571d10453SEric Joyner  * get (0x0B04) or set (0x0B02) the RSS key per VSI
420671d10453SEric Joyner  */
420771d10453SEric Joyner static enum
420871d10453SEric Joyner ice_status __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
420971d10453SEric Joyner 				    struct ice_aqc_get_set_rss_keys *key,
421071d10453SEric Joyner 				    bool set)
421171d10453SEric Joyner {
421271d10453SEric Joyner 	struct ice_aqc_get_set_rss_key *cmd_resp;
421371d10453SEric Joyner 	u16 key_size = sizeof(*key);
421471d10453SEric Joyner 	struct ice_aq_desc desc;
421571d10453SEric Joyner 
421671d10453SEric Joyner 	cmd_resp = &desc.params.get_set_rss_key;
421771d10453SEric Joyner 
421871d10453SEric Joyner 	if (set) {
421971d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
422071d10453SEric Joyner 		desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
422171d10453SEric Joyner 	} else {
422271d10453SEric Joyner 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
422371d10453SEric Joyner 	}
422471d10453SEric Joyner 
422571d10453SEric Joyner 	cmd_resp->vsi_id = CPU_TO_LE16(((vsi_id <<
422671d10453SEric Joyner 					 ICE_AQC_GSET_RSS_KEY_VSI_ID_S) &
422771d10453SEric Joyner 					ICE_AQC_GSET_RSS_KEY_VSI_ID_M) |
422871d10453SEric Joyner 				       ICE_AQC_GSET_RSS_KEY_VSI_VALID);
422971d10453SEric Joyner 
423071d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
423171d10453SEric Joyner }
423271d10453SEric Joyner 
423371d10453SEric Joyner /**
423471d10453SEric Joyner  * ice_aq_get_rss_key
423571d10453SEric Joyner  * @hw: pointer to the HW struct
423671d10453SEric Joyner  * @vsi_handle: software VSI handle
423771d10453SEric Joyner  * @key: pointer to key info struct
423871d10453SEric Joyner  *
423971d10453SEric Joyner  * get the RSS key per VSI
424071d10453SEric Joyner  */
424171d10453SEric Joyner enum ice_status
424271d10453SEric Joyner ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
424371d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *key)
424471d10453SEric Joyner {
424571d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
424671d10453SEric Joyner 		return ICE_ERR_PARAM;
424771d10453SEric Joyner 
424871d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
424971d10453SEric Joyner 					key, false);
425071d10453SEric Joyner }
425171d10453SEric Joyner 
425271d10453SEric Joyner /**
425371d10453SEric Joyner  * ice_aq_set_rss_key
425471d10453SEric Joyner  * @hw: pointer to the HW struct
425571d10453SEric Joyner  * @vsi_handle: software VSI handle
425671d10453SEric Joyner  * @keys: pointer to key info struct
425771d10453SEric Joyner  *
425871d10453SEric Joyner  * set the RSS key per VSI
425971d10453SEric Joyner  */
426071d10453SEric Joyner enum ice_status
426171d10453SEric Joyner ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
426271d10453SEric Joyner 		   struct ice_aqc_get_set_rss_keys *keys)
426371d10453SEric Joyner {
426471d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
426571d10453SEric Joyner 		return ICE_ERR_PARAM;
426671d10453SEric Joyner 
426771d10453SEric Joyner 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
426871d10453SEric Joyner 					keys, true);
426971d10453SEric Joyner }
427071d10453SEric Joyner 
427171d10453SEric Joyner /**
427271d10453SEric Joyner  * ice_aq_add_lan_txq
427371d10453SEric Joyner  * @hw: pointer to the hardware structure
427471d10453SEric Joyner  * @num_qgrps: Number of added queue groups
427571d10453SEric Joyner  * @qg_list: list of queue groups to be added
427671d10453SEric Joyner  * @buf_size: size of buffer for indirect command
427771d10453SEric Joyner  * @cd: pointer to command details structure or NULL
427871d10453SEric Joyner  *
427971d10453SEric Joyner  * Add Tx LAN queue (0x0C30)
428071d10453SEric Joyner  *
428171d10453SEric Joyner  * NOTE:
428271d10453SEric Joyner  * Prior to calling add Tx LAN queue:
428371d10453SEric Joyner  * Initialize the following as part of the Tx queue context:
428471d10453SEric Joyner  * Completion queue ID if the queue uses Completion queue, Quanta profile,
428571d10453SEric Joyner  * Cache profile and Packet shaper profile.
428671d10453SEric Joyner  *
428771d10453SEric Joyner  * After add Tx LAN queue AQ command is completed:
428871d10453SEric Joyner  * Interrupts should be associated with specific queues,
428971d10453SEric Joyner  * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
429071d10453SEric Joyner  * flow.
429171d10453SEric Joyner  */
429271d10453SEric Joyner enum ice_status
429371d10453SEric Joyner ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
429471d10453SEric Joyner 		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
429571d10453SEric Joyner 		   struct ice_sq_cd *cd)
429671d10453SEric Joyner {
429771d10453SEric Joyner 	struct ice_aqc_add_tx_qgrp *list;
429871d10453SEric Joyner 	struct ice_aqc_add_txqs *cmd;
429971d10453SEric Joyner 	struct ice_aq_desc desc;
43007d7af7f8SEric Joyner 	u16 i, sum_size = 0;
430171d10453SEric Joyner 
430271d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
430371d10453SEric Joyner 
430471d10453SEric Joyner 	cmd = &desc.params.add_txqs;
430571d10453SEric Joyner 
430671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
430771d10453SEric Joyner 
430871d10453SEric Joyner 	if (!qg_list)
430971d10453SEric Joyner 		return ICE_ERR_PARAM;
431071d10453SEric Joyner 
431171d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
431271d10453SEric Joyner 		return ICE_ERR_PARAM;
431371d10453SEric Joyner 
43147d7af7f8SEric Joyner 	for (i = 0, list = qg_list; i < num_qgrps; i++) {
43157d7af7f8SEric Joyner 		sum_size += ice_struct_size(list, txqs, list->num_txqs);
43167d7af7f8SEric Joyner 		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
43177d7af7f8SEric Joyner 						      list->num_txqs);
431871d10453SEric Joyner 	}
431971d10453SEric Joyner 
43207d7af7f8SEric Joyner 	if (buf_size != sum_size)
432171d10453SEric Joyner 		return ICE_ERR_PARAM;
432271d10453SEric Joyner 
432371d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
432471d10453SEric Joyner 
432571d10453SEric Joyner 	cmd->num_qgrps = num_qgrps;
432671d10453SEric Joyner 
432771d10453SEric Joyner 	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
432871d10453SEric Joyner }
432971d10453SEric Joyner 
433071d10453SEric Joyner /**
433171d10453SEric Joyner  * ice_aq_dis_lan_txq
433271d10453SEric Joyner  * @hw: pointer to the hardware structure
433371d10453SEric Joyner  * @num_qgrps: number of groups in the list
433471d10453SEric Joyner  * @qg_list: the list of groups to disable
433571d10453SEric Joyner  * @buf_size: the total size of the qg_list buffer in bytes
433671d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
433771d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
433871d10453SEric Joyner  * @cd: pointer to command details structure or NULL
433971d10453SEric Joyner  *
434071d10453SEric Joyner  * Disable LAN Tx queue (0x0C31)
434171d10453SEric Joyner  */
434271d10453SEric Joyner static enum ice_status
434371d10453SEric Joyner ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
434471d10453SEric Joyner 		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
434571d10453SEric Joyner 		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
434671d10453SEric Joyner 		   struct ice_sq_cd *cd)
434771d10453SEric Joyner {
43487d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *item;
434971d10453SEric Joyner 	struct ice_aqc_dis_txqs *cmd;
435071d10453SEric Joyner 	struct ice_aq_desc desc;
435171d10453SEric Joyner 	enum ice_status status;
435271d10453SEric Joyner 	u16 i, sz = 0;
435371d10453SEric Joyner 
435471d10453SEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
435571d10453SEric Joyner 	cmd = &desc.params.dis_txqs;
435671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
435771d10453SEric Joyner 
435871d10453SEric Joyner 	/* qg_list can be NULL only in VM/VF reset flow */
435971d10453SEric Joyner 	if (!qg_list && !rst_src)
436071d10453SEric Joyner 		return ICE_ERR_PARAM;
436171d10453SEric Joyner 
436271d10453SEric Joyner 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
436371d10453SEric Joyner 		return ICE_ERR_PARAM;
436471d10453SEric Joyner 
436571d10453SEric Joyner 	cmd->num_entries = num_qgrps;
436671d10453SEric Joyner 
436771d10453SEric Joyner 	cmd->vmvf_and_timeout = CPU_TO_LE16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
436871d10453SEric Joyner 					    ICE_AQC_Q_DIS_TIMEOUT_M);
436971d10453SEric Joyner 
437071d10453SEric Joyner 	switch (rst_src) {
437171d10453SEric Joyner 	case ICE_VM_RESET:
437271d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
437371d10453SEric Joyner 		cmd->vmvf_and_timeout |=
437471d10453SEric Joyner 			CPU_TO_LE16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
437571d10453SEric Joyner 		break;
437671d10453SEric Joyner 	case ICE_VF_RESET:
437771d10453SEric Joyner 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
437871d10453SEric Joyner 		/* In this case, FW expects vmvf_num to be absolute VF ID */
437971d10453SEric Joyner 		cmd->vmvf_and_timeout |=
438071d10453SEric Joyner 			CPU_TO_LE16((vmvf_num + hw->func_caps.vf_base_id) &
438171d10453SEric Joyner 				    ICE_AQC_Q_DIS_VMVF_NUM_M);
438271d10453SEric Joyner 		break;
438371d10453SEric Joyner 	case ICE_NO_RESET:
438471d10453SEric Joyner 	default:
438571d10453SEric Joyner 		break;
438671d10453SEric Joyner 	}
438771d10453SEric Joyner 
438871d10453SEric Joyner 	/* flush pipe on time out */
438971d10453SEric Joyner 	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
439071d10453SEric Joyner 	/* If no queue group info, we are in a reset flow. Issue the AQ */
439171d10453SEric Joyner 	if (!qg_list)
439271d10453SEric Joyner 		goto do_aq;
439371d10453SEric Joyner 
439471d10453SEric Joyner 	/* set RD bit to indicate that command buffer is provided by the driver
439571d10453SEric Joyner 	 * and it needs to be read by the firmware
439671d10453SEric Joyner 	 */
439771d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
439871d10453SEric Joyner 
43997d7af7f8SEric Joyner 	for (i = 0, item = qg_list; i < num_qgrps; i++) {
44007d7af7f8SEric Joyner 		u16 item_size = ice_struct_size(item, q_id, item->num_qs);
440171d10453SEric Joyner 
440271d10453SEric Joyner 		/* If the num of queues is even, add 2 bytes of padding */
44037d7af7f8SEric Joyner 		if ((item->num_qs % 2) == 0)
44047d7af7f8SEric Joyner 			item_size += 2;
44057d7af7f8SEric Joyner 
44067d7af7f8SEric Joyner 		sz += item_size;
44077d7af7f8SEric Joyner 
44087d7af7f8SEric Joyner 		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
440971d10453SEric Joyner 	}
441071d10453SEric Joyner 
441171d10453SEric Joyner 	if (buf_size != sz)
441271d10453SEric Joyner 		return ICE_ERR_PARAM;
441371d10453SEric Joyner 
441471d10453SEric Joyner do_aq:
441571d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
441671d10453SEric Joyner 	if (status) {
441771d10453SEric Joyner 		if (!qg_list)
441871d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
441971d10453SEric Joyner 				  vmvf_num, hw->adminq.sq_last_status);
442071d10453SEric Joyner 		else
442171d10453SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
442271d10453SEric Joyner 				  LE16_TO_CPU(qg_list[0].q_id[0]),
442371d10453SEric Joyner 				  hw->adminq.sq_last_status);
442471d10453SEric Joyner 	}
442571d10453SEric Joyner 	return status;
442671d10453SEric Joyner }
442771d10453SEric Joyner 
442871d10453SEric Joyner /**
442971d10453SEric Joyner  * ice_aq_move_recfg_lan_txq
443071d10453SEric Joyner  * @hw: pointer to the hardware structure
443171d10453SEric Joyner  * @num_qs: number of queues to move/reconfigure
443271d10453SEric Joyner  * @is_move: true if this operation involves node movement
443371d10453SEric Joyner  * @is_tc_change: true if this operation involves a TC change
443471d10453SEric Joyner  * @subseq_call: true if this operation is a subsequent call
443571d10453SEric Joyner  * @flush_pipe: on timeout, true to flush pipe, false to return EAGAIN
443671d10453SEric Joyner  * @timeout: timeout in units of 100 usec (valid values 0-50)
443771d10453SEric Joyner  * @blocked_cgds: out param, bitmap of CGDs that timed out if returning EAGAIN
443871d10453SEric Joyner  * @buf: struct containing src/dest TEID and per-queue info
443971d10453SEric Joyner  * @buf_size: size of buffer for indirect command
444071d10453SEric Joyner  * @txqs_moved: out param, number of queues successfully moved
444171d10453SEric Joyner  * @cd: pointer to command details structure or NULL
444271d10453SEric Joyner  *
444371d10453SEric Joyner  * Move / Reconfigure Tx LAN queues (0x0C32)
444471d10453SEric Joyner  */
444571d10453SEric Joyner enum ice_status
444671d10453SEric Joyner ice_aq_move_recfg_lan_txq(struct ice_hw *hw, u8 num_qs, bool is_move,
444771d10453SEric Joyner 			  bool is_tc_change, bool subseq_call, bool flush_pipe,
444871d10453SEric Joyner 			  u8 timeout, u32 *blocked_cgds,
444971d10453SEric Joyner 			  struct ice_aqc_move_txqs_data *buf, u16 buf_size,
445071d10453SEric Joyner 			  u8 *txqs_moved, struct ice_sq_cd *cd)
445171d10453SEric Joyner {
445271d10453SEric Joyner 	struct ice_aqc_move_txqs *cmd;
445371d10453SEric Joyner 	struct ice_aq_desc desc;
445471d10453SEric Joyner 	enum ice_status status;
445571d10453SEric Joyner 
445671d10453SEric Joyner 	cmd = &desc.params.move_txqs;
445771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_move_recfg_txqs);
445871d10453SEric Joyner 
445971d10453SEric Joyner #define ICE_LAN_TXQ_MOVE_TIMEOUT_MAX 50
446071d10453SEric Joyner 	if (timeout > ICE_LAN_TXQ_MOVE_TIMEOUT_MAX)
446171d10453SEric Joyner 		return ICE_ERR_PARAM;
446271d10453SEric Joyner 
446371d10453SEric Joyner 	if (is_tc_change && !flush_pipe && !blocked_cgds)
446471d10453SEric Joyner 		return ICE_ERR_PARAM;
446571d10453SEric Joyner 
446671d10453SEric Joyner 	if (!is_move && !is_tc_change)
446771d10453SEric Joyner 		return ICE_ERR_PARAM;
446871d10453SEric Joyner 
446971d10453SEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
447071d10453SEric Joyner 
447171d10453SEric Joyner 	if (is_move)
447271d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_MOVE;
447371d10453SEric Joyner 
447471d10453SEric Joyner 	if (is_tc_change)
447571d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_TYPE_TC_CHANGE;
447671d10453SEric Joyner 
447771d10453SEric Joyner 	if (subseq_call)
447871d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_SUBSEQ_CALL;
447971d10453SEric Joyner 
448071d10453SEric Joyner 	if (flush_pipe)
448171d10453SEric Joyner 		cmd->cmd_type |= ICE_AQC_Q_CMD_FLUSH_PIPE;
448271d10453SEric Joyner 
448371d10453SEric Joyner 	cmd->num_qs = num_qs;
448471d10453SEric Joyner 	cmd->timeout = ((timeout << ICE_AQC_Q_CMD_TIMEOUT_S) &
448571d10453SEric Joyner 			ICE_AQC_Q_CMD_TIMEOUT_M);
448671d10453SEric Joyner 
448771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
448871d10453SEric Joyner 
448971d10453SEric Joyner 	if (!status && txqs_moved)
449071d10453SEric Joyner 		*txqs_moved = cmd->num_qs;
449171d10453SEric Joyner 
449271d10453SEric Joyner 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EAGAIN &&
449371d10453SEric Joyner 	    is_tc_change && !flush_pipe)
449471d10453SEric Joyner 		*blocked_cgds = LE32_TO_CPU(cmd->blocked_cgds);
449571d10453SEric Joyner 
449671d10453SEric Joyner 	return status;
449771d10453SEric Joyner }
449871d10453SEric Joyner 
44998a13362dSEric Joyner /**
45008a13362dSEric Joyner  * ice_aq_add_rdma_qsets
45018a13362dSEric Joyner  * @hw: pointer to the hardware structure
45028a13362dSEric Joyner  * @num_qset_grps: Number of RDMA Qset groups
45038a13362dSEric Joyner  * @qset_list: list of qset groups to be added
45048a13362dSEric Joyner  * @buf_size: size of buffer for indirect command
45058a13362dSEric Joyner  * @cd: pointer to command details structure or NULL
45068a13362dSEric Joyner  *
45078a13362dSEric Joyner  * Add Tx RDMA Qsets (0x0C33)
45088a13362dSEric Joyner  */
45098a13362dSEric Joyner enum ice_status
45108a13362dSEric Joyner ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps,
45118a13362dSEric Joyner 		      struct ice_aqc_add_rdma_qset_data *qset_list,
45128a13362dSEric Joyner 		      u16 buf_size, struct ice_sq_cd *cd)
45138a13362dSEric Joyner {
45148a13362dSEric Joyner 	struct ice_aqc_add_rdma_qset_data *list;
45158a13362dSEric Joyner 	struct ice_aqc_add_rdma_qset *cmd;
45168a13362dSEric Joyner 	struct ice_aq_desc desc;
45178a13362dSEric Joyner 	u16 i, sum_size = 0;
45188a13362dSEric Joyner 
45198a13362dSEric Joyner 	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
45208a13362dSEric Joyner 
45218a13362dSEric Joyner 	cmd = &desc.params.add_rdma_qset;
45228a13362dSEric Joyner 
45238a13362dSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_rdma_qset);
45248a13362dSEric Joyner 
45258a13362dSEric Joyner 	if (!qset_list)
45268a13362dSEric Joyner 		return ICE_ERR_PARAM;
45278a13362dSEric Joyner 
45288a13362dSEric Joyner 	if (num_qset_grps > ICE_LAN_TXQ_MAX_QGRPS)
45298a13362dSEric Joyner 		return ICE_ERR_PARAM;
45308a13362dSEric Joyner 
45318a13362dSEric Joyner 	for (i = 0, list = qset_list; i < num_qset_grps; i++) {
45328a13362dSEric Joyner 		u16 num_qsets = LE16_TO_CPU(list->num_qsets);
45338a13362dSEric Joyner 
45348a13362dSEric Joyner 		sum_size += ice_struct_size(list, rdma_qsets, num_qsets);
45358a13362dSEric Joyner 		list = (struct ice_aqc_add_rdma_qset_data *)(list->rdma_qsets +
45368a13362dSEric Joyner 							     num_qsets);
45378a13362dSEric Joyner 	}
45388a13362dSEric Joyner 
45398a13362dSEric Joyner 	if (buf_size != sum_size)
45408a13362dSEric Joyner 		return ICE_ERR_PARAM;
45418a13362dSEric Joyner 
45428a13362dSEric Joyner 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
45438a13362dSEric Joyner 
45448a13362dSEric Joyner 	cmd->num_qset_grps = num_qset_grps;
45458a13362dSEric Joyner 
45468a13362dSEric Joyner 	return ice_aq_send_cmd(hw, &desc, qset_list, buf_size, cd);
45478a13362dSEric Joyner }
45488a13362dSEric Joyner 
454971d10453SEric Joyner /* End of FW Admin Queue command wrappers */
455071d10453SEric Joyner 
455171d10453SEric Joyner /**
455271d10453SEric Joyner  * ice_write_byte - write a byte to a packed context structure
455371d10453SEric Joyner  * @src_ctx:  the context structure to read from
455471d10453SEric Joyner  * @dest_ctx: the context to be written to
455571d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
455671d10453SEric Joyner  */
455771d10453SEric Joyner static void
455871d10453SEric Joyner ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
455971d10453SEric Joyner {
456071d10453SEric Joyner 	u8 src_byte, dest_byte, mask;
456171d10453SEric Joyner 	u8 *from, *dest;
456271d10453SEric Joyner 	u16 shift_width;
456371d10453SEric Joyner 
456471d10453SEric Joyner 	/* copy from the next struct field */
456571d10453SEric Joyner 	from = src_ctx + ce_info->offset;
456671d10453SEric Joyner 
456771d10453SEric Joyner 	/* prepare the bits and mask */
456871d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
456971d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
457071d10453SEric Joyner 
457171d10453SEric Joyner 	src_byte = *from;
457271d10453SEric Joyner 	src_byte &= mask;
457371d10453SEric Joyner 
457471d10453SEric Joyner 	/* shift to correct alignment */
457571d10453SEric Joyner 	mask <<= shift_width;
457671d10453SEric Joyner 	src_byte <<= shift_width;
457771d10453SEric Joyner 
457871d10453SEric Joyner 	/* get the current bits from the target bit string */
457971d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
458071d10453SEric Joyner 
458171d10453SEric Joyner 	ice_memcpy(&dest_byte, dest, sizeof(dest_byte), ICE_DMA_TO_NONDMA);
458271d10453SEric Joyner 
458371d10453SEric Joyner 	dest_byte &= ~mask;	/* get the bits not changing */
458471d10453SEric Joyner 	dest_byte |= src_byte;	/* add in the new bits */
458571d10453SEric Joyner 
458671d10453SEric Joyner 	/* put it all back */
458771d10453SEric Joyner 	ice_memcpy(dest, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA);
458871d10453SEric Joyner }
458971d10453SEric Joyner 
459071d10453SEric Joyner /**
459171d10453SEric Joyner  * ice_write_word - write a word to a packed context structure
459271d10453SEric Joyner  * @src_ctx:  the context structure to read from
459371d10453SEric Joyner  * @dest_ctx: the context to be written to
459471d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
459571d10453SEric Joyner  */
459671d10453SEric Joyner static void
459771d10453SEric Joyner ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
459871d10453SEric Joyner {
459971d10453SEric Joyner 	u16 src_word, mask;
460071d10453SEric Joyner 	__le16 dest_word;
460171d10453SEric Joyner 	u8 *from, *dest;
460271d10453SEric Joyner 	u16 shift_width;
460371d10453SEric Joyner 
460471d10453SEric Joyner 	/* copy from the next struct field */
460571d10453SEric Joyner 	from = src_ctx + ce_info->offset;
460671d10453SEric Joyner 
460771d10453SEric Joyner 	/* prepare the bits and mask */
460871d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
460971d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
461071d10453SEric Joyner 
461171d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
461271d10453SEric Joyner 	 * will be in a different bit position on big endian machines
461371d10453SEric Joyner 	 */
461471d10453SEric Joyner 	src_word = *(u16 *)from;
461571d10453SEric Joyner 	src_word &= mask;
461671d10453SEric Joyner 
461771d10453SEric Joyner 	/* shift to correct alignment */
461871d10453SEric Joyner 	mask <<= shift_width;
461971d10453SEric Joyner 	src_word <<= shift_width;
462071d10453SEric Joyner 
462171d10453SEric Joyner 	/* get the current bits from the target bit string */
462271d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
462371d10453SEric Joyner 
462471d10453SEric Joyner 	ice_memcpy(&dest_word, dest, sizeof(dest_word), ICE_DMA_TO_NONDMA);
462571d10453SEric Joyner 
462671d10453SEric Joyner 	dest_word &= ~(CPU_TO_LE16(mask));	/* get the bits not changing */
462771d10453SEric Joyner 	dest_word |= CPU_TO_LE16(src_word);	/* add in the new bits */
462871d10453SEric Joyner 
462971d10453SEric Joyner 	/* put it all back */
463071d10453SEric Joyner 	ice_memcpy(dest, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA);
463171d10453SEric Joyner }
463271d10453SEric Joyner 
463371d10453SEric Joyner /**
463471d10453SEric Joyner  * ice_write_dword - write a dword to a packed context structure
463571d10453SEric Joyner  * @src_ctx:  the context structure to read from
463671d10453SEric Joyner  * @dest_ctx: the context to be written to
463771d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
463871d10453SEric Joyner  */
463971d10453SEric Joyner static void
464071d10453SEric Joyner ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
464171d10453SEric Joyner {
464271d10453SEric Joyner 	u32 src_dword, mask;
464371d10453SEric Joyner 	__le32 dest_dword;
464471d10453SEric Joyner 	u8 *from, *dest;
464571d10453SEric Joyner 	u16 shift_width;
464671d10453SEric Joyner 
464771d10453SEric Joyner 	/* copy from the next struct field */
464871d10453SEric Joyner 	from = src_ctx + ce_info->offset;
464971d10453SEric Joyner 
465071d10453SEric Joyner 	/* prepare the bits and mask */
465171d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
465271d10453SEric Joyner 
465371d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
465471d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
465571d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
465671d10453SEric Joyner 	 */
465771d10453SEric Joyner 	if (ce_info->width < 32)
465871d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
465971d10453SEric Joyner 	else
466071d10453SEric Joyner 		mask = (u32)~0;
466171d10453SEric Joyner 
466271d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
466371d10453SEric Joyner 	 * will be in a different bit position on big endian machines
466471d10453SEric Joyner 	 */
466571d10453SEric Joyner 	src_dword = *(u32 *)from;
466671d10453SEric Joyner 	src_dword &= mask;
466771d10453SEric Joyner 
466871d10453SEric Joyner 	/* shift to correct alignment */
466971d10453SEric Joyner 	mask <<= shift_width;
467071d10453SEric Joyner 	src_dword <<= shift_width;
467171d10453SEric Joyner 
467271d10453SEric Joyner 	/* get the current bits from the target bit string */
467371d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
467471d10453SEric Joyner 
467571d10453SEric Joyner 	ice_memcpy(&dest_dword, dest, sizeof(dest_dword), ICE_DMA_TO_NONDMA);
467671d10453SEric Joyner 
467771d10453SEric Joyner 	dest_dword &= ~(CPU_TO_LE32(mask));	/* get the bits not changing */
467871d10453SEric Joyner 	dest_dword |= CPU_TO_LE32(src_dword);	/* add in the new bits */
467971d10453SEric Joyner 
468071d10453SEric Joyner 	/* put it all back */
468171d10453SEric Joyner 	ice_memcpy(dest, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA);
468271d10453SEric Joyner }
468371d10453SEric Joyner 
468471d10453SEric Joyner /**
468571d10453SEric Joyner  * ice_write_qword - write a qword to a packed context structure
468671d10453SEric Joyner  * @src_ctx:  the context structure to read from
468771d10453SEric Joyner  * @dest_ctx: the context to be written to
468871d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
468971d10453SEric Joyner  */
469071d10453SEric Joyner static void
469171d10453SEric Joyner ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
469271d10453SEric Joyner {
469371d10453SEric Joyner 	u64 src_qword, mask;
469471d10453SEric Joyner 	__le64 dest_qword;
469571d10453SEric Joyner 	u8 *from, *dest;
469671d10453SEric Joyner 	u16 shift_width;
469771d10453SEric Joyner 
469871d10453SEric Joyner 	/* copy from the next struct field */
469971d10453SEric Joyner 	from = src_ctx + ce_info->offset;
470071d10453SEric Joyner 
470171d10453SEric Joyner 	/* prepare the bits and mask */
470271d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
470371d10453SEric Joyner 
470471d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
470571d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
470671d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
470771d10453SEric Joyner 	 */
470871d10453SEric Joyner 	if (ce_info->width < 64)
470971d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
471071d10453SEric Joyner 	else
471171d10453SEric Joyner 		mask = (u64)~0;
471271d10453SEric Joyner 
471371d10453SEric Joyner 	/* don't swizzle the bits until after the mask because the mask bits
471471d10453SEric Joyner 	 * will be in a different bit position on big endian machines
471571d10453SEric Joyner 	 */
471671d10453SEric Joyner 	src_qword = *(u64 *)from;
471771d10453SEric Joyner 	src_qword &= mask;
471871d10453SEric Joyner 
471971d10453SEric Joyner 	/* shift to correct alignment */
472071d10453SEric Joyner 	mask <<= shift_width;
472171d10453SEric Joyner 	src_qword <<= shift_width;
472271d10453SEric Joyner 
472371d10453SEric Joyner 	/* get the current bits from the target bit string */
472471d10453SEric Joyner 	dest = dest_ctx + (ce_info->lsb / 8);
472571d10453SEric Joyner 
472671d10453SEric Joyner 	ice_memcpy(&dest_qword, dest, sizeof(dest_qword), ICE_DMA_TO_NONDMA);
472771d10453SEric Joyner 
472871d10453SEric Joyner 	dest_qword &= ~(CPU_TO_LE64(mask));	/* get the bits not changing */
472971d10453SEric Joyner 	dest_qword |= CPU_TO_LE64(src_qword);	/* add in the new bits */
473071d10453SEric Joyner 
473171d10453SEric Joyner 	/* put it all back */
473271d10453SEric Joyner 	ice_memcpy(dest, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA);
473371d10453SEric Joyner }
473471d10453SEric Joyner 
473571d10453SEric Joyner /**
473671d10453SEric Joyner  * ice_set_ctx - set context bits in packed structure
47377d7af7f8SEric Joyner  * @hw: pointer to the hardware structure
473871d10453SEric Joyner  * @src_ctx:  pointer to a generic non-packed context structure
473971d10453SEric Joyner  * @dest_ctx: pointer to memory for the packed structure
474071d10453SEric Joyner  * @ce_info:  a description of the structure to be transformed
474171d10453SEric Joyner  */
474271d10453SEric Joyner enum ice_status
47437d7af7f8SEric Joyner ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
47447d7af7f8SEric Joyner 	    const struct ice_ctx_ele *ce_info)
474571d10453SEric Joyner {
474671d10453SEric Joyner 	int f;
474771d10453SEric Joyner 
474871d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
474971d10453SEric Joyner 		/* We have to deal with each element of the FW response
475071d10453SEric Joyner 		 * using the correct size so that we are correct regardless
475171d10453SEric Joyner 		 * of the endianness of the machine.
475271d10453SEric Joyner 		 */
47537d7af7f8SEric Joyner 		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
47547d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
47557d7af7f8SEric Joyner 				  f, ce_info[f].width, ce_info[f].size_of);
47567d7af7f8SEric Joyner 			continue;
47577d7af7f8SEric Joyner 		}
475871d10453SEric Joyner 		switch (ce_info[f].size_of) {
475971d10453SEric Joyner 		case sizeof(u8):
476071d10453SEric Joyner 			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
476171d10453SEric Joyner 			break;
476271d10453SEric Joyner 		case sizeof(u16):
476371d10453SEric Joyner 			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
476471d10453SEric Joyner 			break;
476571d10453SEric Joyner 		case sizeof(u32):
476671d10453SEric Joyner 			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
476771d10453SEric Joyner 			break;
476871d10453SEric Joyner 		case sizeof(u64):
476971d10453SEric Joyner 			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
477071d10453SEric Joyner 			break;
477171d10453SEric Joyner 		default:
477271d10453SEric Joyner 			return ICE_ERR_INVAL_SIZE;
477371d10453SEric Joyner 		}
477471d10453SEric Joyner 	}
477571d10453SEric Joyner 
477671d10453SEric Joyner 	return ICE_SUCCESS;
477771d10453SEric Joyner }
477871d10453SEric Joyner 
477971d10453SEric Joyner /**
478056429daeSEric Joyner  * ice_aq_get_internal_data
478156429daeSEric Joyner  * @hw: pointer to the hardware structure
478256429daeSEric Joyner  * @cluster_id: specific cluster to dump
478356429daeSEric Joyner  * @table_id: table ID within cluster
478456429daeSEric Joyner  * @start: index of line in the block to read
478556429daeSEric Joyner  * @buf: dump buffer
478656429daeSEric Joyner  * @buf_size: dump buffer size
478756429daeSEric Joyner  * @ret_buf_size: return buffer size (returned by FW)
4788*9e54973fSEric Joyner  * @ret_next_cluster: next cluster to read (returned by FW)
478956429daeSEric Joyner  * @ret_next_table: next block to read (returned by FW)
479056429daeSEric Joyner  * @ret_next_index: next index to read (returned by FW)
479156429daeSEric Joyner  * @cd: pointer to command details structure
479256429daeSEric Joyner  *
479356429daeSEric Joyner  * Get internal FW/HW data (0xFF08) for debug purposes.
479456429daeSEric Joyner  */
479556429daeSEric Joyner enum ice_status
4796*9e54973fSEric Joyner ice_aq_get_internal_data(struct ice_hw *hw, u16 cluster_id, u16 table_id,
479756429daeSEric Joyner 			 u32 start, void *buf, u16 buf_size, u16 *ret_buf_size,
4798*9e54973fSEric Joyner 			 u16 *ret_next_cluster, u16 *ret_next_table,
4799*9e54973fSEric Joyner 			 u32 *ret_next_index, struct ice_sq_cd *cd)
480056429daeSEric Joyner {
480156429daeSEric Joyner 	struct ice_aqc_debug_dump_internals *cmd;
480256429daeSEric Joyner 	struct ice_aq_desc desc;
480356429daeSEric Joyner 	enum ice_status status;
480456429daeSEric Joyner 
480556429daeSEric Joyner 	cmd = &desc.params.debug_dump;
480656429daeSEric Joyner 
480756429daeSEric Joyner 	if (buf_size == 0 || !buf)
480856429daeSEric Joyner 		return ICE_ERR_PARAM;
480956429daeSEric Joyner 
481056429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_debug_dump_internals);
481156429daeSEric Joyner 
4812*9e54973fSEric Joyner 	cmd->cluster_id = CPU_TO_LE16(cluster_id);
481356429daeSEric Joyner 	cmd->table_id = CPU_TO_LE16(table_id);
481456429daeSEric Joyner 	cmd->idx = CPU_TO_LE32(start);
481556429daeSEric Joyner 
481656429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
481756429daeSEric Joyner 
481856429daeSEric Joyner 	if (!status) {
481956429daeSEric Joyner 		if (ret_buf_size)
482056429daeSEric Joyner 			*ret_buf_size = LE16_TO_CPU(desc.datalen);
4821*9e54973fSEric Joyner 		if (ret_next_cluster)
4822*9e54973fSEric Joyner 			*ret_next_cluster = LE16_TO_CPU(cmd->cluster_id);
482356429daeSEric Joyner 		if (ret_next_table)
482456429daeSEric Joyner 			*ret_next_table = LE16_TO_CPU(cmd->table_id);
482556429daeSEric Joyner 		if (ret_next_index)
482656429daeSEric Joyner 			*ret_next_index = LE32_TO_CPU(cmd->idx);
482756429daeSEric Joyner 	}
482856429daeSEric Joyner 
482956429daeSEric Joyner 	return status;
483056429daeSEric Joyner }
483156429daeSEric Joyner 
483256429daeSEric Joyner /**
483371d10453SEric Joyner  * ice_read_byte - read context byte into struct
483471d10453SEric Joyner  * @src_ctx:  the context structure to read from
483571d10453SEric Joyner  * @dest_ctx: the context to be written to
483671d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
483771d10453SEric Joyner  */
483871d10453SEric Joyner static void
48399dc2f6e2SEric Joyner ice_read_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
484071d10453SEric Joyner {
484171d10453SEric Joyner 	u8 dest_byte, mask;
484271d10453SEric Joyner 	u8 *src, *target;
484371d10453SEric Joyner 	u16 shift_width;
484471d10453SEric Joyner 
484571d10453SEric Joyner 	/* prepare the bits and mask */
484671d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
484771d10453SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
484871d10453SEric Joyner 
484971d10453SEric Joyner 	/* shift to correct alignment */
485071d10453SEric Joyner 	mask <<= shift_width;
485171d10453SEric Joyner 
485271d10453SEric Joyner 	/* get the current bits from the src bit string */
485371d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
485471d10453SEric Joyner 
485571d10453SEric Joyner 	ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_DMA_TO_NONDMA);
485671d10453SEric Joyner 
48579dc2f6e2SEric Joyner 	dest_byte &= mask;
485871d10453SEric Joyner 
485971d10453SEric Joyner 	dest_byte >>= shift_width;
486071d10453SEric Joyner 
486171d10453SEric Joyner 	/* get the address from the struct field */
486271d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
486371d10453SEric Joyner 
486471d10453SEric Joyner 	/* put it back in the struct */
486571d10453SEric Joyner 	ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA);
486671d10453SEric Joyner }
486771d10453SEric Joyner 
486871d10453SEric Joyner /**
486971d10453SEric Joyner  * ice_read_word - read context word into struct
487071d10453SEric Joyner  * @src_ctx:  the context structure to read from
487171d10453SEric Joyner  * @dest_ctx: the context to be written to
487271d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
487371d10453SEric Joyner  */
487471d10453SEric Joyner static void
48759dc2f6e2SEric Joyner ice_read_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
487671d10453SEric Joyner {
487771d10453SEric Joyner 	u16 dest_word, mask;
487871d10453SEric Joyner 	u8 *src, *target;
487971d10453SEric Joyner 	__le16 src_word;
488071d10453SEric Joyner 	u16 shift_width;
488171d10453SEric Joyner 
488271d10453SEric Joyner 	/* prepare the bits and mask */
488371d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
488471d10453SEric Joyner 	mask = BIT(ce_info->width) - 1;
488571d10453SEric Joyner 
488671d10453SEric Joyner 	/* shift to correct alignment */
488771d10453SEric Joyner 	mask <<= shift_width;
488871d10453SEric Joyner 
488971d10453SEric Joyner 	/* get the current bits from the src bit string */
489071d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
489171d10453SEric Joyner 
489271d10453SEric Joyner 	ice_memcpy(&src_word, src, sizeof(src_word), ICE_DMA_TO_NONDMA);
489371d10453SEric Joyner 
489471d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
489571d10453SEric Joyner 	 * correctly
489671d10453SEric Joyner 	 */
48979dc2f6e2SEric Joyner 	src_word &= CPU_TO_LE16(mask);
489871d10453SEric Joyner 
489971d10453SEric Joyner 	/* get the data back into host order before shifting */
490071d10453SEric Joyner 	dest_word = LE16_TO_CPU(src_word);
490171d10453SEric Joyner 
490271d10453SEric Joyner 	dest_word >>= shift_width;
490371d10453SEric Joyner 
490471d10453SEric Joyner 	/* get the address from the struct field */
490571d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
490671d10453SEric Joyner 
490771d10453SEric Joyner 	/* put it back in the struct */
490871d10453SEric Joyner 	ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA);
490971d10453SEric Joyner }
491071d10453SEric Joyner 
491171d10453SEric Joyner /**
491271d10453SEric Joyner  * ice_read_dword - read context dword into struct
491371d10453SEric Joyner  * @src_ctx:  the context structure to read from
491471d10453SEric Joyner  * @dest_ctx: the context to be written to
491571d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
491671d10453SEric Joyner  */
491771d10453SEric Joyner static void
49189dc2f6e2SEric Joyner ice_read_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
491971d10453SEric Joyner {
492071d10453SEric Joyner 	u32 dest_dword, mask;
492171d10453SEric Joyner 	__le32 src_dword;
492271d10453SEric Joyner 	u8 *src, *target;
492371d10453SEric Joyner 	u16 shift_width;
492471d10453SEric Joyner 
492571d10453SEric Joyner 	/* prepare the bits and mask */
492671d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
492771d10453SEric Joyner 
492871d10453SEric Joyner 	/* if the field width is exactly 32 on an x86 machine, then the shift
492971d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
493071d10453SEric Joyner 	 * to 5 bits so the shift will do nothing
493171d10453SEric Joyner 	 */
493271d10453SEric Joyner 	if (ce_info->width < 32)
493371d10453SEric Joyner 		mask = BIT(ce_info->width) - 1;
493471d10453SEric Joyner 	else
493571d10453SEric Joyner 		mask = (u32)~0;
493671d10453SEric Joyner 
493771d10453SEric Joyner 	/* shift to correct alignment */
493871d10453SEric Joyner 	mask <<= shift_width;
493971d10453SEric Joyner 
494071d10453SEric Joyner 	/* get the current bits from the src bit string */
494171d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
494271d10453SEric Joyner 
494371d10453SEric Joyner 	ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_DMA_TO_NONDMA);
494471d10453SEric Joyner 
494571d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
494671d10453SEric Joyner 	 * correctly
494771d10453SEric Joyner 	 */
49489dc2f6e2SEric Joyner 	src_dword &= CPU_TO_LE32(mask);
494971d10453SEric Joyner 
495071d10453SEric Joyner 	/* get the data back into host order before shifting */
495171d10453SEric Joyner 	dest_dword = LE32_TO_CPU(src_dword);
495271d10453SEric Joyner 
495371d10453SEric Joyner 	dest_dword >>= shift_width;
495471d10453SEric Joyner 
495571d10453SEric Joyner 	/* get the address from the struct field */
495671d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
495771d10453SEric Joyner 
495871d10453SEric Joyner 	/* put it back in the struct */
495971d10453SEric Joyner 	ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA);
496071d10453SEric Joyner }
496171d10453SEric Joyner 
496271d10453SEric Joyner /**
496371d10453SEric Joyner  * ice_read_qword - read context qword into struct
496471d10453SEric Joyner  * @src_ctx:  the context structure to read from
496571d10453SEric Joyner  * @dest_ctx: the context to be written to
496671d10453SEric Joyner  * @ce_info:  a description of the struct to be filled
496771d10453SEric Joyner  */
496871d10453SEric Joyner static void
49699dc2f6e2SEric Joyner ice_read_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
497071d10453SEric Joyner {
497171d10453SEric Joyner 	u64 dest_qword, mask;
497271d10453SEric Joyner 	__le64 src_qword;
497371d10453SEric Joyner 	u8 *src, *target;
497471d10453SEric Joyner 	u16 shift_width;
497571d10453SEric Joyner 
497671d10453SEric Joyner 	/* prepare the bits and mask */
497771d10453SEric Joyner 	shift_width = ce_info->lsb % 8;
497871d10453SEric Joyner 
497971d10453SEric Joyner 	/* if the field width is exactly 64 on an x86 machine, then the shift
498071d10453SEric Joyner 	 * operation will not work because the SHL instructions count is masked
498171d10453SEric Joyner 	 * to 6 bits so the shift will do nothing
498271d10453SEric Joyner 	 */
498371d10453SEric Joyner 	if (ce_info->width < 64)
498471d10453SEric Joyner 		mask = BIT_ULL(ce_info->width) - 1;
498571d10453SEric Joyner 	else
498671d10453SEric Joyner 		mask = (u64)~0;
498771d10453SEric Joyner 
498871d10453SEric Joyner 	/* shift to correct alignment */
498971d10453SEric Joyner 	mask <<= shift_width;
499071d10453SEric Joyner 
499171d10453SEric Joyner 	/* get the current bits from the src bit string */
499271d10453SEric Joyner 	src = src_ctx + (ce_info->lsb / 8);
499371d10453SEric Joyner 
499471d10453SEric Joyner 	ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_DMA_TO_NONDMA);
499571d10453SEric Joyner 
499671d10453SEric Joyner 	/* the data in the memory is stored as little endian so mask it
499771d10453SEric Joyner 	 * correctly
499871d10453SEric Joyner 	 */
49999dc2f6e2SEric Joyner 	src_qword &= CPU_TO_LE64(mask);
500071d10453SEric Joyner 
500171d10453SEric Joyner 	/* get the data back into host order before shifting */
500271d10453SEric Joyner 	dest_qword = LE64_TO_CPU(src_qword);
500371d10453SEric Joyner 
500471d10453SEric Joyner 	dest_qword >>= shift_width;
500571d10453SEric Joyner 
500671d10453SEric Joyner 	/* get the address from the struct field */
500771d10453SEric Joyner 	target = dest_ctx + ce_info->offset;
500871d10453SEric Joyner 
500971d10453SEric Joyner 	/* put it back in the struct */
501071d10453SEric Joyner 	ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA);
501171d10453SEric Joyner }
501271d10453SEric Joyner 
501371d10453SEric Joyner /**
501471d10453SEric Joyner  * ice_get_ctx - extract context bits from a packed structure
501571d10453SEric Joyner  * @src_ctx:  pointer to a generic packed context structure
501671d10453SEric Joyner  * @dest_ctx: pointer to a generic non-packed context structure
501771d10453SEric Joyner  * @ce_info:  a description of the structure to be read from
501871d10453SEric Joyner  */
501971d10453SEric Joyner enum ice_status
50209dc2f6e2SEric Joyner ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
502171d10453SEric Joyner {
502271d10453SEric Joyner 	int f;
502371d10453SEric Joyner 
502471d10453SEric Joyner 	for (f = 0; ce_info[f].width; f++) {
502571d10453SEric Joyner 		switch (ce_info[f].size_of) {
502671d10453SEric Joyner 		case 1:
502771d10453SEric Joyner 			ice_read_byte(src_ctx, dest_ctx, &ce_info[f]);
502871d10453SEric Joyner 			break;
502971d10453SEric Joyner 		case 2:
503071d10453SEric Joyner 			ice_read_word(src_ctx, dest_ctx, &ce_info[f]);
503171d10453SEric Joyner 			break;
503271d10453SEric Joyner 		case 4:
503371d10453SEric Joyner 			ice_read_dword(src_ctx, dest_ctx, &ce_info[f]);
503471d10453SEric Joyner 			break;
503571d10453SEric Joyner 		case 8:
503671d10453SEric Joyner 			ice_read_qword(src_ctx, dest_ctx, &ce_info[f]);
503771d10453SEric Joyner 			break;
503871d10453SEric Joyner 		default:
503971d10453SEric Joyner 			/* nothing to do, just keep going */
504071d10453SEric Joyner 			break;
504171d10453SEric Joyner 		}
504271d10453SEric Joyner 	}
504371d10453SEric Joyner 
504471d10453SEric Joyner 	return ICE_SUCCESS;
504571d10453SEric Joyner }
504671d10453SEric Joyner 
504771d10453SEric Joyner /**
504871d10453SEric Joyner  * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
504971d10453SEric Joyner  * @hw: pointer to the HW struct
505071d10453SEric Joyner  * @vsi_handle: software VSI handle
505171d10453SEric Joyner  * @tc: TC number
505271d10453SEric Joyner  * @q_handle: software queue handle
505371d10453SEric Joyner  */
505471d10453SEric Joyner struct ice_q_ctx *
505571d10453SEric Joyner ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
505671d10453SEric Joyner {
505771d10453SEric Joyner 	struct ice_vsi_ctx *vsi;
505871d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
505971d10453SEric Joyner 
506071d10453SEric Joyner 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
506171d10453SEric Joyner 	if (!vsi)
506271d10453SEric Joyner 		return NULL;
506371d10453SEric Joyner 	if (q_handle >= vsi->num_lan_q_entries[tc])
506471d10453SEric Joyner 		return NULL;
506571d10453SEric Joyner 	if (!vsi->lan_q_ctx[tc])
506671d10453SEric Joyner 		return NULL;
506771d10453SEric Joyner 	q_ctx = vsi->lan_q_ctx[tc];
506871d10453SEric Joyner 	return &q_ctx[q_handle];
506971d10453SEric Joyner }
507071d10453SEric Joyner 
507171d10453SEric Joyner /**
507271d10453SEric Joyner  * ice_ena_vsi_txq
507371d10453SEric Joyner  * @pi: port information structure
507471d10453SEric Joyner  * @vsi_handle: software VSI handle
507571d10453SEric Joyner  * @tc: TC number
507671d10453SEric Joyner  * @q_handle: software queue handle
507771d10453SEric Joyner  * @num_qgrps: Number of added queue groups
507871d10453SEric Joyner  * @buf: list of queue groups to be added
507971d10453SEric Joyner  * @buf_size: size of buffer for indirect command
508071d10453SEric Joyner  * @cd: pointer to command details structure or NULL
508171d10453SEric Joyner  *
508271d10453SEric Joyner  * This function adds one LAN queue
508371d10453SEric Joyner  */
508471d10453SEric Joyner enum ice_status
508571d10453SEric Joyner ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
508671d10453SEric Joyner 		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
508771d10453SEric Joyner 		struct ice_sq_cd *cd)
508871d10453SEric Joyner {
508971d10453SEric Joyner 	struct ice_aqc_txsched_elem_data node = { 0 };
509071d10453SEric Joyner 	struct ice_sched_node *parent;
509171d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
509271d10453SEric Joyner 	enum ice_status status;
509371d10453SEric Joyner 	struct ice_hw *hw;
509471d10453SEric Joyner 
509571d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
509671d10453SEric Joyner 		return ICE_ERR_CFG;
509771d10453SEric Joyner 
509871d10453SEric Joyner 	if (num_qgrps > 1 || buf->num_txqs > 1)
509971d10453SEric Joyner 		return ICE_ERR_MAX_LIMIT;
510071d10453SEric Joyner 
510171d10453SEric Joyner 	hw = pi->hw;
510271d10453SEric Joyner 
510371d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
510471d10453SEric Joyner 		return ICE_ERR_PARAM;
510571d10453SEric Joyner 
510671d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
510771d10453SEric Joyner 
510871d10453SEric Joyner 	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
510971d10453SEric Joyner 	if (!q_ctx) {
511071d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
511171d10453SEric Joyner 			  q_handle);
511271d10453SEric Joyner 		status = ICE_ERR_PARAM;
511371d10453SEric Joyner 		goto ena_txq_exit;
511471d10453SEric Joyner 	}
511571d10453SEric Joyner 
511671d10453SEric Joyner 	/* find a parent node */
511771d10453SEric Joyner 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
511871d10453SEric Joyner 					    ICE_SCHED_NODE_OWNER_LAN);
511971d10453SEric Joyner 	if (!parent) {
512071d10453SEric Joyner 		status = ICE_ERR_PARAM;
512171d10453SEric Joyner 		goto ena_txq_exit;
512271d10453SEric Joyner 	}
512371d10453SEric Joyner 
512471d10453SEric Joyner 	buf->parent_teid = parent->info.node_teid;
512571d10453SEric Joyner 	node.parent_teid = parent->info.node_teid;
512671d10453SEric Joyner 	/* Mark that the values in the "generic" section as valid. The default
512771d10453SEric Joyner 	 * value in the "generic" section is zero. This means that :
512871d10453SEric Joyner 	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
512971d10453SEric Joyner 	 * - 0 priority among siblings, indicated by Bit 1-3.
513071d10453SEric Joyner 	 * - WFQ, indicated by Bit 4.
513171d10453SEric Joyner 	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
513271d10453SEric Joyner 	 * Bit 5-6.
513371d10453SEric Joyner 	 * - Bit 7 is reserved.
513471d10453SEric Joyner 	 * Without setting the generic section as valid in valid_sections, the
513571d10453SEric Joyner 	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
513671d10453SEric Joyner 	 */
51377d7af7f8SEric Joyner 	buf->txqs[0].info.valid_sections =
51387d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
51397d7af7f8SEric Joyner 		ICE_AQC_ELEM_VALID_EIR;
51407d7af7f8SEric Joyner 	buf->txqs[0].info.generic = 0;
51417d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_profile_idx =
51427d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
51437d7af7f8SEric Joyner 	buf->txqs[0].info.cir_bw.bw_alloc =
51447d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
51457d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_profile_idx =
51467d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
51477d7af7f8SEric Joyner 	buf->txqs[0].info.eir_bw.bw_alloc =
51487d7af7f8SEric Joyner 		CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
514971d10453SEric Joyner 
515071d10453SEric Joyner 	/* add the LAN queue */
515171d10453SEric Joyner 	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
515271d10453SEric Joyner 	if (status != ICE_SUCCESS) {
515371d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
515471d10453SEric Joyner 			  LE16_TO_CPU(buf->txqs[0].txq_id),
515571d10453SEric Joyner 			  hw->adminq.sq_last_status);
515671d10453SEric Joyner 		goto ena_txq_exit;
515771d10453SEric Joyner 	}
515871d10453SEric Joyner 
515971d10453SEric Joyner 	node.node_teid = buf->txqs[0].q_teid;
516071d10453SEric Joyner 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
516171d10453SEric Joyner 	q_ctx->q_handle = q_handle;
516271d10453SEric Joyner 	q_ctx->q_teid = LE32_TO_CPU(node.node_teid);
516371d10453SEric Joyner 
516471d10453SEric Joyner 	/* add a leaf node into scheduler tree queue layer */
51659c30461dSEric Joyner 	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node, NULL);
516671d10453SEric Joyner 	if (!status)
516771d10453SEric Joyner 		status = ice_sched_replay_q_bw(pi, q_ctx);
516871d10453SEric Joyner 
516971d10453SEric Joyner ena_txq_exit:
517071d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
517171d10453SEric Joyner 	return status;
517271d10453SEric Joyner }
517371d10453SEric Joyner 
517471d10453SEric Joyner /**
517571d10453SEric Joyner  * ice_dis_vsi_txq
517671d10453SEric Joyner  * @pi: port information structure
517771d10453SEric Joyner  * @vsi_handle: software VSI handle
517871d10453SEric Joyner  * @tc: TC number
517971d10453SEric Joyner  * @num_queues: number of queues
518071d10453SEric Joyner  * @q_handles: pointer to software queue handle array
518171d10453SEric Joyner  * @q_ids: pointer to the q_id array
518271d10453SEric Joyner  * @q_teids: pointer to queue node teids
518371d10453SEric Joyner  * @rst_src: if called due to reset, specifies the reset source
518471d10453SEric Joyner  * @vmvf_num: the relative VM or VF number that is undergoing the reset
518571d10453SEric Joyner  * @cd: pointer to command details structure or NULL
518671d10453SEric Joyner  *
518771d10453SEric Joyner  * This function removes queues and their corresponding nodes in SW DB
518871d10453SEric Joyner  */
518971d10453SEric Joyner enum ice_status
519071d10453SEric Joyner ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
519171d10453SEric Joyner 		u16 *q_handles, u16 *q_ids, u32 *q_teids,
519271d10453SEric Joyner 		enum ice_disq_rst_src rst_src, u16 vmvf_num,
519371d10453SEric Joyner 		struct ice_sq_cd *cd)
519471d10453SEric Joyner {
519571d10453SEric Joyner 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
51967d7af7f8SEric Joyner 	struct ice_aqc_dis_txq_item *qg_list;
519771d10453SEric Joyner 	struct ice_q_ctx *q_ctx;
51987d7af7f8SEric Joyner 	struct ice_hw *hw;
51997d7af7f8SEric Joyner 	u16 i, buf_size;
520071d10453SEric Joyner 
520171d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
520271d10453SEric Joyner 		return ICE_ERR_CFG;
520371d10453SEric Joyner 
52047d7af7f8SEric Joyner 	hw = pi->hw;
52057d7af7f8SEric Joyner 
520671d10453SEric Joyner 	if (!num_queues) {
520771d10453SEric Joyner 		/* if queue is disabled already yet the disable queue command
520871d10453SEric Joyner 		 * has to be sent to complete the VF reset, then call
520971d10453SEric Joyner 		 * ice_aq_dis_lan_txq without any queue information
521071d10453SEric Joyner 		 */
521171d10453SEric Joyner 		if (rst_src)
52127d7af7f8SEric Joyner 			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
521371d10453SEric Joyner 						  vmvf_num, NULL);
521471d10453SEric Joyner 		return ICE_ERR_CFG;
521571d10453SEric Joyner 	}
521671d10453SEric Joyner 
52177d7af7f8SEric Joyner 	buf_size = ice_struct_size(qg_list, q_id, 1);
52187d7af7f8SEric Joyner 	qg_list = (struct ice_aqc_dis_txq_item *)ice_malloc(hw, buf_size);
52197d7af7f8SEric Joyner 	if (!qg_list)
52207d7af7f8SEric Joyner 		return ICE_ERR_NO_MEMORY;
52217d7af7f8SEric Joyner 
522271d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
522371d10453SEric Joyner 
522471d10453SEric Joyner 	for (i = 0; i < num_queues; i++) {
522571d10453SEric Joyner 		struct ice_sched_node *node;
522671d10453SEric Joyner 
522771d10453SEric Joyner 		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
522871d10453SEric Joyner 		if (!node)
522971d10453SEric Joyner 			continue;
52307d7af7f8SEric Joyner 		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
523171d10453SEric Joyner 		if (!q_ctx) {
52327d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
523371d10453SEric Joyner 				  q_handles[i]);
523471d10453SEric Joyner 			continue;
523571d10453SEric Joyner 		}
523671d10453SEric Joyner 		if (q_ctx->q_handle != q_handles[i]) {
52377d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
523871d10453SEric Joyner 				  q_ctx->q_handle, q_handles[i]);
523971d10453SEric Joyner 			continue;
524071d10453SEric Joyner 		}
52417d7af7f8SEric Joyner 		qg_list->parent_teid = node->info.parent_teid;
52427d7af7f8SEric Joyner 		qg_list->num_qs = 1;
52437d7af7f8SEric Joyner 		qg_list->q_id[0] = CPU_TO_LE16(q_ids[i]);
52447d7af7f8SEric Joyner 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
52457d7af7f8SEric Joyner 					    vmvf_num, cd);
524671d10453SEric Joyner 
524771d10453SEric Joyner 		if (status != ICE_SUCCESS)
524871d10453SEric Joyner 			break;
524971d10453SEric Joyner 		ice_free_sched_node(pi, node);
525071d10453SEric Joyner 		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
525171d10453SEric Joyner 	}
525271d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
52537d7af7f8SEric Joyner 	ice_free(hw, qg_list);
525471d10453SEric Joyner 	return status;
525571d10453SEric Joyner }
525671d10453SEric Joyner 
525771d10453SEric Joyner /**
525871d10453SEric Joyner  * ice_cfg_vsi_qs - configure the new/existing VSI queues
525971d10453SEric Joyner  * @pi: port information structure
526071d10453SEric Joyner  * @vsi_handle: software VSI handle
526171d10453SEric Joyner  * @tc_bitmap: TC bitmap
526271d10453SEric Joyner  * @maxqs: max queues array per TC
526371d10453SEric Joyner  * @owner: LAN or RDMA
526471d10453SEric Joyner  *
526571d10453SEric Joyner  * This function adds/updates the VSI queues per TC.
526671d10453SEric Joyner  */
526771d10453SEric Joyner static enum ice_status
526871d10453SEric Joyner ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
526971d10453SEric Joyner 	       u16 *maxqs, u8 owner)
527071d10453SEric Joyner {
527171d10453SEric Joyner 	enum ice_status status = ICE_SUCCESS;
527271d10453SEric Joyner 	u8 i;
527371d10453SEric Joyner 
527471d10453SEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
527571d10453SEric Joyner 		return ICE_ERR_CFG;
527671d10453SEric Joyner 
527771d10453SEric Joyner 	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
527871d10453SEric Joyner 		return ICE_ERR_PARAM;
527971d10453SEric Joyner 
528071d10453SEric Joyner 	ice_acquire_lock(&pi->sched_lock);
528171d10453SEric Joyner 
528271d10453SEric Joyner 	ice_for_each_traffic_class(i) {
528371d10453SEric Joyner 		/* configuration is possible only if TC node is present */
528471d10453SEric Joyner 		if (!ice_sched_get_tc_node(pi, i))
528571d10453SEric Joyner 			continue;
528671d10453SEric Joyner 
528771d10453SEric Joyner 		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
528871d10453SEric Joyner 					   ice_is_tc_ena(tc_bitmap, i));
528971d10453SEric Joyner 		if (status)
529071d10453SEric Joyner 			break;
529171d10453SEric Joyner 	}
529271d10453SEric Joyner 
529371d10453SEric Joyner 	ice_release_lock(&pi->sched_lock);
529471d10453SEric Joyner 	return status;
529571d10453SEric Joyner }
529671d10453SEric Joyner 
529771d10453SEric Joyner /**
529871d10453SEric Joyner  * ice_cfg_vsi_lan - configure VSI LAN queues
529971d10453SEric Joyner  * @pi: port information structure
530071d10453SEric Joyner  * @vsi_handle: software VSI handle
530171d10453SEric Joyner  * @tc_bitmap: TC bitmap
530271d10453SEric Joyner  * @max_lanqs: max LAN queues array per TC
530371d10453SEric Joyner  *
530471d10453SEric Joyner  * This function adds/updates the VSI LAN queues per TC.
530571d10453SEric Joyner  */
530671d10453SEric Joyner enum ice_status
530771d10453SEric Joyner ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
530871d10453SEric Joyner 		u16 *max_lanqs)
530971d10453SEric Joyner {
531071d10453SEric Joyner 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
531171d10453SEric Joyner 			      ICE_SCHED_NODE_OWNER_LAN);
531271d10453SEric Joyner }
531371d10453SEric Joyner 
531471d10453SEric Joyner /**
53158a13362dSEric Joyner  * ice_cfg_vsi_rdma - configure the VSI RDMA queues
53168a13362dSEric Joyner  * @pi: port information structure
53178a13362dSEric Joyner  * @vsi_handle: software VSI handle
53188a13362dSEric Joyner  * @tc_bitmap: TC bitmap
53198a13362dSEric Joyner  * @max_rdmaqs: max RDMA queues array per TC
53208a13362dSEric Joyner  *
53218a13362dSEric Joyner  * This function adds/updates the VSI RDMA queues per TC.
53228a13362dSEric Joyner  */
53238a13362dSEric Joyner enum ice_status
53248a13362dSEric Joyner ice_cfg_vsi_rdma(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
53258a13362dSEric Joyner 		 u16 *max_rdmaqs)
53268a13362dSEric Joyner {
53278a13362dSEric Joyner 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_rdmaqs,
53288a13362dSEric Joyner 			      ICE_SCHED_NODE_OWNER_RDMA);
53298a13362dSEric Joyner }
53308a13362dSEric Joyner 
53318a13362dSEric Joyner /**
53328a13362dSEric Joyner  * ice_ena_vsi_rdma_qset
53338a13362dSEric Joyner  * @pi: port information structure
53348a13362dSEric Joyner  * @vsi_handle: software VSI handle
53358a13362dSEric Joyner  * @tc: TC number
53368a13362dSEric Joyner  * @rdma_qset: pointer to RDMA qset
53378a13362dSEric Joyner  * @num_qsets: number of RDMA qsets
53388a13362dSEric Joyner  * @qset_teid: pointer to qset node teids
53398a13362dSEric Joyner  *
53408a13362dSEric Joyner  * This function adds RDMA qset
53418a13362dSEric Joyner  */
53428a13362dSEric Joyner enum ice_status
53438a13362dSEric Joyner ice_ena_vsi_rdma_qset(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
53448a13362dSEric Joyner 		      u16 *rdma_qset, u16 num_qsets, u32 *qset_teid)
53458a13362dSEric Joyner {
53468a13362dSEric Joyner 	struct ice_aqc_txsched_elem_data node = { 0 };
53478a13362dSEric Joyner 	struct ice_aqc_add_rdma_qset_data *buf;
53488a13362dSEric Joyner 	struct ice_sched_node *parent;
53498a13362dSEric Joyner 	enum ice_status status;
53508a13362dSEric Joyner 	struct ice_hw *hw;
53518a13362dSEric Joyner 	u16 i, buf_size;
53528a13362dSEric Joyner 
53538a13362dSEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
53548a13362dSEric Joyner 		return ICE_ERR_CFG;
53558a13362dSEric Joyner 	hw = pi->hw;
53568a13362dSEric Joyner 
53578a13362dSEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
53588a13362dSEric Joyner 		return ICE_ERR_PARAM;
53598a13362dSEric Joyner 
53608a13362dSEric Joyner 	buf_size = ice_struct_size(buf, rdma_qsets, num_qsets);
53618a13362dSEric Joyner 	buf = (struct ice_aqc_add_rdma_qset_data *)ice_malloc(hw, buf_size);
53628a13362dSEric Joyner 	if (!buf)
53638a13362dSEric Joyner 		return ICE_ERR_NO_MEMORY;
53648a13362dSEric Joyner 	ice_acquire_lock(&pi->sched_lock);
53658a13362dSEric Joyner 
53668a13362dSEric Joyner 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
53678a13362dSEric Joyner 					    ICE_SCHED_NODE_OWNER_RDMA);
53688a13362dSEric Joyner 	if (!parent) {
53698a13362dSEric Joyner 		status = ICE_ERR_PARAM;
53708a13362dSEric Joyner 		goto rdma_error_exit;
53718a13362dSEric Joyner 	}
53728a13362dSEric Joyner 	buf->parent_teid = parent->info.node_teid;
53738a13362dSEric Joyner 	node.parent_teid = parent->info.node_teid;
53748a13362dSEric Joyner 
53758a13362dSEric Joyner 	buf->num_qsets = CPU_TO_LE16(num_qsets);
53768a13362dSEric Joyner 	for (i = 0; i < num_qsets; i++) {
53778a13362dSEric Joyner 		buf->rdma_qsets[i].tx_qset_id = CPU_TO_LE16(rdma_qset[i]);
53788a13362dSEric Joyner 		buf->rdma_qsets[i].info.valid_sections =
53798a13362dSEric Joyner 			ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
53808a13362dSEric Joyner 			ICE_AQC_ELEM_VALID_EIR;
53818a13362dSEric Joyner 		buf->rdma_qsets[i].info.generic = 0;
53828a13362dSEric Joyner 		buf->rdma_qsets[i].info.cir_bw.bw_profile_idx =
53838a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
53848a13362dSEric Joyner 		buf->rdma_qsets[i].info.cir_bw.bw_alloc =
53858a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
53868a13362dSEric Joyner 		buf->rdma_qsets[i].info.eir_bw.bw_profile_idx =
53878a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
53888a13362dSEric Joyner 		buf->rdma_qsets[i].info.eir_bw.bw_alloc =
53898a13362dSEric Joyner 			CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
53908a13362dSEric Joyner 	}
53918a13362dSEric Joyner 	status = ice_aq_add_rdma_qsets(hw, 1, buf, buf_size, NULL);
53928a13362dSEric Joyner 	if (status != ICE_SUCCESS) {
53938a13362dSEric Joyner 		ice_debug(hw, ICE_DBG_RDMA, "add RDMA qset failed\n");
53948a13362dSEric Joyner 		goto rdma_error_exit;
53958a13362dSEric Joyner 	}
53968a13362dSEric Joyner 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
53978a13362dSEric Joyner 	for (i = 0; i < num_qsets; i++) {
53988a13362dSEric Joyner 		node.node_teid = buf->rdma_qsets[i].qset_teid;
53998a13362dSEric Joyner 		status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1,
54009c30461dSEric Joyner 					    &node, NULL);
54018a13362dSEric Joyner 		if (status)
54028a13362dSEric Joyner 			break;
54038a13362dSEric Joyner 		qset_teid[i] = LE32_TO_CPU(node.node_teid);
54048a13362dSEric Joyner 	}
54058a13362dSEric Joyner rdma_error_exit:
54068a13362dSEric Joyner 	ice_release_lock(&pi->sched_lock);
54078a13362dSEric Joyner 	ice_free(hw, buf);
54088a13362dSEric Joyner 	return status;
54098a13362dSEric Joyner }
54108a13362dSEric Joyner 
54118a13362dSEric Joyner /**
54128a13362dSEric Joyner  * ice_dis_vsi_rdma_qset - free RDMA resources
54138a13362dSEric Joyner  * @pi: port_info struct
54148a13362dSEric Joyner  * @count: number of RDMA qsets to free
54158a13362dSEric Joyner  * @qset_teid: TEID of qset node
54168a13362dSEric Joyner  * @q_id: list of queue IDs being disabled
54178a13362dSEric Joyner  */
54188a13362dSEric Joyner enum ice_status
54198a13362dSEric Joyner ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
54208a13362dSEric Joyner 		      u16 *q_id)
54218a13362dSEric Joyner {
54228a13362dSEric Joyner 	struct ice_aqc_dis_txq_item *qg_list;
54238a13362dSEric Joyner 	enum ice_status status = ICE_SUCCESS;
54248a13362dSEric Joyner 	struct ice_hw *hw;
54258a13362dSEric Joyner 	u16 qg_size;
54268a13362dSEric Joyner 	int i;
54278a13362dSEric Joyner 
54288a13362dSEric Joyner 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
54298a13362dSEric Joyner 		return ICE_ERR_CFG;
54308a13362dSEric Joyner 
54318a13362dSEric Joyner 	hw = pi->hw;
54328a13362dSEric Joyner 
54338a13362dSEric Joyner 	qg_size = ice_struct_size(qg_list, q_id, 1);
54348a13362dSEric Joyner 	qg_list = (struct ice_aqc_dis_txq_item *)ice_malloc(hw, qg_size);
54358a13362dSEric Joyner 	if (!qg_list)
54368a13362dSEric Joyner 		return ICE_ERR_NO_MEMORY;
54378a13362dSEric Joyner 
54388a13362dSEric Joyner 	ice_acquire_lock(&pi->sched_lock);
54398a13362dSEric Joyner 
54408a13362dSEric Joyner 	for (i = 0; i < count; i++) {
54418a13362dSEric Joyner 		struct ice_sched_node *node;
54428a13362dSEric Joyner 
54438a13362dSEric Joyner 		node = ice_sched_find_node_by_teid(pi->root, qset_teid[i]);
54448a13362dSEric Joyner 		if (!node)
54458a13362dSEric Joyner 			continue;
54468a13362dSEric Joyner 
54478a13362dSEric Joyner 		qg_list->parent_teid = node->info.parent_teid;
54488a13362dSEric Joyner 		qg_list->num_qs = 1;
54498a13362dSEric Joyner 		qg_list->q_id[0] =
54508a13362dSEric Joyner 			CPU_TO_LE16(q_id[i] |
54518a13362dSEric Joyner 				    ICE_AQC_Q_DIS_BUF_ELEM_TYPE_RDMA_QSET);
54528a13362dSEric Joyner 
54538a13362dSEric Joyner 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, qg_size,
54548a13362dSEric Joyner 					    ICE_NO_RESET, 0, NULL);
54558a13362dSEric Joyner 		if (status)
54568a13362dSEric Joyner 			break;
54578a13362dSEric Joyner 
54588a13362dSEric Joyner 		ice_free_sched_node(pi, node);
54598a13362dSEric Joyner 	}
54608a13362dSEric Joyner 
54618a13362dSEric Joyner 	ice_release_lock(&pi->sched_lock);
54628a13362dSEric Joyner 	ice_free(hw, qg_list);
54638a13362dSEric Joyner 	return status;
54648a13362dSEric Joyner }
54658a13362dSEric Joyner 
54668a13362dSEric Joyner /**
54679c30461dSEric Joyner  * ice_aq_get_sensor_reading
54689c30461dSEric Joyner  * @hw: pointer to the HW struct
54699c30461dSEric Joyner  * @sensor: sensor type
54709c30461dSEric Joyner  * @format: requested response format
54719c30461dSEric Joyner  * @data: pointer to data to be read from the sensor
54729c30461dSEric Joyner  * @cd: pointer to command details structure or NULL
54739c30461dSEric Joyner  *
54749c30461dSEric Joyner  * Get sensor reading (0x0632)
54759c30461dSEric Joyner  */
54769c30461dSEric Joyner enum ice_status
54779c30461dSEric Joyner ice_aq_get_sensor_reading(struct ice_hw *hw, u8 sensor, u8 format,
54789c30461dSEric Joyner 			  struct ice_aqc_get_sensor_reading_resp *data,
54799c30461dSEric Joyner 			  struct ice_sq_cd *cd)
54809c30461dSEric Joyner {
54819c30461dSEric Joyner 	struct ice_aqc_get_sensor_reading *cmd;
54829c30461dSEric Joyner 	struct ice_aq_desc desc;
54839c30461dSEric Joyner 	enum ice_status status;
54849c30461dSEric Joyner 
54859c30461dSEric Joyner 	if (!data)
54869c30461dSEric Joyner 		return ICE_ERR_PARAM;
54879c30461dSEric Joyner 
54889c30461dSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sensor_reading);
54899c30461dSEric Joyner 	cmd = &desc.params.get_sensor_reading;
54909c30461dSEric Joyner 	cmd->sensor = sensor;
54919c30461dSEric Joyner 	cmd->format = format;
54929c30461dSEric Joyner 
54939c30461dSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
54949c30461dSEric Joyner 
54959c30461dSEric Joyner 	if (!status)
54969c30461dSEric Joyner 		ice_memcpy(data, &desc.params.get_sensor_reading_resp,
54979c30461dSEric Joyner 			   sizeof(*data), ICE_NONDMA_TO_NONDMA);
54989c30461dSEric Joyner 
54999c30461dSEric Joyner 	return status;
55009c30461dSEric Joyner }
55019c30461dSEric Joyner 
55029c30461dSEric Joyner /**
55037d7af7f8SEric Joyner  * ice_is_main_vsi - checks whether the VSI is main VSI
55047d7af7f8SEric Joyner  * @hw: pointer to the HW struct
55057d7af7f8SEric Joyner  * @vsi_handle: VSI handle
55067d7af7f8SEric Joyner  *
55077d7af7f8SEric Joyner  * Checks whether the VSI is the main VSI (the first PF VSI created on
55087d7af7f8SEric Joyner  * given PF).
55097d7af7f8SEric Joyner  */
55107d7af7f8SEric Joyner static bool ice_is_main_vsi(struct ice_hw *hw, u16 vsi_handle)
55117d7af7f8SEric Joyner {
55127d7af7f8SEric Joyner 	return vsi_handle == ICE_MAIN_VSI_HANDLE && hw->vsi_ctx[vsi_handle];
55137d7af7f8SEric Joyner }
55147d7af7f8SEric Joyner 
55157d7af7f8SEric Joyner /**
551671d10453SEric Joyner  * ice_replay_pre_init - replay pre initialization
551771d10453SEric Joyner  * @hw: pointer to the HW struct
55187d7af7f8SEric Joyner  * @sw: pointer to switch info struct for which function initializes filters
551971d10453SEric Joyner  *
552071d10453SEric Joyner  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
552171d10453SEric Joyner  */
552256429daeSEric Joyner enum ice_status
55237d7af7f8SEric Joyner ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
552471d10453SEric Joyner {
55257d7af7f8SEric Joyner 	enum ice_status status;
552671d10453SEric Joyner 	u8 i;
552771d10453SEric Joyner 
552871d10453SEric Joyner 	/* Delete old entries from replay filter list head if there is any */
55297d7af7f8SEric Joyner 	ice_rm_sw_replay_rule_info(hw, sw);
553071d10453SEric Joyner 	/* In start of replay, move entries into replay_rules list, it
553171d10453SEric Joyner 	 * will allow adding rules entries back to filt_rules list,
553271d10453SEric Joyner 	 * which is operational list.
553371d10453SEric Joyner 	 */
553471d10453SEric Joyner 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++)
553571d10453SEric Joyner 		LIST_REPLACE_INIT(&sw->recp_list[i].filt_rules,
553671d10453SEric Joyner 				  &sw->recp_list[i].filt_replay_rules);
553771d10453SEric Joyner 	ice_sched_replay_agg_vsi_preinit(hw);
553871d10453SEric Joyner 
55397d7af7f8SEric Joyner 	status = ice_sched_replay_root_node_bw(hw->port_info);
55407d7af7f8SEric Joyner 	if (status)
55417d7af7f8SEric Joyner 		return status;
55427d7af7f8SEric Joyner 
554371d10453SEric Joyner 	return ice_sched_replay_tc_node_bw(hw->port_info);
554471d10453SEric Joyner }
554571d10453SEric Joyner 
554671d10453SEric Joyner /**
554771d10453SEric Joyner  * ice_replay_vsi - replay VSI configuration
554871d10453SEric Joyner  * @hw: pointer to the HW struct
554971d10453SEric Joyner  * @vsi_handle: driver VSI handle
555071d10453SEric Joyner  *
555171d10453SEric Joyner  * Restore all VSI configuration after reset. It is required to call this
555271d10453SEric Joyner  * function with main VSI first.
555371d10453SEric Joyner  */
555471d10453SEric Joyner enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
555571d10453SEric Joyner {
55567d7af7f8SEric Joyner 	struct ice_switch_info *sw = hw->switch_info;
55577d7af7f8SEric Joyner 	struct ice_port_info *pi = hw->port_info;
555871d10453SEric Joyner 	enum ice_status status;
555971d10453SEric Joyner 
556071d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
556171d10453SEric Joyner 		return ICE_ERR_PARAM;
556271d10453SEric Joyner 
556371d10453SEric Joyner 	/* Replay pre-initialization if there is any */
55647d7af7f8SEric Joyner 	if (ice_is_main_vsi(hw, vsi_handle)) {
55657d7af7f8SEric Joyner 		status = ice_replay_pre_init(hw, sw);
556671d10453SEric Joyner 		if (status)
556771d10453SEric Joyner 			return status;
556871d10453SEric Joyner 	}
556971d10453SEric Joyner 	/* Replay per VSI all RSS configurations */
557071d10453SEric Joyner 	status = ice_replay_rss_cfg(hw, vsi_handle);
557171d10453SEric Joyner 	if (status)
557271d10453SEric Joyner 		return status;
557371d10453SEric Joyner 	/* Replay per VSI all filters */
55747d7af7f8SEric Joyner 	status = ice_replay_vsi_all_fltr(hw, pi, vsi_handle);
557571d10453SEric Joyner 	if (!status)
557671d10453SEric Joyner 		status = ice_replay_vsi_agg(hw, vsi_handle);
557771d10453SEric Joyner 	return status;
557871d10453SEric Joyner }
557971d10453SEric Joyner 
558071d10453SEric Joyner /**
558171d10453SEric Joyner  * ice_replay_post - post replay configuration cleanup
558271d10453SEric Joyner  * @hw: pointer to the HW struct
558371d10453SEric Joyner  *
558471d10453SEric Joyner  * Post replay cleanup.
558571d10453SEric Joyner  */
558671d10453SEric Joyner void ice_replay_post(struct ice_hw *hw)
558771d10453SEric Joyner {
558871d10453SEric Joyner 	/* Delete old entries from replay filter list head */
558971d10453SEric Joyner 	ice_rm_all_sw_replay_rule_info(hw);
559071d10453SEric Joyner 	ice_sched_replay_agg(hw);
559171d10453SEric Joyner }
559271d10453SEric Joyner 
559371d10453SEric Joyner /**
559471d10453SEric Joyner  * ice_stat_update40 - read 40 bit stat from the chip and update stat values
559571d10453SEric Joyner  * @hw: ptr to the hardware info
559671d10453SEric Joyner  * @reg: offset of 64 bit HW register to read from
559771d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
559871d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
559971d10453SEric Joyner  * @cur_stat: ptr to current stat value
560071d10453SEric Joyner  */
560171d10453SEric Joyner void
560271d10453SEric Joyner ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
560371d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
560471d10453SEric Joyner {
560571d10453SEric Joyner 	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
560671d10453SEric Joyner 
560771d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
560871d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
560971d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
561071d10453SEric Joyner 	 * count up from zero.
561171d10453SEric Joyner 	 */
561271d10453SEric Joyner 	if (!prev_stat_loaded) {
561371d10453SEric Joyner 		*prev_stat = new_data;
561471d10453SEric Joyner 		return;
561571d10453SEric Joyner 	}
561671d10453SEric Joyner 
561771d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
561871d10453SEric Joyner 	 * add it to the software stat value.
561971d10453SEric Joyner 	 */
562071d10453SEric Joyner 	if (new_data >= *prev_stat)
562171d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
562271d10453SEric Joyner 	else
562371d10453SEric Joyner 		/* to manage the potential roll-over */
562471d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
562571d10453SEric Joyner 
562671d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
562771d10453SEric Joyner 	*prev_stat = new_data;
562871d10453SEric Joyner }
562971d10453SEric Joyner 
563071d10453SEric Joyner /**
563171d10453SEric Joyner  * ice_stat_update32 - read 32 bit stat from the chip and update stat values
563271d10453SEric Joyner  * @hw: ptr to the hardware info
563371d10453SEric Joyner  * @reg: offset of HW register to read from
563471d10453SEric Joyner  * @prev_stat_loaded: bool to specify if previous stats are loaded
563571d10453SEric Joyner  * @prev_stat: ptr to previous loaded stat value
563671d10453SEric Joyner  * @cur_stat: ptr to current stat value
563771d10453SEric Joyner  */
563871d10453SEric Joyner void
563971d10453SEric Joyner ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
564071d10453SEric Joyner 		  u64 *prev_stat, u64 *cur_stat)
564171d10453SEric Joyner {
564271d10453SEric Joyner 	u32 new_data;
564371d10453SEric Joyner 
564471d10453SEric Joyner 	new_data = rd32(hw, reg);
564571d10453SEric Joyner 
564671d10453SEric Joyner 	/* device stats are not reset at PFR, they likely will not be zeroed
564771d10453SEric Joyner 	 * when the driver starts. Thus, save the value from the first read
564871d10453SEric Joyner 	 * without adding to the statistic value so that we report stats which
564971d10453SEric Joyner 	 * count up from zero.
565071d10453SEric Joyner 	 */
565171d10453SEric Joyner 	if (!prev_stat_loaded) {
565271d10453SEric Joyner 		*prev_stat = new_data;
565371d10453SEric Joyner 		return;
565471d10453SEric Joyner 	}
565571d10453SEric Joyner 
565671d10453SEric Joyner 	/* Calculate the difference between the new and old values, and then
565771d10453SEric Joyner 	 * add it to the software stat value.
565871d10453SEric Joyner 	 */
565971d10453SEric Joyner 	if (new_data >= *prev_stat)
566071d10453SEric Joyner 		*cur_stat += new_data - *prev_stat;
566171d10453SEric Joyner 	else
566271d10453SEric Joyner 		/* to manage the potential roll-over */
566371d10453SEric Joyner 		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
566471d10453SEric Joyner 
566571d10453SEric Joyner 	/* Update the previously stored value to prepare for next read */
566671d10453SEric Joyner 	*prev_stat = new_data;
566771d10453SEric Joyner }
566871d10453SEric Joyner 
566971d10453SEric Joyner /**
567071d10453SEric Joyner  * ice_stat_update_repc - read GLV_REPC stats from chip and update stat values
567171d10453SEric Joyner  * @hw: ptr to the hardware info
567271d10453SEric Joyner  * @vsi_handle: VSI handle
567371d10453SEric Joyner  * @prev_stat_loaded: bool to specify if the previous stat values are loaded
567471d10453SEric Joyner  * @cur_stats: ptr to current stats structure
567571d10453SEric Joyner  *
567671d10453SEric Joyner  * The GLV_REPC statistic register actually tracks two 16bit statistics, and
567771d10453SEric Joyner  * thus cannot be read using the normal ice_stat_update32 function.
567871d10453SEric Joyner  *
567971d10453SEric Joyner  * Read the GLV_REPC register associated with the given VSI, and update the
568071d10453SEric Joyner  * rx_no_desc and rx_error values in the ice_eth_stats structure.
568171d10453SEric Joyner  *
568271d10453SEric Joyner  * Because the statistics in GLV_REPC stick at 0xFFFF, the register must be
568371d10453SEric Joyner  * cleared each time it's read.
568471d10453SEric Joyner  *
568571d10453SEric Joyner  * Note that the GLV_RDPC register also counts the causes that would trigger
568671d10453SEric Joyner  * GLV_REPC. However, it does not give the finer grained detail about why the
568771d10453SEric Joyner  * packets are being dropped. The GLV_REPC values can be used to distinguish
568871d10453SEric Joyner  * whether Rx packets are dropped due to errors or due to no available
568971d10453SEric Joyner  * descriptors.
569071d10453SEric Joyner  */
569171d10453SEric Joyner void
569271d10453SEric Joyner ice_stat_update_repc(struct ice_hw *hw, u16 vsi_handle, bool prev_stat_loaded,
569371d10453SEric Joyner 		     struct ice_eth_stats *cur_stats)
569471d10453SEric Joyner {
569571d10453SEric Joyner 	u16 vsi_num, no_desc, error_cnt;
569671d10453SEric Joyner 	u32 repc;
569771d10453SEric Joyner 
569871d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
569971d10453SEric Joyner 		return;
570071d10453SEric Joyner 
570171d10453SEric Joyner 	vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
570271d10453SEric Joyner 
570371d10453SEric Joyner 	/* If we haven't loaded stats yet, just clear the current value */
570471d10453SEric Joyner 	if (!prev_stat_loaded) {
570571d10453SEric Joyner 		wr32(hw, GLV_REPC(vsi_num), 0);
570671d10453SEric Joyner 		return;
570771d10453SEric Joyner 	}
570871d10453SEric Joyner 
570971d10453SEric Joyner 	repc = rd32(hw, GLV_REPC(vsi_num));
571071d10453SEric Joyner 	no_desc = (repc & GLV_REPC_NO_DESC_CNT_M) >> GLV_REPC_NO_DESC_CNT_S;
571171d10453SEric Joyner 	error_cnt = (repc & GLV_REPC_ERROR_CNT_M) >> GLV_REPC_ERROR_CNT_S;
571271d10453SEric Joyner 
571371d10453SEric Joyner 	/* Clear the count by writing to the stats register */
571471d10453SEric Joyner 	wr32(hw, GLV_REPC(vsi_num), 0);
571571d10453SEric Joyner 
571671d10453SEric Joyner 	cur_stats->rx_no_desc += no_desc;
571771d10453SEric Joyner 	cur_stats->rx_errors += error_cnt;
571871d10453SEric Joyner }
571971d10453SEric Joyner 
572071d10453SEric Joyner /**
572171d10453SEric Joyner  * ice_aq_alternate_write
572271d10453SEric Joyner  * @hw: pointer to the hardware structure
572371d10453SEric Joyner  * @reg_addr0: address of first dword to be written
572471d10453SEric Joyner  * @reg_val0: value to be written under 'reg_addr0'
572571d10453SEric Joyner  * @reg_addr1: address of second dword to be written
572671d10453SEric Joyner  * @reg_val1: value to be written under 'reg_addr1'
572771d10453SEric Joyner  *
572871d10453SEric Joyner  * Write one or two dwords to alternate structure. Fields are indicated
572971d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers.
573071d10453SEric Joyner  */
573171d10453SEric Joyner enum ice_status
573271d10453SEric Joyner ice_aq_alternate_write(struct ice_hw *hw, u32 reg_addr0, u32 reg_val0,
573371d10453SEric Joyner 		       u32 reg_addr1, u32 reg_val1)
573471d10453SEric Joyner {
573571d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
573671d10453SEric Joyner 	struct ice_aq_desc desc;
573771d10453SEric Joyner 	enum ice_status status;
573871d10453SEric Joyner 
573971d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
574071d10453SEric Joyner 
574171d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_alt_direct);
574271d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
574371d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
574471d10453SEric Joyner 	cmd->dword0_value = CPU_TO_LE32(reg_val0);
574571d10453SEric Joyner 	cmd->dword1_value = CPU_TO_LE32(reg_val1);
574671d10453SEric Joyner 
574771d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
574871d10453SEric Joyner 
574971d10453SEric Joyner 	return status;
575071d10453SEric Joyner }
575171d10453SEric Joyner 
575271d10453SEric Joyner /**
575371d10453SEric Joyner  * ice_aq_alternate_read
575471d10453SEric Joyner  * @hw: pointer to the hardware structure
575571d10453SEric Joyner  * @reg_addr0: address of first dword to be read
575671d10453SEric Joyner  * @reg_val0: pointer for data read from 'reg_addr0'
575771d10453SEric Joyner  * @reg_addr1: address of second dword to be read
575871d10453SEric Joyner  * @reg_val1: pointer for data read from 'reg_addr1'
575971d10453SEric Joyner  *
576071d10453SEric Joyner  * Read one or two dwords from alternate structure. Fields are indicated
576171d10453SEric Joyner  * by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer
576271d10453SEric Joyner  * is not passed then only register at 'reg_addr0' is read.
576371d10453SEric Joyner  */
576471d10453SEric Joyner enum ice_status
576571d10453SEric Joyner ice_aq_alternate_read(struct ice_hw *hw, u32 reg_addr0, u32 *reg_val0,
576671d10453SEric Joyner 		      u32 reg_addr1, u32 *reg_val1)
576771d10453SEric Joyner {
576871d10453SEric Joyner 	struct ice_aqc_read_write_alt_direct *cmd;
576971d10453SEric Joyner 	struct ice_aq_desc desc;
577071d10453SEric Joyner 	enum ice_status status;
577171d10453SEric Joyner 
577271d10453SEric Joyner 	cmd = &desc.params.read_write_alt_direct;
577371d10453SEric Joyner 
577471d10453SEric Joyner 	if (!reg_val0)
577571d10453SEric Joyner 		return ICE_ERR_PARAM;
577671d10453SEric Joyner 
577771d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_alt_direct);
577871d10453SEric Joyner 	cmd->dword0_addr = CPU_TO_LE32(reg_addr0);
577971d10453SEric Joyner 	cmd->dword1_addr = CPU_TO_LE32(reg_addr1);
578071d10453SEric Joyner 
578171d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
578271d10453SEric Joyner 
578371d10453SEric Joyner 	if (status == ICE_SUCCESS) {
578471d10453SEric Joyner 		*reg_val0 = LE32_TO_CPU(cmd->dword0_value);
578571d10453SEric Joyner 
578671d10453SEric Joyner 		if (reg_val1)
578771d10453SEric Joyner 			*reg_val1 = LE32_TO_CPU(cmd->dword1_value);
578871d10453SEric Joyner 	}
578971d10453SEric Joyner 
579071d10453SEric Joyner 	return status;
579171d10453SEric Joyner }
579271d10453SEric Joyner 
579371d10453SEric Joyner /**
579471d10453SEric Joyner  *  ice_aq_alternate_write_done
579571d10453SEric Joyner  *  @hw: pointer to the HW structure.
579671d10453SEric Joyner  *  @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS
579771d10453SEric Joyner  *  @reset_needed: indicates the SW should trigger GLOBAL reset
579871d10453SEric Joyner  *
579971d10453SEric Joyner  *  Indicates to the FW that alternate structures have been changed.
580071d10453SEric Joyner  */
580171d10453SEric Joyner enum ice_status
580271d10453SEric Joyner ice_aq_alternate_write_done(struct ice_hw *hw, u8 bios_mode, bool *reset_needed)
580371d10453SEric Joyner {
580471d10453SEric Joyner 	struct ice_aqc_done_alt_write *cmd;
580571d10453SEric Joyner 	struct ice_aq_desc desc;
580671d10453SEric Joyner 	enum ice_status status;
580771d10453SEric Joyner 
580871d10453SEric Joyner 	cmd = &desc.params.done_alt_write;
580971d10453SEric Joyner 
581071d10453SEric Joyner 	if (!reset_needed)
581171d10453SEric Joyner 		return ICE_ERR_PARAM;
581271d10453SEric Joyner 
581371d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_done_alt_write);
581471d10453SEric Joyner 	cmd->flags = bios_mode;
581571d10453SEric Joyner 
581671d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
581771d10453SEric Joyner 	if (!status)
581871d10453SEric Joyner 		*reset_needed = (LE16_TO_CPU(cmd->flags) &
581971d10453SEric Joyner 				 ICE_AQC_RESP_RESET_NEEDED) != 0;
582071d10453SEric Joyner 
582171d10453SEric Joyner 	return status;
582271d10453SEric Joyner }
582371d10453SEric Joyner 
582471d10453SEric Joyner /**
582571d10453SEric Joyner  *  ice_aq_alternate_clear
582671d10453SEric Joyner  *  @hw: pointer to the HW structure.
582771d10453SEric Joyner  *
582871d10453SEric Joyner  *  Clear the alternate structures of the port from which the function
582971d10453SEric Joyner  *  is called.
583071d10453SEric Joyner  */
583171d10453SEric Joyner enum ice_status ice_aq_alternate_clear(struct ice_hw *hw)
583271d10453SEric Joyner {
583371d10453SEric Joyner 	struct ice_aq_desc desc;
583471d10453SEric Joyner 	enum ice_status status;
583571d10453SEric Joyner 
583671d10453SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_port_alt_write);
583771d10453SEric Joyner 
583871d10453SEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
583971d10453SEric Joyner 
584071d10453SEric Joyner 	return status;
584171d10453SEric Joyner }
584271d10453SEric Joyner 
584371d10453SEric Joyner /**
584471d10453SEric Joyner  * ice_sched_query_elem - query element information from HW
584571d10453SEric Joyner  * @hw: pointer to the HW struct
584671d10453SEric Joyner  * @node_teid: node TEID to be queried
584771d10453SEric Joyner  * @buf: buffer to element information
584871d10453SEric Joyner  *
584971d10453SEric Joyner  * This function queries HW element information
585071d10453SEric Joyner  */
585171d10453SEric Joyner enum ice_status
585271d10453SEric Joyner ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
58537d7af7f8SEric Joyner 		     struct ice_aqc_txsched_elem_data *buf)
585471d10453SEric Joyner {
585571d10453SEric Joyner 	u16 buf_size, num_elem_ret = 0;
585671d10453SEric Joyner 	enum ice_status status;
585771d10453SEric Joyner 
585871d10453SEric Joyner 	buf_size = sizeof(*buf);
585971d10453SEric Joyner 	ice_memset(buf, 0, buf_size, ICE_NONDMA_MEM);
58607d7af7f8SEric Joyner 	buf->node_teid = CPU_TO_LE32(node_teid);
586171d10453SEric Joyner 	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
586271d10453SEric Joyner 					  NULL);
586371d10453SEric Joyner 	if (status != ICE_SUCCESS || num_elem_ret != 1)
586471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
586571d10453SEric Joyner 	return status;
586671d10453SEric Joyner }
586771d10453SEric Joyner 
586871d10453SEric Joyner /**
586971d10453SEric Joyner  * ice_get_fw_mode - returns FW mode
587071d10453SEric Joyner  * @hw: pointer to the HW struct
587171d10453SEric Joyner  */
587271d10453SEric Joyner enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
587371d10453SEric Joyner {
587471d10453SEric Joyner #define ICE_FW_MODE_DBG_M BIT(0)
587571d10453SEric Joyner #define ICE_FW_MODE_REC_M BIT(1)
587671d10453SEric Joyner #define ICE_FW_MODE_ROLLBACK_M BIT(2)
587771d10453SEric Joyner 	u32 fw_mode;
587871d10453SEric Joyner 
587971d10453SEric Joyner 	/* check the current FW mode */
588071d10453SEric Joyner 	fw_mode = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_MODES_M;
588171d10453SEric Joyner 	if (fw_mode & ICE_FW_MODE_DBG_M)
588271d10453SEric Joyner 		return ICE_FW_MODE_DBG;
588371d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_REC_M)
588471d10453SEric Joyner 		return ICE_FW_MODE_REC;
588571d10453SEric Joyner 	else if (fw_mode & ICE_FW_MODE_ROLLBACK_M)
588671d10453SEric Joyner 		return ICE_FW_MODE_ROLLBACK;
588771d10453SEric Joyner 	else
588871d10453SEric Joyner 		return ICE_FW_MODE_NORMAL;
588971d10453SEric Joyner }
589071d10453SEric Joyner 
589171d10453SEric Joyner /**
58929dc2f6e2SEric Joyner  * ice_get_cur_lldp_persist_status
589371d10453SEric Joyner  * @hw: pointer to the HW struct
589471d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
589571d10453SEric Joyner  *
589671d10453SEric Joyner  * Get the current status of LLDP persistent
589771d10453SEric Joyner  */
589871d10453SEric Joyner enum ice_status
589971d10453SEric Joyner ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
590071d10453SEric Joyner {
590171d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
590271d10453SEric Joyner 	enum ice_status ret;
590371d10453SEric Joyner 	__le32 raw_data;
590471d10453SEric Joyner 	u32 data, mask;
590571d10453SEric Joyner 
590671d10453SEric Joyner 	if (!lldp_status)
590771d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
590871d10453SEric Joyner 
590971d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
591071d10453SEric Joyner 	if (ret)
591171d10453SEric Joyner 		return ret;
591271d10453SEric Joyner 
591371d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LLDP_PRESERVED_MOD_ID,
591471d10453SEric Joyner 			      ICE_AQC_NVM_CUR_LLDP_PERSIST_RD_OFFSET,
591571d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data,
591671d10453SEric Joyner 			      false, true, NULL);
591771d10453SEric Joyner 	if (!ret) {
591871d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
591971d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
592071d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
592171d10453SEric Joyner 		data = data & mask;
592271d10453SEric Joyner 		*lldp_status = data >>
592371d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
592471d10453SEric Joyner 	}
592571d10453SEric Joyner 
592671d10453SEric Joyner 	ice_release_nvm(hw);
592771d10453SEric Joyner 
592871d10453SEric Joyner 	return ret;
592971d10453SEric Joyner }
593071d10453SEric Joyner 
593171d10453SEric Joyner /**
593271d10453SEric Joyner  * ice_get_dflt_lldp_persist_status
593371d10453SEric Joyner  * @hw: pointer to the HW struct
593471d10453SEric Joyner  * @lldp_status: return value of LLDP persistent status
593571d10453SEric Joyner  *
593671d10453SEric Joyner  * Get the default status of LLDP persistent
593771d10453SEric Joyner  */
593871d10453SEric Joyner enum ice_status
593971d10453SEric Joyner ice_get_dflt_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status)
594071d10453SEric Joyner {
594171d10453SEric Joyner 	struct ice_port_info *pi = hw->port_info;
594271d10453SEric Joyner 	u32 data, mask, loc_data, loc_data_tmp;
594371d10453SEric Joyner 	enum ice_status ret;
594471d10453SEric Joyner 	__le16 loc_raw_data;
594571d10453SEric Joyner 	__le32 raw_data;
594671d10453SEric Joyner 
594771d10453SEric Joyner 	if (!lldp_status)
594871d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
594971d10453SEric Joyner 
595071d10453SEric Joyner 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
595171d10453SEric Joyner 	if (ret)
595271d10453SEric Joyner 		return ret;
595371d10453SEric Joyner 
595471d10453SEric Joyner 	/* Read the offset of EMP_SR_PTR */
595571d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT,
595671d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_OFFSET,
595771d10453SEric Joyner 			      ICE_AQC_NVM_EMP_SR_PTR_RD_LEN,
595871d10453SEric Joyner 			      &loc_raw_data, false, true, NULL);
595971d10453SEric Joyner 	if (ret)
596071d10453SEric Joyner 		goto exit;
596171d10453SEric Joyner 
596271d10453SEric Joyner 	loc_data = LE16_TO_CPU(loc_raw_data);
596371d10453SEric Joyner 	if (loc_data & ICE_AQC_NVM_EMP_SR_PTR_TYPE_M) {
596471d10453SEric Joyner 		loc_data &= ICE_AQC_NVM_EMP_SR_PTR_M;
596571d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_SECTOR_UNIT;
596671d10453SEric Joyner 	} else {
596771d10453SEric Joyner 		loc_data *= ICE_AQC_NVM_WORD_UNIT;
596871d10453SEric Joyner 	}
596971d10453SEric Joyner 
597071d10453SEric Joyner 	/* Read the offset of LLDP configuration pointer */
597171d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_PTR_OFFSET;
597271d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
597371d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_CFG_PTR_RD_LEN, &loc_raw_data,
597471d10453SEric Joyner 			      false, true, NULL);
597571d10453SEric Joyner 	if (ret)
597671d10453SEric Joyner 		goto exit;
597771d10453SEric Joyner 
597871d10453SEric Joyner 	loc_data_tmp = LE16_TO_CPU(loc_raw_data);
597971d10453SEric Joyner 	loc_data_tmp *= ICE_AQC_NVM_WORD_UNIT;
598071d10453SEric Joyner 	loc_data += loc_data_tmp;
598171d10453SEric Joyner 
598271d10453SEric Joyner 	/* We need to skip LLDP configuration section length (2 bytes) */
598371d10453SEric Joyner 	loc_data += ICE_AQC_NVM_LLDP_CFG_HEADER_LEN;
598471d10453SEric Joyner 
598571d10453SEric Joyner 	/* Read the LLDP Default Configure */
598671d10453SEric Joyner 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, loc_data,
598771d10453SEric Joyner 			      ICE_AQC_NVM_LLDP_STATUS_RD_LEN, &raw_data, false,
598871d10453SEric Joyner 			      true, NULL);
598971d10453SEric Joyner 	if (!ret) {
599071d10453SEric Joyner 		data = LE32_TO_CPU(raw_data);
599171d10453SEric Joyner 		mask = ICE_AQC_NVM_LLDP_STATUS_M <<
599271d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
599371d10453SEric Joyner 		data = data & mask;
599471d10453SEric Joyner 		*lldp_status = data >>
599571d10453SEric Joyner 			(ICE_AQC_NVM_LLDP_STATUS_M_LEN * pi->lport);
599671d10453SEric Joyner 	}
599771d10453SEric Joyner 
599871d10453SEric Joyner exit:
599971d10453SEric Joyner 	ice_release_nvm(hw);
600071d10453SEric Joyner 
600171d10453SEric Joyner 	return ret;
600271d10453SEric Joyner }
600371d10453SEric Joyner 
600471d10453SEric Joyner /**
600556429daeSEric Joyner  * ice_aq_read_i2c
600656429daeSEric Joyner  * @hw: pointer to the hw struct
600756429daeSEric Joyner  * @topo_addr: topology address for a device to communicate with
600856429daeSEric Joyner  * @bus_addr: 7-bit I2C bus address
600956429daeSEric Joyner  * @addr: I2C memory address (I2C offset) with up to 16 bits
601056429daeSEric Joyner  * @params: I2C parameters: bit [7] - Repeated start, bits [6:5] data offset size,
601156429daeSEric Joyner  *			    bit [4] - I2C address type, bits [3:0] - data size to read (0-16 bytes)
601256429daeSEric Joyner  * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
601356429daeSEric Joyner  * @cd: pointer to command details structure or NULL
601456429daeSEric Joyner  *
601556429daeSEric Joyner  * Read I2C (0x06E2)
601656429daeSEric Joyner  */
601756429daeSEric Joyner enum ice_status
601856429daeSEric Joyner ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
601956429daeSEric Joyner 		u16 bus_addr, __le16 addr, u8 params, u8 *data,
602056429daeSEric Joyner 		struct ice_sq_cd *cd)
602156429daeSEric Joyner {
602256429daeSEric Joyner 	struct ice_aq_desc desc = { 0 };
602356429daeSEric Joyner 	struct ice_aqc_i2c *cmd;
602456429daeSEric Joyner 	enum ice_status status;
602556429daeSEric Joyner 	u8 data_size;
602656429daeSEric Joyner 
602756429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
602856429daeSEric Joyner 	cmd = &desc.params.read_write_i2c;
602956429daeSEric Joyner 
603056429daeSEric Joyner 	if (!data)
603156429daeSEric Joyner 		return ICE_ERR_PARAM;
603256429daeSEric Joyner 
603356429daeSEric Joyner 	data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
603456429daeSEric Joyner 
603556429daeSEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
603656429daeSEric Joyner 	cmd->topo_addr = topo_addr;
603756429daeSEric Joyner 	cmd->i2c_params = params;
603856429daeSEric Joyner 	cmd->i2c_addr = addr;
603956429daeSEric Joyner 
604056429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
604156429daeSEric Joyner 	if (!status) {
604256429daeSEric Joyner 		struct ice_aqc_read_i2c_resp *resp;
604356429daeSEric Joyner 		u8 i;
604456429daeSEric Joyner 
604556429daeSEric Joyner 		resp = &desc.params.read_i2c_resp;
604656429daeSEric Joyner 		for (i = 0; i < data_size; i++) {
604756429daeSEric Joyner 			*data = resp->i2c_data[i];
604856429daeSEric Joyner 			data++;
604956429daeSEric Joyner 		}
605056429daeSEric Joyner 	}
605156429daeSEric Joyner 
605256429daeSEric Joyner 	return status;
605356429daeSEric Joyner }
605456429daeSEric Joyner 
605556429daeSEric Joyner /**
605656429daeSEric Joyner  * ice_aq_write_i2c
605756429daeSEric Joyner  * @hw: pointer to the hw struct
605856429daeSEric Joyner  * @topo_addr: topology address for a device to communicate with
605956429daeSEric Joyner  * @bus_addr: 7-bit I2C bus address
606056429daeSEric Joyner  * @addr: I2C memory address (I2C offset) with up to 16 bits
606156429daeSEric Joyner  * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
606256429daeSEric Joyner  * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
606356429daeSEric Joyner  * @cd: pointer to command details structure or NULL
606456429daeSEric Joyner  *
606556429daeSEric Joyner  * Write I2C (0x06E3)
606656429daeSEric Joyner  */
606756429daeSEric Joyner enum ice_status
606856429daeSEric Joyner ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
6069*9e54973fSEric Joyner 		 u16 bus_addr, __le16 addr, u8 params, const u8 *data,
607056429daeSEric Joyner 		 struct ice_sq_cd *cd)
607156429daeSEric Joyner {
607256429daeSEric Joyner 	struct ice_aq_desc desc = { 0 };
607356429daeSEric Joyner 	struct ice_aqc_i2c *cmd;
607456429daeSEric Joyner 	u8 i, data_size;
607556429daeSEric Joyner 
607656429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
607756429daeSEric Joyner 	cmd = &desc.params.read_write_i2c;
607856429daeSEric Joyner 
607956429daeSEric Joyner 	data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
608056429daeSEric Joyner 
608156429daeSEric Joyner 	/* data_size limited to 4 */
608256429daeSEric Joyner 	if (data_size > 4)
608356429daeSEric Joyner 		return ICE_ERR_PARAM;
608456429daeSEric Joyner 
608556429daeSEric Joyner 	cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
608656429daeSEric Joyner 	cmd->topo_addr = topo_addr;
608756429daeSEric Joyner 	cmd->i2c_params = params;
608856429daeSEric Joyner 	cmd->i2c_addr = addr;
608956429daeSEric Joyner 
609056429daeSEric Joyner 	for (i = 0; i < data_size; i++) {
609156429daeSEric Joyner 		cmd->i2c_data[i] = *data;
609256429daeSEric Joyner 		data++;
609356429daeSEric Joyner 	}
609456429daeSEric Joyner 
609556429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
609656429daeSEric Joyner }
609756429daeSEric Joyner 
609856429daeSEric Joyner /**
609956429daeSEric Joyner  * ice_aq_set_gpio
610056429daeSEric Joyner  * @hw: pointer to the hw struct
610156429daeSEric Joyner  * @gpio_ctrl_handle: GPIO controller node handle
610256429daeSEric Joyner  * @pin_idx: IO Number of the GPIO that needs to be set
610356429daeSEric Joyner  * @value: SW provide IO value to set in the LSB
610456429daeSEric Joyner  * @cd: pointer to command details structure or NULL
610556429daeSEric Joyner  *
610656429daeSEric Joyner  * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
610756429daeSEric Joyner  */
610856429daeSEric Joyner enum ice_status
610956429daeSEric Joyner ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
611056429daeSEric Joyner 		struct ice_sq_cd *cd)
611156429daeSEric Joyner {
611256429daeSEric Joyner 	struct ice_aqc_gpio *cmd;
611356429daeSEric Joyner 	struct ice_aq_desc desc;
611456429daeSEric Joyner 
611556429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
611656429daeSEric Joyner 	cmd = &desc.params.read_write_gpio;
61178923de59SPiotr Kubaj 	cmd->gpio_ctrl_handle = CPU_TO_LE16(gpio_ctrl_handle);
611856429daeSEric Joyner 	cmd->gpio_num = pin_idx;
611956429daeSEric Joyner 	cmd->gpio_val = value ? 1 : 0;
612056429daeSEric Joyner 
612156429daeSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
612256429daeSEric Joyner }
612356429daeSEric Joyner 
612456429daeSEric Joyner /**
612556429daeSEric Joyner  * ice_aq_get_gpio
612656429daeSEric Joyner  * @hw: pointer to the hw struct
612756429daeSEric Joyner  * @gpio_ctrl_handle: GPIO controller node handle
612856429daeSEric Joyner  * @pin_idx: IO Number of the GPIO that needs to be set
612956429daeSEric Joyner  * @value: IO value read
613056429daeSEric Joyner  * @cd: pointer to command details structure or NULL
613156429daeSEric Joyner  *
613256429daeSEric Joyner  * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
613356429daeSEric Joyner  * the topology
613456429daeSEric Joyner  */
613556429daeSEric Joyner enum ice_status
613656429daeSEric Joyner ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
613756429daeSEric Joyner 		bool *value, struct ice_sq_cd *cd)
613856429daeSEric Joyner {
613956429daeSEric Joyner 	struct ice_aqc_gpio *cmd;
614056429daeSEric Joyner 	struct ice_aq_desc desc;
614156429daeSEric Joyner 	enum ice_status status;
614256429daeSEric Joyner 
614356429daeSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
614456429daeSEric Joyner 	cmd = &desc.params.read_write_gpio;
61458923de59SPiotr Kubaj 	cmd->gpio_ctrl_handle = CPU_TO_LE16(gpio_ctrl_handle);
614656429daeSEric Joyner 	cmd->gpio_num = pin_idx;
614756429daeSEric Joyner 
614856429daeSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
614956429daeSEric Joyner 	if (status)
615056429daeSEric Joyner 		return status;
615156429daeSEric Joyner 
615256429daeSEric Joyner 	*value = !!cmd->gpio_val;
615356429daeSEric Joyner 	return ICE_SUCCESS;
615456429daeSEric Joyner }
615556429daeSEric Joyner 
615656429daeSEric Joyner /**
61578923de59SPiotr Kubaj  * ice_is_fw_api_min_ver
61588923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
61598923de59SPiotr Kubaj  * @maj: major version
61608923de59SPiotr Kubaj  * @min: minor version
61618923de59SPiotr Kubaj  * @patch: patch version
61628923de59SPiotr Kubaj  *
61638923de59SPiotr Kubaj  * Checks if the firmware is minimum version
61648923de59SPiotr Kubaj  */
61658923de59SPiotr Kubaj static bool ice_is_fw_api_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch)
61668923de59SPiotr Kubaj {
61678923de59SPiotr Kubaj 	if (hw->api_maj_ver == maj) {
61688923de59SPiotr Kubaj 		if (hw->api_min_ver > min)
61698923de59SPiotr Kubaj 			return true;
61708923de59SPiotr Kubaj 		if (hw->api_min_ver == min && hw->api_patch >= patch)
61718923de59SPiotr Kubaj 			return true;
61728923de59SPiotr Kubaj 	} else if (hw->api_maj_ver > maj) {
61738923de59SPiotr Kubaj 		return true;
61748923de59SPiotr Kubaj 	}
61758923de59SPiotr Kubaj 
61768923de59SPiotr Kubaj 	return false;
61778923de59SPiotr Kubaj }
61788923de59SPiotr Kubaj 
61798923de59SPiotr Kubaj /**
61808923de59SPiotr Kubaj  * ice_is_fw_min_ver
61818923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
61828923de59SPiotr Kubaj  * @branch: branch version
61838923de59SPiotr Kubaj  * @maj: major version
61848923de59SPiotr Kubaj  * @min: minor version
61858923de59SPiotr Kubaj  * @patch: patch version
61868923de59SPiotr Kubaj  *
61878923de59SPiotr Kubaj  * Checks if the firmware is minimum version
61888923de59SPiotr Kubaj  */
61898923de59SPiotr Kubaj static bool ice_is_fw_min_ver(struct ice_hw *hw, u8 branch, u8 maj, u8 min,
61908923de59SPiotr Kubaj 			      u8 patch)
61918923de59SPiotr Kubaj {
61928923de59SPiotr Kubaj 	if (hw->fw_branch == branch) {
61938923de59SPiotr Kubaj 		if (hw->fw_maj_ver > maj)
61948923de59SPiotr Kubaj 			return true;
61958923de59SPiotr Kubaj 		if (hw->fw_maj_ver == maj) {
61968923de59SPiotr Kubaj 			if (hw->fw_min_ver > min)
61978923de59SPiotr Kubaj 				return true;
61988923de59SPiotr Kubaj 			if (hw->fw_min_ver == min && hw->fw_patch >= patch)
61998923de59SPiotr Kubaj 				return true;
62008923de59SPiotr Kubaj 		}
62018923de59SPiotr Kubaj 	}
62028923de59SPiotr Kubaj 
62038923de59SPiotr Kubaj 	return false;
62048923de59SPiotr Kubaj }
62058923de59SPiotr Kubaj 
62068923de59SPiotr Kubaj /**
620771d10453SEric Joyner  * ice_fw_supports_link_override
620871d10453SEric Joyner  * @hw: pointer to the hardware structure
620971d10453SEric Joyner  *
621071d10453SEric Joyner  * Checks if the firmware supports link override
621171d10453SEric Joyner  */
621271d10453SEric Joyner bool ice_fw_supports_link_override(struct ice_hw *hw)
621371d10453SEric Joyner {
62148923de59SPiotr Kubaj 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LINK_OVERRIDE_MAJ,
62158923de59SPiotr Kubaj 				     ICE_FW_API_LINK_OVERRIDE_MIN,
62168923de59SPiotr Kubaj 				     ICE_FW_API_LINK_OVERRIDE_PATCH);
621771d10453SEric Joyner }
621871d10453SEric Joyner 
621971d10453SEric Joyner /**
622071d10453SEric Joyner  * ice_get_link_default_override
622171d10453SEric Joyner  * @ldo: pointer to the link default override struct
622271d10453SEric Joyner  * @pi: pointer to the port info struct
622371d10453SEric Joyner  *
622471d10453SEric Joyner  * Gets the link default override for a port
622571d10453SEric Joyner  */
622671d10453SEric Joyner enum ice_status
622771d10453SEric Joyner ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
622871d10453SEric Joyner 			      struct ice_port_info *pi)
622971d10453SEric Joyner {
623071d10453SEric Joyner 	u16 i, tlv, tlv_len, tlv_start, buf, offset;
623171d10453SEric Joyner 	struct ice_hw *hw = pi->hw;
623271d10453SEric Joyner 	enum ice_status status;
623371d10453SEric Joyner 
623471d10453SEric Joyner 	status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
623571d10453SEric Joyner 					ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
623671d10453SEric Joyner 	if (status) {
62377d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n");
623871d10453SEric Joyner 		return status;
623971d10453SEric Joyner 	}
624071d10453SEric Joyner 
624171d10453SEric Joyner 	/* Each port has its own config; calculate for our port */
624271d10453SEric Joyner 	tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
624371d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
624471d10453SEric Joyner 
624571d10453SEric Joyner 	/* link options first */
624671d10453SEric Joyner 	status = ice_read_sr_word(hw, tlv_start, &buf);
624771d10453SEric Joyner 	if (status) {
62487d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
624971d10453SEric Joyner 		return status;
625071d10453SEric Joyner 	}
625171d10453SEric Joyner 	ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
625271d10453SEric Joyner 	ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
625371d10453SEric Joyner 		ICE_LINK_OVERRIDE_PHY_CFG_S;
625471d10453SEric Joyner 
625571d10453SEric Joyner 	/* link PHY config */
625671d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
625771d10453SEric Joyner 	status = ice_read_sr_word(hw, offset, &buf);
625871d10453SEric Joyner 	if (status) {
62597d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n");
626071d10453SEric Joyner 		return status;
626171d10453SEric Joyner 	}
626271d10453SEric Joyner 	ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
626371d10453SEric Joyner 
626471d10453SEric Joyner 	/* PHY types low */
626571d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
626671d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
626771d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
626871d10453SEric Joyner 		if (status) {
62697d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
627071d10453SEric Joyner 			return status;
627171d10453SEric Joyner 		}
627271d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
627371d10453SEric Joyner 		ldo->phy_type_low |= ((u64)buf << (i * 16));
627471d10453SEric Joyner 	}
627571d10453SEric Joyner 
627671d10453SEric Joyner 	/* PHY types high */
627771d10453SEric Joyner 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
627871d10453SEric Joyner 		ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
627971d10453SEric Joyner 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
628071d10453SEric Joyner 		status = ice_read_sr_word(hw, (offset + i), &buf);
628171d10453SEric Joyner 		if (status) {
62827d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
628371d10453SEric Joyner 			return status;
628471d10453SEric Joyner 		}
628571d10453SEric Joyner 		/* shift 16 bits at a time to fill 64 bits */
628671d10453SEric Joyner 		ldo->phy_type_high |= ((u64)buf << (i * 16));
628771d10453SEric Joyner 	}
628871d10453SEric Joyner 
628971d10453SEric Joyner 	return status;
629071d10453SEric Joyner }
62917d7af7f8SEric Joyner 
62927d7af7f8SEric Joyner /**
62937d7af7f8SEric Joyner  * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
62947d7af7f8SEric Joyner  * @caps: get PHY capability data
62957d7af7f8SEric Joyner  */
62967d7af7f8SEric Joyner bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
62977d7af7f8SEric Joyner {
62987d7af7f8SEric Joyner 	if (caps->caps & ICE_AQC_PHY_AN_MODE ||
62997d7af7f8SEric Joyner 	    caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
63007d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE73 |
63017d7af7f8SEric Joyner 				       ICE_AQC_PHY_AN_EN_CLAUSE37))
63027d7af7f8SEric Joyner 		return true;
63037d7af7f8SEric Joyner 
63047d7af7f8SEric Joyner 	return false;
63057d7af7f8SEric Joyner }
63067d7af7f8SEric Joyner 
63077d7af7f8SEric Joyner /**
63089cf1841cSEric Joyner  * ice_is_fw_health_report_supported
63099cf1841cSEric Joyner  * @hw: pointer to the hardware structure
63109cf1841cSEric Joyner  *
63119cf1841cSEric Joyner  * Return true if firmware supports health status reports,
63129cf1841cSEric Joyner  * false otherwise
63139cf1841cSEric Joyner  */
63149cf1841cSEric Joyner bool ice_is_fw_health_report_supported(struct ice_hw *hw)
63159cf1841cSEric Joyner {
63169cf1841cSEric Joyner 	if (hw->api_maj_ver > ICE_FW_API_HEALTH_REPORT_MAJ)
63179cf1841cSEric Joyner 		return true;
63189cf1841cSEric Joyner 
63199cf1841cSEric Joyner 	if (hw->api_maj_ver == ICE_FW_API_HEALTH_REPORT_MAJ) {
63209cf1841cSEric Joyner 		if (hw->api_min_ver > ICE_FW_API_HEALTH_REPORT_MIN)
63219cf1841cSEric Joyner 			return true;
63229cf1841cSEric Joyner 		if (hw->api_min_ver == ICE_FW_API_HEALTH_REPORT_MIN &&
63239cf1841cSEric Joyner 		    hw->api_patch >= ICE_FW_API_HEALTH_REPORT_PATCH)
63249cf1841cSEric Joyner 			return true;
63259cf1841cSEric Joyner 	}
63269cf1841cSEric Joyner 
63279cf1841cSEric Joyner 	return false;
63289cf1841cSEric Joyner }
63299cf1841cSEric Joyner 
63309cf1841cSEric Joyner /**
63319cf1841cSEric Joyner  * ice_aq_set_health_status_config - Configure FW health events
63329cf1841cSEric Joyner  * @hw: pointer to the HW struct
63339cf1841cSEric Joyner  * @event_source: type of diagnostic events to enable
63349cf1841cSEric Joyner  * @cd: pointer to command details structure or NULL
63359cf1841cSEric Joyner  *
63369cf1841cSEric Joyner  * Configure the health status event types that the firmware will send to this
63379cf1841cSEric Joyner  * PF. The supported event types are: PF-specific, all PFs, and global
63389cf1841cSEric Joyner  */
63399cf1841cSEric Joyner enum ice_status
63409cf1841cSEric Joyner ice_aq_set_health_status_config(struct ice_hw *hw, u8 event_source,
63419cf1841cSEric Joyner 				struct ice_sq_cd *cd)
63429cf1841cSEric Joyner {
63439cf1841cSEric Joyner 	struct ice_aqc_set_health_status_config *cmd;
63449cf1841cSEric Joyner 	struct ice_aq_desc desc;
63459cf1841cSEric Joyner 
63469cf1841cSEric Joyner 	cmd = &desc.params.set_health_status_config;
63479cf1841cSEric Joyner 
63489cf1841cSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc,
63499cf1841cSEric Joyner 				      ice_aqc_opc_set_health_status_config);
63509cf1841cSEric Joyner 
63519cf1841cSEric Joyner 	cmd->event_source = event_source;
63529cf1841cSEric Joyner 
63539cf1841cSEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
63549cf1841cSEric Joyner }
63559cf1841cSEric Joyner 
63569cf1841cSEric Joyner /**
63579cf1841cSEric Joyner  * ice_aq_get_port_options
63589cf1841cSEric Joyner  * @hw: pointer to the hw struct
63599cf1841cSEric Joyner  * @options: buffer for the resultant port options
63609cf1841cSEric Joyner  * @option_count: input - size of the buffer in port options structures,
63619cf1841cSEric Joyner  *                output - number of returned port options
63629cf1841cSEric Joyner  * @lport: logical port to call the command with (optional)
63639cf1841cSEric Joyner  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
63649cf1841cSEric Joyner  *               when PF owns more than 1 port it must be true
63659cf1841cSEric Joyner  * @active_option_idx: index of active port option in returned buffer
63669cf1841cSEric Joyner  * @active_option_valid: active option in returned buffer is valid
63679dc2f6e2SEric Joyner  * @pending_option_idx: index of pending port option in returned buffer
63689dc2f6e2SEric Joyner  * @pending_option_valid: pending option in returned buffer is valid
63699cf1841cSEric Joyner  *
63709cf1841cSEric Joyner  * Calls Get Port Options AQC (0x06ea) and verifies result.
63719cf1841cSEric Joyner  */
63729cf1841cSEric Joyner enum ice_status
63739cf1841cSEric Joyner ice_aq_get_port_options(struct ice_hw *hw,
63749cf1841cSEric Joyner 			struct ice_aqc_get_port_options_elem *options,
63759cf1841cSEric Joyner 			u8 *option_count, u8 lport, bool lport_valid,
63769dc2f6e2SEric Joyner 			u8 *active_option_idx, bool *active_option_valid,
63779dc2f6e2SEric Joyner 			u8 *pending_option_idx, bool *pending_option_valid)
63789cf1841cSEric Joyner {
63799cf1841cSEric Joyner 	struct ice_aqc_get_port_options *cmd;
63809cf1841cSEric Joyner 	struct ice_aq_desc desc;
63819cf1841cSEric Joyner 	enum ice_status status;
63829cf1841cSEric Joyner 	u8 i;
63839cf1841cSEric Joyner 
63849cf1841cSEric Joyner 	/* options buffer shall be able to hold max returned options */
63859cf1841cSEric Joyner 	if (*option_count < ICE_AQC_PORT_OPT_COUNT_M)
63869cf1841cSEric Joyner 		return ICE_ERR_PARAM;
63879cf1841cSEric Joyner 
63889cf1841cSEric Joyner 	cmd = &desc.params.get_port_options;
63899cf1841cSEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options);
63909cf1841cSEric Joyner 
63919cf1841cSEric Joyner 	cmd->lport_num = lport;
63929cf1841cSEric Joyner 	cmd->lport_num_valid = lport_valid;
63939cf1841cSEric Joyner 
63949cf1841cSEric Joyner 	status = ice_aq_send_cmd(hw, &desc, options,
63959cf1841cSEric Joyner 				 *option_count * sizeof(*options), NULL);
63969cf1841cSEric Joyner 	if (status != ICE_SUCCESS)
63979cf1841cSEric Joyner 		return status;
63989cf1841cSEric Joyner 
63999cf1841cSEric Joyner 	/* verify direct FW response & set output parameters */
64009cf1841cSEric Joyner 	*option_count = cmd->port_options_count & ICE_AQC_PORT_OPT_COUNT_M;
64019cf1841cSEric Joyner 	ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count);
64029cf1841cSEric Joyner 	*active_option_valid = cmd->port_options & ICE_AQC_PORT_OPT_VALID;
64039cf1841cSEric Joyner 	if (*active_option_valid) {
64049cf1841cSEric Joyner 		*active_option_idx = cmd->port_options &
64059cf1841cSEric Joyner 				     ICE_AQC_PORT_OPT_ACTIVE_M;
64069cf1841cSEric Joyner 		if (*active_option_idx > (*option_count - 1))
64079cf1841cSEric Joyner 			return ICE_ERR_OUT_OF_RANGE;
64089cf1841cSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n",
64099cf1841cSEric Joyner 			  *active_option_idx);
64109cf1841cSEric Joyner 	}
64119cf1841cSEric Joyner 
64129dc2f6e2SEric Joyner 	*pending_option_valid = cmd->pending_port_option_status &
64139dc2f6e2SEric Joyner 				ICE_AQC_PENDING_PORT_OPT_VALID;
64149dc2f6e2SEric Joyner 	if (*pending_option_valid) {
64159dc2f6e2SEric Joyner 		*pending_option_idx = cmd->pending_port_option_status &
64169dc2f6e2SEric Joyner 				      ICE_AQC_PENDING_PORT_OPT_IDX_M;
64179dc2f6e2SEric Joyner 		if (*pending_option_idx > (*option_count - 1))
64189dc2f6e2SEric Joyner 			return ICE_ERR_OUT_OF_RANGE;
64199dc2f6e2SEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n",
64209dc2f6e2SEric Joyner 			  *pending_option_idx);
64219dc2f6e2SEric Joyner 	}
64229dc2f6e2SEric Joyner 
64239dc2f6e2SEric Joyner 	/* mask output options fields */
64249cf1841cSEric Joyner 	for (i = 0; i < *option_count; i++) {
64259cf1841cSEric Joyner 		options[i].pmd &= ICE_AQC_PORT_OPT_PMD_COUNT_M;
64269cf1841cSEric Joyner 		options[i].max_lane_speed &= ICE_AQC_PORT_OPT_MAX_LANE_M;
64279cf1841cSEric Joyner 		ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n",
64289dc2f6e2SEric Joyner 			  options[i].pmd, options[i].max_lane_speed);
64299cf1841cSEric Joyner 	}
64309cf1841cSEric Joyner 
64319cf1841cSEric Joyner 	return ICE_SUCCESS;
64329cf1841cSEric Joyner }
64339cf1841cSEric Joyner 
64349cf1841cSEric Joyner /**
64359dc2f6e2SEric Joyner  * ice_aq_set_port_option
64369dc2f6e2SEric Joyner  * @hw: pointer to the hw struct
64379dc2f6e2SEric Joyner  * @lport: logical port to call the command with
64389dc2f6e2SEric Joyner  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
64399dc2f6e2SEric Joyner  *               when PF owns more than 1 port it must be true
64409dc2f6e2SEric Joyner  * @new_option: new port option to be written
64419dc2f6e2SEric Joyner  *
64429dc2f6e2SEric Joyner  * Calls Set Port Options AQC (0x06eb).
64439dc2f6e2SEric Joyner  */
64449dc2f6e2SEric Joyner enum ice_status
64459dc2f6e2SEric Joyner ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
64469dc2f6e2SEric Joyner 		       u8 new_option)
64479dc2f6e2SEric Joyner {
64489dc2f6e2SEric Joyner 	struct ice_aqc_set_port_option *cmd;
64499dc2f6e2SEric Joyner 	struct ice_aq_desc desc;
64509dc2f6e2SEric Joyner 
64519dc2f6e2SEric Joyner 	if (new_option >= ICE_AQC_PORT_OPT_COUNT_M)
64529dc2f6e2SEric Joyner 		return ICE_ERR_PARAM;
64539dc2f6e2SEric Joyner 
64549dc2f6e2SEric Joyner 	cmd = &desc.params.set_port_option;
64559dc2f6e2SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option);
64569dc2f6e2SEric Joyner 
64579dc2f6e2SEric Joyner 	cmd->lport_num = lport;
64589dc2f6e2SEric Joyner 
64599dc2f6e2SEric Joyner 	cmd->lport_num_valid = lport_valid;
64609dc2f6e2SEric Joyner 	cmd->selected_port_option = new_option;
64619dc2f6e2SEric Joyner 
64629dc2f6e2SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
64639dc2f6e2SEric Joyner }
64649dc2f6e2SEric Joyner 
64659dc2f6e2SEric Joyner /**
64667d7af7f8SEric Joyner  * ice_aq_set_lldp_mib - Set the LLDP MIB
64677d7af7f8SEric Joyner  * @hw: pointer to the HW struct
64687d7af7f8SEric Joyner  * @mib_type: Local, Remote or both Local and Remote MIBs
64697d7af7f8SEric Joyner  * @buf: pointer to the caller-supplied buffer to store the MIB block
64707d7af7f8SEric Joyner  * @buf_size: size of the buffer (in bytes)
64717d7af7f8SEric Joyner  * @cd: pointer to command details structure or NULL
64727d7af7f8SEric Joyner  *
64737d7af7f8SEric Joyner  * Set the LLDP MIB. (0x0A08)
64747d7af7f8SEric Joyner  */
64757d7af7f8SEric Joyner enum ice_status
64767d7af7f8SEric Joyner ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
64777d7af7f8SEric Joyner 		    struct ice_sq_cd *cd)
64787d7af7f8SEric Joyner {
64797d7af7f8SEric Joyner 	struct ice_aqc_lldp_set_local_mib *cmd;
64807d7af7f8SEric Joyner 	struct ice_aq_desc desc;
64817d7af7f8SEric Joyner 
64827d7af7f8SEric Joyner 	cmd = &desc.params.lldp_set_mib;
64837d7af7f8SEric Joyner 
64847d7af7f8SEric Joyner 	if (buf_size == 0 || !buf)
64857d7af7f8SEric Joyner 		return ICE_ERR_PARAM;
64867d7af7f8SEric Joyner 
64877d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
64887d7af7f8SEric Joyner 
64897d7af7f8SEric Joyner 	desc.flags |= CPU_TO_LE16((u16)ICE_AQ_FLAG_RD);
64907d7af7f8SEric Joyner 	desc.datalen = CPU_TO_LE16(buf_size);
64917d7af7f8SEric Joyner 
64927d7af7f8SEric Joyner 	cmd->type = mib_type;
64937d7af7f8SEric Joyner 	cmd->length = CPU_TO_LE16(buf_size);
64947d7af7f8SEric Joyner 
64957d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
64967d7af7f8SEric Joyner }
64977d7af7f8SEric Joyner 
64987d7af7f8SEric Joyner /**
649956429daeSEric Joyner  * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
65007d7af7f8SEric Joyner  * @hw: pointer to HW struct
65017d7af7f8SEric Joyner  */
65027d7af7f8SEric Joyner bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
65037d7af7f8SEric Joyner {
65048923de59SPiotr Kubaj 	if (hw->mac_type != ICE_MAC_E810 && hw->mac_type != ICE_MAC_GENERIC)
65057d7af7f8SEric Joyner 		return false;
65067d7af7f8SEric Joyner 
65078923de59SPiotr Kubaj 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LLDP_FLTR_MAJ,
65088923de59SPiotr Kubaj 				     ICE_FW_API_LLDP_FLTR_MIN,
65098923de59SPiotr Kubaj 				     ICE_FW_API_LLDP_FLTR_PATCH);
65107d7af7f8SEric Joyner }
65117d7af7f8SEric Joyner 
65127d7af7f8SEric Joyner /**
65137d7af7f8SEric Joyner  * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
65147d7af7f8SEric Joyner  * @hw: pointer to HW struct
65157d7af7f8SEric Joyner  * @vsi_num: absolute HW index for VSI
65167d7af7f8SEric Joyner  * @add: boolean for if adding or removing a filter
65177d7af7f8SEric Joyner  */
65187d7af7f8SEric Joyner enum ice_status
65197d7af7f8SEric Joyner ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
65207d7af7f8SEric Joyner {
65217d7af7f8SEric Joyner 	struct ice_aqc_lldp_filter_ctrl *cmd;
65227d7af7f8SEric Joyner 	struct ice_aq_desc desc;
65237d7af7f8SEric Joyner 
65247d7af7f8SEric Joyner 	cmd = &desc.params.lldp_filter_ctrl;
65257d7af7f8SEric Joyner 
65267d7af7f8SEric Joyner 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
65277d7af7f8SEric Joyner 
65287d7af7f8SEric Joyner 	if (add)
65297d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
65307d7af7f8SEric Joyner 	else
65317d7af7f8SEric Joyner 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
65327d7af7f8SEric Joyner 
65337d7af7f8SEric Joyner 	cmd->vsi_num = CPU_TO_LE16(vsi_num);
65347d7af7f8SEric Joyner 
65357d7af7f8SEric Joyner 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
65367d7af7f8SEric Joyner }
65379cf1841cSEric Joyner 
65389cf1841cSEric Joyner /**
65398923de59SPiotr Kubaj  * ice_lldp_execute_pending_mib - execute LLDP pending MIB request
65408923de59SPiotr Kubaj  * @hw: pointer to HW struct
65418923de59SPiotr Kubaj  */
65428923de59SPiotr Kubaj enum ice_status ice_lldp_execute_pending_mib(struct ice_hw *hw)
65438923de59SPiotr Kubaj {
65448923de59SPiotr Kubaj 	struct ice_aq_desc desc;
65458923de59SPiotr Kubaj 
65468923de59SPiotr Kubaj 	ice_fill_dflt_direct_cmd_desc(&desc, ice_execute_pending_lldp_mib);
65478923de59SPiotr Kubaj 
65488923de59SPiotr Kubaj 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
65498923de59SPiotr Kubaj }
65508923de59SPiotr Kubaj 
65518923de59SPiotr Kubaj /**
65529cf1841cSEric Joyner  * ice_fw_supports_report_dflt_cfg
65539cf1841cSEric Joyner  * @hw: pointer to the hardware structure
65549cf1841cSEric Joyner  *
65559cf1841cSEric Joyner  * Checks if the firmware supports report default configuration
65569cf1841cSEric Joyner  */
65579cf1841cSEric Joyner bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
65589cf1841cSEric Joyner {
65598923de59SPiotr Kubaj 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ,
65608923de59SPiotr Kubaj 				     ICE_FW_API_REPORT_DFLT_CFG_MIN,
65618923de59SPiotr Kubaj 				     ICE_FW_API_REPORT_DFLT_CFG_PATCH);
65629cf1841cSEric Joyner }
656356429daeSEric Joyner 
65649dc2f6e2SEric Joyner /* each of the indexes into the following array match the speed of a return
65659dc2f6e2SEric Joyner  * value from the list of AQ returned speeds like the range:
65669dc2f6e2SEric Joyner  * ICE_AQ_LINK_SPEED_10MB .. ICE_AQ_LINK_SPEED_100GB excluding
65679dc2f6e2SEric Joyner  * ICE_AQ_LINK_SPEED_UNKNOWN which is BIT(15) The array is defined as 15
65689dc2f6e2SEric Joyner  * elements long because the link_speed returned by the firmware is a 16 bit
65699dc2f6e2SEric Joyner  * value, but is indexed by [fls(speed) - 1]
65709dc2f6e2SEric Joyner  */
65719c30461dSEric Joyner static const u32 ice_aq_to_link_speed[] = {
65729dc2f6e2SEric Joyner 	ICE_LINK_SPEED_10MBPS,	/* BIT(0) */
65739dc2f6e2SEric Joyner 	ICE_LINK_SPEED_100MBPS,
65749dc2f6e2SEric Joyner 	ICE_LINK_SPEED_1000MBPS,
65759dc2f6e2SEric Joyner 	ICE_LINK_SPEED_2500MBPS,
65769dc2f6e2SEric Joyner 	ICE_LINK_SPEED_5000MBPS,
65779dc2f6e2SEric Joyner 	ICE_LINK_SPEED_10000MBPS,
65789dc2f6e2SEric Joyner 	ICE_LINK_SPEED_20000MBPS,
65799dc2f6e2SEric Joyner 	ICE_LINK_SPEED_25000MBPS,
65809dc2f6e2SEric Joyner 	ICE_LINK_SPEED_40000MBPS,
65819dc2f6e2SEric Joyner 	ICE_LINK_SPEED_50000MBPS,
65829dc2f6e2SEric Joyner 	ICE_LINK_SPEED_100000MBPS,	/* BIT(10) */
65839dc2f6e2SEric Joyner };
65849dc2f6e2SEric Joyner 
65859dc2f6e2SEric Joyner /**
65869dc2f6e2SEric Joyner  * ice_get_link_speed - get integer speed from table
65879dc2f6e2SEric Joyner  * @index: array index from fls(aq speed) - 1
65889dc2f6e2SEric Joyner  *
65899dc2f6e2SEric Joyner  * Returns: u32 value containing integer speed
65909dc2f6e2SEric Joyner  */
65919dc2f6e2SEric Joyner u32 ice_get_link_speed(u16 index)
65929dc2f6e2SEric Joyner {
65939c30461dSEric Joyner 	if (index >= ARRAY_SIZE(ice_aq_to_link_speed))
65949c30461dSEric Joyner 		return ICE_LINK_SPEED_UNKNOWN;
65959c30461dSEric Joyner 
65969dc2f6e2SEric Joyner 	return ice_aq_to_link_speed[index];
65979dc2f6e2SEric Joyner }
65989dc2f6e2SEric Joyner 
659956429daeSEric Joyner /**
66008923de59SPiotr Kubaj  * ice_fw_supports_fec_dis_auto
66018923de59SPiotr Kubaj  * @hw: pointer to the hardware structure
66028923de59SPiotr Kubaj  *
66038923de59SPiotr Kubaj  * Checks if the firmware supports FEC disable in Auto FEC mode
66048923de59SPiotr Kubaj  */
66058923de59SPiotr Kubaj bool ice_fw_supports_fec_dis_auto(struct ice_hw *hw)
66068923de59SPiotr Kubaj {
6607*9e54973fSEric Joyner 	return ice_is_fw_min_ver(hw, ICE_FW_VER_BRANCH_E810,
66088923de59SPiotr Kubaj 				 ICE_FW_FEC_DIS_AUTO_MAJ,
66098923de59SPiotr Kubaj 				 ICE_FW_FEC_DIS_AUTO_MIN,
6610*9e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_PATCH) ||
6611*9e54973fSEric Joyner 	       ice_is_fw_min_ver(hw, ICE_FW_VER_BRANCH_E82X,
6612*9e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_MAJ_E82X,
6613*9e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_MIN_E82X,
6614*9e54973fSEric Joyner 				 ICE_FW_FEC_DIS_AUTO_PATCH_E82X);
66158923de59SPiotr Kubaj }
66169c30461dSEric Joyner 
66178923de59SPiotr Kubaj /**
661856429daeSEric Joyner  * ice_is_fw_auto_drop_supported
661956429daeSEric Joyner  * @hw: pointer to the hardware structure
662056429daeSEric Joyner  *
662156429daeSEric Joyner  * Checks if the firmware supports auto drop feature
662256429daeSEric Joyner  */
662356429daeSEric Joyner bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)
662456429daeSEric Joyner {
662556429daeSEric Joyner 	if (hw->api_maj_ver >= ICE_FW_API_AUTO_DROP_MAJ &&
662656429daeSEric Joyner 	    hw->api_min_ver >= ICE_FW_API_AUTO_DROP_MIN)
662756429daeSEric Joyner 		return true;
662856429daeSEric Joyner 	return false;
662956429daeSEric Joyner }
66308923de59SPiotr Kubaj 
6631